def get_package_path_from_name(module_name, return_module_path=False): """ Returns package path from given package name :param module_name: str, name of the module we want to retrieve path of :param return_module_path: bool :return: str """ split_name = module_name.split('.') if len(split_name) > 1: sub_path = string.join(split_name[:-1], '/') else: sub_path = module_name paths = sys.path found_path = None for path in paths: test_path = path_utils.join_path(path, sub_path) if path_utils.is_dir(test_path): found_path = path if not found_path: return None test_path = found_path good_path = '' index = 0 for name in split_name: if index == len(split_name) - 1: if return_module_path: good_path = path_utils.join_path(good_path, '{}.py'.format(name)) break test_path = path_utils.join_path(test_path, name) if not path_utils.is_dir(test_path): continue files = fileio.get_files(test_path) if '__init__.py' in files: good_path = test_path else: return None index += 1 return good_path
def _on_sub_path_filter_edited(self): """ Internal callback function that is called when sub path filter text is edited """ current_text = str(self._sub_path_filter.text()).strip() if not current_text: self.set_directory(self._directory) if self._update_tree: self._tree_widget.set_directory(self._directory) text = self._filter_names.text self._on_filter_names(text) return sub_dir = path.join_path(self._directory, current_text) if not sub_dir: return if path.is_dir(sub_dir): if self._update_tree: self._tree_widget.set_directory(self._directory) text = self._filter_names.text self._on_filter_names(text) if self._emit_changes: self.subPathChanged.emit(current_text)
def remove(self): from tpDcc.libs.qt.core import qtutils if not path.is_dir(self.full_path): LOGGER.warning('Impossible to remove Project Path: {}'.format( self.full_path)) return False project_name = self.project_data.name project_path = self.project_data.path result = qtutils.get_permission( message='Are you sure you want to delete project: {}'.format( self.name), title='Deleting Project', cancel=False) if not result: return valid_delete = folder.delete_folder(folder_name=project_name, directory=project_path) if valid_delete is None: return False return True
def rename_folder(directory, name, make_unique=False): """ Renames given with a new name :param directory: str, full path to the diretory we want to rename :param name: str, new name of the folder we want to rename :param make_unique: bool, Whether to add a number to the folder name to make it unique :return: str, path of the renamed folder """ from tpDcc.libs.python import path base_name = path.get_basename(directory=directory) if base_name == name: return parent_path = path.get_dirname(directory=directory) rename_path = path.join_path(parent_path, name) if make_unique: rename_path = path.unique_path_name(directory=rename_path) if path.is_dir(rename_path) or path.is_file(rename_path): return False try: os.chmod(directory, 0o777) message = 'rename: {0} >> {1}'.format(directory, rename_path) LOGGER.info(message) os.rename(directory, rename_path) except Exception: LOGGER.error('{}'.format(traceback.format_exc())) return False return rename_path
def dropEvent(self, event): item = self.item_at(event.pos()) if item: item_path = self.get_tree_item_path_string(item) item_full_path = path.join_path(self._directory, item_path) if item_full_path and path.is_dir(item_full_path): super(FileTreeWidget, self).dropEvent(event)
def get_files(root_folder, full_path=False, recursive=False, pattern="*"): """ Returns files found in the given folder :param root_folder: str, folder we want to search files on :param full_path: bool, if true, full path to the files will be returned otherwise file names will be returned :return: list<str> """ from tpDcc.libs.python import path if not path.is_dir(root_folder): return [] # TODO: For now pattern only works in recursive searches. Fix it to work on both found = list() if recursive: for dir_path, dir_names, file_names in os.walk(root_folder): for file_name in fnmatch.filter(file_names, pattern): if full_path: found.append(os.path.join(dir_path, file_name)) else: found.append(file_name) else: files = os.listdir(root_folder) for f in files: file_path = path.join_path(root_folder, f) if path.is_file(file_path=file_path): if full_path: found.append(file_path) else: found.append(f) return found
def delete_folder(folder_name, directory=None): """ Deletes the folder by name in the given directory :param folder_name: str, name of the folder to delete :param directory: str, the directory path where the folder is stored :return: str, folder that was deleted with path """ from tpDcc.libs.python import path def delete_read_only_error(action, name, exc): """ Helper to delete read only files """ os.chmod(name, 0o777) action(name) full_path = folder_name if directory: full_path = path.join_path(directory, folder_name) if not path.is_dir(full_path): return None try: shutil.rmtree(full_path, onerror=delete_read_only_error) except Exception as exc: LOGGER.warning('Could not remove children of path "{}" | {}'.format( full_path, exc)) return full_path
def save(self, comment=None): """ Saves a new version file :param comment: str :return: str, new version file name """ from tpDcc.libs.python import folder, path if not comment: comment = '-' comment = comment.replace('\n', ' ').replace('\r', ' ') self._create_version_folder() self._create_comment_file() unique_file_name = self._increment_version_file_name() if path.is_dir(self.file_path): folder.copy_folder(directory=self.file_path, directory_destination=unique_file_name) elif path.is_file(self.file_path): copy_file(file_path=self.file_path, file_path_destination=unique_file_name) self.save_comment(comment=comment, version_file=unique_file_name) return unique_file_name
def load_python_module(module_name, directory): """ Loads a given module name located in the given directory NOTE: After loading a module you can access programmatically to all functions and attributes of the module :param module_name: str, name of the module we want to load :param directory: str, directory path where the module is located :return: mod, loaded module """ import imp from tpDcc.libs.python import path if not path.is_dir(directory): return None full_path = path.join_path(directory, module_name) if not path.is_file(full_path): return None split_name = module_name.split('.') file_path, path_name, description = imp.find_module( split_name[0], [directory]) try: module = imp.load_module(module_name, file_path, path_name, description) except Exception: file_path.close() return traceback.format_exc() finally: if file_path: file_path.close() return module
def import_python_module(module_name, directory): """ Imports the given module :param module_name: str, name of the module :param directory: str, path where the module is located :return: mod, imported module """ from tpDcc.libs.python import path, fileio if not path.is_dir(directory=directory): return module = None full_path = path.join_path(directory, module_name) if path.is_file(full_path): if directory not in sys.path: sys.path.append(directory) split_name = module_name.split('.') script_name = split_name[0] exec('import {}'.format(script_name)) exec('reload({})'.format(script_name)) module = eval(script_name) sys.path.remove(directory) return module
def copy_folder(directory, directory_destination, ignore_patterns=[]): """ Copy the given directory into a new directory :param directory: str, directory to copy with full path :param directory_destination: str, destination directory :param ignore_patterns: list<str>, extensions we want to ignore when copying folder elements If ['txt', 'py'] is given all py and text extension files will be ignored during the copy operation :return: str, destination directory """ from tpDcc.libs.python import path, osplatform if not path.is_dir(directory=directory): return if not ignore_patterns: cmd = None if osplatform.is_linux(): cmd = ['rsync', directory, directory_destination, '-azr'] elif osplatform.is_windows(): cmd = [ 'robocopy', directory.replace('/', '\\'), directory_destination.replace('/', '\\'), '/S', '/Z', '/MIR'] if cmd: proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) out, err = proc.communicate() if out: logger.error(err) else: shutil.copytree(directory, directory_destination) else: shutil.copytree(directory, directory_destination, ignore=shutil.ignore_patterns(ignore_patterns)) return directory_destination
def clean_folder(directory): """ Removes everything in the given directory :param directory: str """ from tpDcc.libs.python import path, fileio, folder base_name = path.get_basename(directory=directory) dir_name = path.get_dirname(directory=directory) if path.is_dir(directory): files = folder.get_files(directory) for f in files: fileio.delete_file(f, directory) delete_folder(base_name, dir_name) if not path.is_dir(directory): create_folder(base_name, dir_name)
def dropEvent(self, event): item = self.item_at(event.pos()) if item: item_path = self.get_tree_item_path_string(item) item_full_path = path.join_path(self._directory, item_path) if not item_full_path or not path.is_dir(item_full_path): event.ignore() else: event.accept() else: event.ignore()
def refresh(self, directories): directories = python.force_list(directories) self.clear() for diretory_found in directories: name = diretory_found if not path_utils.is_dir(diretory_found): name = 'Directory Not Valid! {}'.format(diretory_found) item = QListWidgetItem() item.setText(name) item.setSizeHint(QSize(20, 25)) self.addItem(item)
def has_versions(self): """ Returns whether the version file already has versions folder created or not :return: bool """ from tpDcc.libs.python import path version_folder = self._get_version_folder() if path.is_dir(version_folder): return True
def _on_browse(self): projects_path = self._project.full_path if self._project else None if not projects_path or not os.path.isdir(projects_path): projects_path = 'C:/' filename = qtutils.get_folder(projects_path, parent=self) if not filename: return filename = path_utils.clean_path(filename) if filename and path_utils.is_dir(filename): self._on_text_changed(filename)
def _on_directory_browsed(self, projects_path): """ Internal callback function that is triggered when the user browses a new projects path :param projects_path: str """ if not projects_path or not path.is_dir(projects_path): return self.set_projects_path(projects_path) self._update_ui()
def has_versions(self): """ Returns if the current version file has version or not :return: bool """ version_folder = self._get_version_folder() if path.is_dir(version_folder): return True return False
def create_project(self): project_full_path = self.full_path if path.is_dir(project_full_path): logger.warning( 'Project Path {} already exists! Choose another one ...'. format(project_full_path)) return folder.create_folder(name=self.name, directory=self._project_path) self._set_default_settings() return self
def get_files_and_folders(directory): """ Get files and folders found in the given directory :param directory: str, folder we want to get files and folders from :return: list<str> """ from tpDcc.libs.python import path if not path.is_dir(directory=directory): return return os.listdir(directory)
def check_folder(self, warning_text=None): """ Check if a folder is an invalid one and raise error if necessary :param warning_text: str :return: bool """ from tpDcc.libs.python import path if not path.is_dir(self.file_path): if warning_text is not None: raise NameError(str(warning_text)) return False return True
def _on_directory_browsed(self, dir): """ Set the project directory :param dir: str """ if not dir or not path.is_dir(dir): return if self._settings: self._settings.set('project_directory', dir) LOGGER.debug('Updated FactoRig Project Path: {}'.format(dir)) self._update_ui() else: self._update_ui(dir)
def _on_text_changed(self, directory): directory = str(directory) if not path_utils.is_dir(directory): return found = self._list.get_directories() if directory in found: return if found: found.insert(0, directory) else: found = [directory] self.directoryChanged.emit(found) self._list.refresh(found) if self._project: self._project.set_external_code_paths(found)
def check_path(self, warning_text=None): """ Check if a path to a file is invalid and raise error if necessary :param warning_text: str :return: bool """ from tpDcc.libs.python import path dir_name = path.get_dirname(self.file_path) if not path.is_dir(dir_name): if warning_text is not None: raise UserWarning(str(warning_text)) return False return True
def get_size(file_path, round_value=2): """ Return the size of the given directory or file path :param file_path: str :param round_value: int, value to round size to :return: int """ from tpDcc.libs.python import fileio, path size = 0 if path.is_dir(file_path): size = get_folder_size(file_path, round_value) if path.is_file(file_path): size = fileio.get_file_size(file_path, round_value) return size
def _on_create(self): project_path = self._project_line.text() project_name = self._name_line.text() if not project_path or not path.is_dir(project_path) or not project_name: LOGGER.warning('Project Path: {} or Project Name: {} are not valid!'.format(project_path, project_name)) return if self._selected_template is None: LOGGER.warning('No Template selected, please select one first ...') return new_project = self._selected_template.create_project(project_name=project_name, project_path=project_path) if new_project is not None: LOGGER.debug( 'Project {} created successfully on path {}'.format(new_project.name, new_project.path)) self._name_line.setText('') self.projectCreated.emit(new_project.name) return new_project return None
def __init__(self, name, file_path, data_path=None): super(LibraryDataFolder, self).__init__(file_path=file_path) self.settings = None new_path = path_utils.join_path(file_path, name) self.file_path = path_utils.get_dirname(new_path) self.name = path_utils.get_basename(new_path) self.data_type = None # if data_path: # tp.data_manager.add_directory(data_path) # Check if the given file path is a folder or not (and create folder if necessary) test_path = path_utils.join_path(self.file_path, self.name) is_folder = path_utils.is_dir(test_path) if is_folder: self.folder_path = test_path else: self._create_folder()
def open_browser(file_path): """ Open the file browser to the path specified :param file_path: str, filename with path :return: """ from tpDcc.libs.python import osplatform, path if not path.is_file(file_path) and not path.is_dir(file_path): return if osplatform.is_windows(): os.startfile(file_path) elif osplatform.is_linux(): try: opener = 'open' if sys.platform == 'darwin' else 'xdg-open' subprocess.call([opener, file_path]) except Exception as e: os.system('gnome-terminal --working-directory={}'.format(file_path))
def copy_file(file_path, file_path_destination): """ Copies the given file to a new given directory :param file_path: str, file to copy with full path :param file_path_destination: str, destination directory where we want to copy the file into :return: str, the new copied path """ from tpDcc.libs.python import path, osplatform osplatform.get_permission(file_path) if path.is_file(file_path): if path.is_dir(file_path_destination): file_name = path.get_basename(file_path) file_path_destination = path.join_path(file_path_destination, file_name) shutil.copy2(file_path, file_path_destination) return file_path_destination
def get_sub_folder(self, name=None): """ Returns sub folder of this data folder :param name: str, name of the sub folder :return: str """ if name: sub_folder = name else: if not self.settings: self._load_folder() sub_folder = self.settings.get('sub_folder') if self.folder_path: if not path_utils.is_dir( path_utils.join_path(self.folder_path, '.sub/{}'.format(sub_folder))): return return folder