def cwd(self, remote_path): if not remote_path or not isinstance(remote_path, str): raise FatalError('A valid path is required') try: self.ftp.cwd(remote_path) self.remote_path_prefix = self.ftp.pwd() except ftp_error as e: raise FatalError('Cannot change path to dir: {}'.format(remote_path)) from e
def rmdir(self, dirname): if not dirname or not isinstance(dirname, str) or '/' in dirname: raise FatalError('dirname: {} is not valid'.format(dirname)) try: self.ftp.rmd(dirname) except ftp_error as e: raise FatalError('Cannot delete remote dir: {} in path: {}'.format(dirname, self.remote_path_prefix)) \ from e
def _concat_prefix_path(cls, prefix, path): if not path or not isinstance(path, str): raise FatalError('path: {} is not valid'.format(path)) if os.path.isabs(path): if not path.startswith(prefix): raise FatalError('remote path must be under {}'.format(prefix)) full_path = path else: full_path = os.path.abspath(os.path.join(prefix, path)) return full_path
def mkdir(self, dirname, auto_cd=True): if not dirname or not isinstance(dirname, str): raise FatalError('relative dirname: {} is not valid'.format(dirname)) # dir_path = '{}/{}'.format(self.remote_path_prefix, dirname) dir_path = dirname try: self.ftp.mkd(dir_path) if auto_cd: self.cwd(dir_path) except ftp_error as e: raise FatalError('Cannot create dir: {}'.format(dir_path)) from e
def mdelete(self, filenames): if not filenames: return for filename in filenames: if not filename or not isinstance(filename, str): raise FatalError('filename: {} is not valid'.format(filename)) cur_file = None try: for filename in filenames: cur_file = filename self.ftp.delete(filename) except ftp_error as e: raise FatalError('Cannot delete remote file: {} in path: {}'.format(cur_file, self.remote_path_prefix)) \ from e
def mget(self, filenames): if not filenames: return for filename in filenames: if not filename or not isinstance(filename, str): raise FatalError('filename: {} is not valid'.format(filename)) cur_file = None try: for filename in filenames: cur_file = filename with open(os.path.join(self.local_path, filename), 'wb') as fp: self.ftp.retrbinary('RETR {}'.format(filename), fp.write) except ftp_error as e: raise FatalError('Cannot retrieve file: {} to location: {}'.format(cur_file, self.local_path)) from e
def mput(self, filenames): if not filenames: return for filename in filenames: if not filename or not isinstance(filename, str): raise FatalError('filename: {} is not valid'.format(filename)) cur_file = None try: for filename in filenames: cur_file = filename # https://stackoverflow.com/questions/2911754/how-to-upload-binary-file-with-ftplib-in-python with open(os.path.join(self.local_path, filename), 'rb') as fp: self.ftp.storbinary('STOR {}'.format(filename), fp) except ftp_error as e: raise FatalError('Cannot retrieve file: {} to location: {}'.format(cur_file, self.local_path)) from e
def lcd(self, local_path=None): if local_path is None: return self.get_local_dir() if not local_path or not isinstance(local_path, str): raise FatalError('A valid path is required') if os.path.isabs(local_path): new_path = os.path.abspath(local_path) else: new_path = os.path.abspath(os.path.join(self.get_local_dir(), local_path)) if not os.path.exists(new_path) or not os.path.isdir(new_path): raise FatalError('path {} does not exist or is not a directory'.format(new_path)) self.set_local_dir(new_path)
def delete(self, filename): file_path = self._concat_prefix_path(self.remote_path_prefix, filename) try: os.remove(file_path) except OSError as e: raise FatalError('Can not remove file: {}'.format(file_path)) from e
def rmdir(self, dirname): dir_path = self._concat_prefix_path(self.remote_path_prefix, dirname) try: os.rmdir(dir_path) # todo: fails is dir is not empty... Keep like this? except OSError as e: raise FatalError('Can not remove dir: {}'.format(dir_path)) from e
def cwd(self, remote_path): new_path = self._concat_prefix_path(self.remote_path_prefix, remote_path) if not os.path.exists(new_path) or not os.path.isdir(new_path): raise FatalError('path {} does not exist or is not a directory'.format(new_path)) self.remote_path_prefix = new_path
def put(self, filename): src = self._concat_prefix_path(self.local_path, filename) dst = self._concat_prefix_path(self.remote_path_prefix, filename) try: shutil.copy2(src, dst, follow_symlinks=False) except OSError as e: raise FatalError('Can not copy file {} to {}'.format(src, dst)) from e
def mkdir(self, dirname, auto_cd=True): dir_path = self._concat_prefix_path(self.remote_path_prefix, dirname) try: os.mkdir(dir_path) if auto_cd: self.remote_path_prefix = dir_path except OSError as e: raise FatalError('Cannot create dir: {}'.format(dir_path)) from e
def ls(self, argument=None): if not argument: path = self.remote_path_prefix else: path = self._concat_prefix_path(self.remote_path_prefix, argument) try: return os.listdir(path) except OSError as e: raise FatalError('Cannot list dropbox path dir: {}'.format(path)) from e
def __getitem__(self, key): key = str(key) if key in self.data: return self.data[key] if key in self._parser['DEFAULT']: # get value from configfile if not self.can_override(key): raise FatalError( 'Forbidden: file config parameter: {} cannot override settings' .format(key)) value = self._parser['DEFAULT'][key] # all loaded as str initially type_name = self.resolve_type(key) try: # python expression evaluation if value and (type_name == 'python_expression' or self.has_py_prefix(value)): value = eval(self.strip_py_prefix(value), {'__builtins__': {}}, {}) # type conversions if value and type_name == 'int': value = self._parser['DEFAULT'].getint(key) elif value and type_name == 'float': value = self._parser['DEFAULT'].getfloat(key) elif value and type_name == 'bool': value = self._parser['DEFAULT'].getboolean(key) except Exception as e: raise FatalError( 'Error evaluating config value: {}'.format(value)) from e elif self.in_settings(key): # or get value from settings value = self.value_from_settings(key) else: raise KeyError('config key {} not found'.format(key)) self.save_key_value_recursive(key, value) return value
def ls(self, argument=None): if argument: # todo: not necessary to use absolute paths as the ftp server keeps the working dir # path = argument if argument.startswith('/') else '{}/{}'.format(self.remote_path_prefix, argument) path = argument else: path = self.remote_path_prefix try: return self.ftp.nlst(path) except ftp_error as e: raise FatalError('Cannot list remote path: {}'.format(path)) from e
def connect(self): ftp_clazz = FTP_TLS if self.use_tls else FTP try: ftp = ftp_clazz(host=self.host) ftp.login(self.user, self.passwd) if self.use_tls: ftp.prot_p() except ftp_error as e: raise FatalError('Cannot connect and login to ftp server {}'.format(self.host)) from e self.ftp = ftp # if remote path does not exist create it, position ftp inside the path in any case self._makedirs(self.remote_path_prefix)
def init_config(config_path=None): """Must be called once on app initialization""" global _config_path, _config_parser, _config _config_path = config_path _config_parser = configparser.ConfigParser() try: if config_path is not None: assert os.path.isfile( config_path), 'Config path {} is not a valid file path'.format( config_path) _config_parser.read(_config_path) except (AssertionError, OSError, configparser.Error) as e: # get_logger().exception('Could not parse App config file: %s. Details: ', config_path) raise FatalError( 'Failed to load config file: {}'.format(config_path)) from e else: _config = _Config() _config.reset_config_parser(_config_parser)
def __init__(self, local_path=None, remote_path=None, **kwargs): if not local_path or not remote_path: raise FatalError('{} kwargs: local_path and remote_path required'.format(self.__class__.__name__))
def get_backend_class(classname_or_alias): try: clazz = _registered_alias.get(classname_or_alias) or _registered_clazz[classname_or_alias] except KeyError as e: raise FatalError('Could not instantiate registered backend') from e return clazz
def _makedirs(self, remote_path): try: self._makedirs_aux(self.ftp, remote_path) except ftp_error as e: raise FatalError('Cannot create remote path: {}'.format(remote_path)) from e