def saveas(self, filepath: PathLike) -> None: """Save the ZipFile to a file. Args: filepath: String or :term:`path-like object`, that represents the name of a ZipFile. """ # Remove duplicates from ZipFile self._remove_duplicates() # Mark plattform, which created the files as Windows # to avoid inference of wrong Unix permissions for zinfo in self._file.infolist(): zinfo.create_system = 0 # Close ZipArchive (to allow to read the buffer) self._file.close() # Read buffer and write ZipFile if not isinstance(self._buffer, io.BytesIO): raise TypeError("buffer has not been initialized") path = env.expand(filepath) with open(path, 'wb') as file: file.write(self._buffer.getvalue()) # Close buffer self._buffer.close() # Reload saved workpace from file self.load(path, pwd=self._pwd)
def __init__( self, workspace: OptPathLike = None, basedir: OptPathLike = None, pwd: OptBytes = None) -> None: super().__init__() # Initialize Attribute Container # Initialize instance variables with default values self.config = self._default_config.copy() self._file = ws.Workspace() self._logger = log.Logger() self.paths = [env.expand(path) for path in self._default_paths] # Bind session to workspace self._set_attr_group_parent(self._file) # Load session configuration from file if env.is_file(self._config_file_path): self._load_config() # Load workspace from file filepath: OptPath = None if workspace and isinstance(workspace, (Path, str)): filepath = Path(workspace) elif self.config.get('restore_on_startup'): cfg_path = self.config.get('path') if isinstance(cfg_path, (Path, str)): filepath = Path(cfg_path) if isinstance(filepath, Path): self.load(workspace=filepath, basedir=basedir, pwd=pwd)
def append(self, source: PathLike, target: OptPathLike = None) -> bool: """Append file to the ZipFile. Args: source: String or :term:`path-like object`, that points to a valid file in the directory structure if the system. If the file does not exist, a FileNotFoundError is raised. If the filepath points to a directory, a IsADirectoryError is raised. target: String or :term:`path-like object`, that points to a valid directory in the directory structure of the ZipFile. By default the root directory is used. If the directory does not exist, a FileNotFoundError is raised. If the target directory already contains a file, which name equals the filename of the source, a FileExistsError is raised. Returns: Boolean value which is True if the file has been appended. """ # Check source file src_file = env.expand(source) if not src_file.exists(): raise FileNotFoundError(f"file '{src_file}' does not exist") if src_file.is_dir(): raise IsADirectoryError(f"'{src_file}' is a directory not a file") # Check target directory if target: tgt_dir = PurePath(target).as_posix() + '/' if not self._locate(tgt_dir): raise FileNotFoundError( f"directory '{tgt_dir}' does not exist") else: tgt_dir = '.' tgt_file = Path(tgt_dir, src_file.name) if self._locate(tgt_file): raise FileExistsError( f"directory '{tgt_dir}' already contains a file " f"with name '{src_file.name}'") # Create ZipInfo entry from source file filename = PurePath(tgt_file).as_posix() date_time = time.localtime(src_file.stat().st_mtime)[:6] zinfo = ZipInfo(filename=filename, date_time=date_time) # type: ignore # Copy file to archive with src_file.open('rb') as src: data = src.read() # TODO ([email protected]): The zipfile standard module currently # does not support encryption in write mode. See: # https://docs.python.org/3/library/zipfile.html # When support is provided, the below line shall be replaced by: # self._file.writestr(zinfo, data, pwd=pwd) self._file.writestr(zinfo, data) return True
def _locate_logfile( self, filepath: PathLike = _default_file) -> OptPath: # Get valid logfile from filepath if isinstance(filepath, (str, Path)): logfile = env.expand(filepath) if env.touch(logfile): return logfile # Get temporary logfile logfile = env.get_temp_file(suffix='log') if env.touch(logfile): warnings.warn( f"logfile '{filepath}' is not valid: " f"using temporary logfile '{logfile}'") return logfile return None
def _set_path(self, path: PathLike) -> bool: """Set filepath. Path to a file containing or referencing the resource. Returns: Boolean value which is True on success, else False. """ if not isinstance(path, (str, tuple, Path)): raise TypeError("attribute 'path' is required to be path-like" f", not '{type(path)}'") self._config['path'] = env.expand(path) return True
def _locate_path( self, workspace: OptPathLike = None, basedir: OptPathLike = None) -> OptPath: if not workspace: return None if not basedir: # If workspace is a fully qualified file path in the directory # structure of the system, ignore the 'paths' list if env.is_file(workspace): return env.expand(workspace) # Use the 'paths' list to find a workspace for path in self.paths: candidate = Path(path, workspace) if candidate.is_file(): return candidate raise FileNotFoundError( f"file {workspace} does not exist") return Path(basedir, workspace)
def _get_path_expand(self, *args, check: bool = False, create: bool = False): """Get expanded path. Args: path (string or tuple or list): check (bool): create (bool): Returns: String containing expanded path. """ path = str(env.join_path(args)) # expand rian environment variables base = self._get_base() udict = { 'workspace': self._get_workspace() or 'none', 'base': self._get_base() or 'none', 'basepath': str(env.join_path(self._config['default']['basepath'][base])) } for key, val in self._config['default']['basepath'].items(): udict[key] = str(env.join_path(val)) for key, val in self._config['current']['path'].items(): udict[key] = str(env.join_path(val)) path = str(env.expand(path, udict=udict)) # (optional) create directory if create: env.mkdir(path) # (optional) check path if check and not os.path.exists(path): return None return path
def load(self, filepath: PathLike, pwd: OptBytes = None) -> None: """Load Workspace from file. Args: filepath: String or :term:`path-like object`, that points to a valid ZipFile file. If the filepath points to a valid ZipFile, then the class instance is initialized with a memory copy of the file. If the given file, however, does not exist or isn't a valid ZipFile respectively one of the errors FileNotFoundError or BadZipFile is raised. pwd: Bytes representing password of ZipFile. """ # Initialize instance Variables, Buffer and buffered ZipFile self._changed = False self._path = env.expand(filepath) self._pwd = pwd self._buffer = io.BytesIO() self._file = ZipFile(self._buffer, mode='w') if not self._path: raise ValueError('') # TODO # Copy contents from ZipFile to buffered ZipFile with warnings.catch_warnings(): warnings.simplefilter("ignore", UserWarning) try: with ZipFile(self._path, mode='r') as fh: for zinfo in fh.infolist(): data = fh.read(zinfo, pwd=pwd) # TODO ([email protected]): The zipfile standard # module currently does not support encryption in write # mode of new ZipFiles. See: # https://docs.python.org/3/library/zipfile.html # When support is provided, the below line for writing # files shall be replaced by: # self._file.writestr(zinfo, data, pwd=pwd) self._file.writestr(zinfo, data) except FileNotFoundError as err: raise FileNotFoundError( f"file '{self.path}' does not exist") from err except BadZipFile as err: raise BadZipFile( f"file '{self.path}' is not a valid ZIP file") from err
def as_path(text: str, expand: bool = True) -> pathlib.Path: """Convert text into list. Args: text: String representing a path. expand: Boolen value, whoch determines, if variables in environmental path variables are expanded. Returns: Value of the text as Path. """ # Check types of Arguments check.has_type("first argument 'text'", text, str) check.has_type("'expand'", expand, bool) if expand: return env.expand(text) return pathlib.Path(text)
def saveas(self, filepath: PathLike) -> None: """Save the workspace to a file. Args: filepath: String or :term:`path-like object`, that represents the name of a workspace file. """ path = env.expand(filepath) # Update datetime self.date = datetime.datetime.now() # Update 'workspace.ini' with self.open(self._config_file, mode='w') as file: ini.save( { 'dc': self._get_attr_values(group='dc'), 'hooks': self._get_attr_values(category='hooks') }, file) super().saveas(filepath)
def _open_path(self, path: PathLike, *args: Any, **kwds: Any) -> FileLike: # Open file handler from given file path file = open(env.expand(path), *args, **kwds) # Store weak reference of file handler self._children.append(weakref.proxy(file)) return file
def test_expand(self) -> None: udict = {'var1': 'a/%var2%', 'var2': 'b'} val = env.expand('%var1%/c', 'd', udict=udict) self.assertEqual(val, pathlib.Path('a/b/c/d'))