def rename_file(name, directory, new_name, new_version=False): """ Renames the give nfile in the directory with a new name :param name: :param directory: :param new_name: :param new_version: :return: """ from tpDcc.libs.python import path full_path = path.join_path(directory, name) if not path.is_file(full_path): return full_path new_full_path = path.join_path(directory, new_name) if path.is_file(new_full_path): print('A file named {} already exists in the directory: {}'.format( new_name, directory)) return full_path os.chmod(full_path, 0o777) os.rename(full_path, new_full_path) return new_full_path
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 create_project_from_data(cls, project_data_path): """ Creates a new project using a project data JSON file :param project_data_path: str, path where project JSON data file is located :return: Project """ if project_data_path is None or not path.is_file(project_data_path): LOGGER.warning('Project Data Path {} is not valid!'.format(project_data_path)) return None project_data = settings.JSONSettings() project_options = settings.JSONSettings() project_dir = path.get_dirname(project_data_path) project_name = path.get_basename(project_data_path) project_data.set_directory(project_dir, project_name) project_options.set_directory(project_dir, 'options.json') project_name = project_data.get('name') project_path = path.get_dirname(path.get_dirname(project_data_path)) project_image = project_data.get('image') LOGGER.debug('New Project found [{}]: {}'.format(project_name, project_path)) project_data = core_project.ProjectData( name=project_name, project_path=project_path, settings=project_data, options=project_options) new_project = cls(project_data=project_data) if project_image: new_project.set_image(project_image) return new_project
def open(self, file_path=None): if not dcc.is_maya(): LOGGER.warning('Maya data must be accessed from within Maya!') return open_file = None if file_path: open_file = file_path if not open_file: file_path = self.get_file() if not path.is_file(file_path): LOGGER.warning('Could not open file: {}'.format(file_path)) return open_file = file_path helpers.display_info('Opening: {}'.format(open_file)) try: maya.cmds.file(open_file, f=True, o=True, iv=True, pr=True) except Exception: LOGGER.error('Impossible to open Maya file: {} | {}'.format(open_file, traceback.format_exc())) self._after_open() top_transforms = scene.get_top_dag_nodes(exclude_cameras=True) return top_transforms
def create_item(self, name=None): """ Creates a new item (folder) inside the selected item :param name: str, name of the new item """ current_item = self._current_item if current_item: item_path = self.get_tree_item_path_string(self._current_item) item_path = path.join_path(self._directory, item_path) if path.is_file(item_path): item_path = path.get_dirname(item_path) current_item = self._current_item.parent() if not current_item: item_path = self._directory if not name: name = self.NEW_ITEM_NAME folder.create_folder(name=name, directory=item_path) if current_item: self._add_sub_items(current_item) self.setItemExpanded(current_item, True) else: self.refresh()
def import_data(self, file_path=''): """ Loads data object :param file_path: str, file path of file to load """ if not dcc.is_maya(): LOGGER.warning('Data must be accessed from within Maya!') return if file_path: import_file = file_path else: import_file = self.get_file() if not path.is_file(import_file): LOGGER.warning('Impossible to import invalid data file: {}'.format(file_path)) return track = scene.TrackNodes() track.load('transform') scene.import_scene(import_file, do_save=False) self._after_open() transforms = track.get_delta() top_transforms = scene.get_top_dag_nodes_in_list(transforms) return top_transforms
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 delete_file(name, directory=None, show_warning=True): """ Delete the file by name in the directory :param name: str, name of the file to delete :param directory: str, the directory where the file is stored :param show_warning: bool :return: str, file path that was deleted """ from tpDcc.libs.python import path, osplatform if not directory: full_path = name else: full_path = path.join_path(directory, name) if not path.is_file(full_path): if show_warning: print('File "{}" was not deleted.'.format(full_path)) return full_path try: osplatform.get_permission(full_path) except Exception: pass try: os.remove(full_path) except Exception: pass return full_path
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 get_version_data(self, version_number): """ Returns the data (comment and user) of the given version :param version_number: int :return: tuple(str, str) """ comment_path = self._get_comment_path() if not comment_path: return None, None if not path.is_file(comment_path): return None, None version_data = jsonio.read_file(comment_path) if not version_data: return None, None for version_dict in version_data: version = version_dict.get('version', None) comment = version_dict.get('comment', '') user = version_dict.get('user', '') if version == str(version_number): return comment, user return None, None
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 get_version_data(self, version_number): """ Returns the data (comment and user) of the given version :param version_number: int :return: tuple(str, str) """ comment_path = self._get_comment_path() if not comment_path: return None, None if path.is_file(comment_path): read = fileio.FileReader(comment_path) lines = read.read() version = None comment = None user = None for line in lines: start_index = line.find('"') if start_index > -1: end_index = line.find('";') sub_part = line[start_index + 1:end_index] sub_part = sub_part.replace('"', '\\"') line = line[:start_index + 1] + sub_part + line[end_index:] # Get version, comment and user variables by executing the line try: exec(line) except Exception: pass if version == version_number: return comment, user return None, None
def _import_mesh_obj(self, data_path): """ Internal function that imports mesh object stored in given path :param data_path: str, path that contains already exported mesh object :return: str, name of the imported mesh """ dependencies = self.get_dependencies(data_path) mesh_path = dependencies.get('geo_file', None) if not mesh_path or not os.path.isfile(mesh_path): mesh_path = path_utils.join_path(data_path, 'mesh.obj') if not path_utils.is_file(mesh_path): return None nodes = dcc.client().list_nodes(node_type='mesh', full_path=False) dcc.client().import_file(mesh_path, import_type='OBJ', ignore_version=True, options='mo=1') current_nodes = dcc.client().list_nodes(node_type='mesh', full_path=False) delta = list(set(current_nodes).difference(nodes)) if delta: delta = dcc.client().node_parent(delta, full_path=True) return delta
def copy(source, target, description=''): """ Copies given file or files and creates a new version of the file with the given description :param source: str, source file or folder we want to copy :param target: str, destination file or folder we want to copy into :param description: str, description of the new version """ is_source_a_file = path_utils.is_file(source) if is_source_a_file: copied_path = fileio.copy_file(source, target) else: if not path_utils.exists(source): LOGGER.info( 'Nothing to copy: {}\t\tData was probably created but not saved yet.' .format(path_utils.get_dirname(is_source_a_file))) return if path_utils.exists(target): folder.delete_folder(target) copied_path = folder.copy_folder(source, target) if not copied_path: LOGGER.warning('Error copying {}\t to\t{}'.format(source, target)) return if copied_path > -1: LOGGER.info('Finished copying {} from {} to {}'.format( description, source, target)) version_file = version.VersionFile(copied_path) version_file.save('Copied from {}'.format(source))
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 _has_changed(self): if self._file_path: if path_utils.is_file(self._file_path): last_modified = fileio.get_last_modified_date(self._file_path) if last_modified != self._last_modified: return True return False
def has_default(self): if not self._version_name: return file_name = self._default_version_file_name() if path.is_file(file_name): return True return False
def _get_version_folder(self): from tpDcc.libs.python import path if path.is_file(self.file_path): dir_name = path.get_dirname(self.file_path) version_path = path.join_path(dir_name, self._version_folder_name) else: version_path = path.join_path(self.file_path, self._version_folder_name) return version_path
def _get_version_folder(self): if path.is_file(self._file_path): version_dir = path.get_dirname(self._file_path) version_path = path.join_path(version_dir, self._version_folder_name) else: version_path = path.join_path(self._file_path, self._version_folder_name) return version_path
def delete_version(self, version_number): """ Deletes specific version file :param version_number: int """ version_path = self.get_version_path(version_number) if path.is_file(version_path): fileio.delete_file(version_path) else: folder.delete_folder(path)
def _get_influences(self, folder_path): influence_dict = dict() info_file = path_utils.join_path(folder_path, 'influence.info') if not path_utils.is_file(info_file): return influence_dict info_lines = fileio.get_file_lines(info_file) for line in info_lines: if not line: continue line_dict = eval(line) influence_dict.update(line_dict) return influence_dict
def check_file(self, warning_text=None): """ Check if a file 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_file(self.file_path): if warning_text is not None: raise UserWarning(str(warning_text)) return False return True
def _has_json_file(self): """ Checks if the JSON file where settings should be stored exists or not :return: bool """ if not self.file_path: return False settings_directory = path.get_dirname(self.file_path) name = path.get_basename(self.file_path, with_extension=False) file_path = path.join_path(settings_directory, name + '.json') if path.is_file(file_path): return True return False
def clean_student_license(self, file_path=''): if not dcc.is_maya(): LOGGER.warning('Data must be accessed from within Maya!') return if file_path: file_to_clean = file_path else: file_to_clean = self.get_file() if not path.is_file(file_to_clean): LOGGER.warning('Impossible to reference invalid data file: {}'.format(file_path)) return changed = helpers.clean_student_line(file_to_clean) if changed: LOGGER.debug('Cleaned student license from file: {}'.format(file_to_clean))
def set_directory(self, directory, filename='settings.json'): self.directory = directory # Check that given file name is a valid JSON file if not filename.endswith('.json'): old = path.join_path(directory, filename) if path.is_file(old): self.file_path = old self._read() return self.file_path = fileio.create_file(filename=filename, directory=directory) self._read() return self.file_path
def _get_influences(self, folder_path): """ Internal function that returns a dictionary containing influences data from influence files contained in the given directory :param folder_path: str, path that contains influence file :return: dict, influence data """ influence_dict = dict() files = fileio.get_files(folder_path) dependencies = self.get_dependencies(folder_path) or dict() info_file = dependencies.get('info_file', None) if not info_file or not os.path.isfile(info_file): if not files: return influence_dict info_file = path_utils.join_path(folder_path, 'influence.info') if not path_utils.is_file(info_file): return influence_dict info_lines = fileio.get_file_lines(info_file) for line in info_lines: if not line: continue line_dict = eval(line) influence_dict.update(line_dict) weight_files = python.force_list(dependencies.get('weight', list())) if not weight_files: for influence in files: if not influence.endswith( '.weights') or influence == 'influence.info': continue weight_files.append( path_utils.join_path(folder_path, influence)) for weight_file in weight_files: read_thread = ReadWeightFileThread() try: influence_dict = read_thread.run(influence_dict, weight_file) except Exception as exc: logger.error( 'Errors with influence "{}" while reading weight file: "{}" | {}' .format(weight_file, info_file, exc)) return influence_dict
def _on_set_project_image(self): """ Internal callback function that is called when project image is set """ image_file = dcc.select_file_dialog(title='Select Project Image File', pattern="PNG Files (*.png)") if image_file is None or not path.is_file(image_file): LOGGER.warning( 'Selected Image "{}" is not valid!'.format(image_file)) return valid_change = self._project_data.set_project_image(image_file) if valid_change: self.projectImageChanged.emit(image_file)
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 _get_json_file(self): """ Internal function that returns JSON file where settings are stored :return: str """ if not self.file_path: return settings_directory = path.get_dirname(self.file_path) name = path.get_basename(self.file_path, with_extension=False) file_path = fileio.create_file(name + '.json', settings_directory) if not file_path: test_path = path.join_path(settings_directory, name + '.json') if path.is_file(test_path): file_path = test_path return file_path
def get_folder_data_instance(self): """ Returns the data instance for this data Depending on the data type this folder contains a differnet object is created :return: variant """ if not self.settings: self._load_folder() if not self.name: return data_type = self.settings.get('data_type') if not data_type: data_type = self.data_type if data_type is None: test_file = os.path.join( self.folder_path, '{}.{}'.format(self.name, scripts.ScriptExtensions.Python)) if path_utils.is_file(test_file): data_type = scripts.ScriptTypes.Python self.settings.set('data_type', data_type) if not data_type: LOGGER.warning( 'Impossible to instantiate Data Folder because given Data Type: {} is not valid!' .format(data_type)) return data_manager = self.get_manager() if not data_manager: LOGGER.warning( 'Impossible to instantiate Data Folder because LibraryManager is not defined!' ) return data_inst = data_manager.get_type_instance(data_type) if data_inst: data_inst.set_directory(self.folder_path) data_inst.set_name(self.name) return data_inst