Пример #1
0
def example_1():
    def key_error_handler(*args, **kwargs):
        print 'KeyError handler'
        print args, kwargs

    with ErrorManager.for_KeyError(handler=key_error_handler):
        d = {}
        d['fake_item']
Пример #2
0
def example_3():
    def success_handler(*args, **kwargs):
        print 'success handler'
        print args, kwargs

    with ErrorManager.for_all(on_success=success_handler):
        d = {'item': 0}
        d['item']
Пример #3
0
def example_2():
    def default_error_handler(*args, **kwargs):
        print 'defaul handler'
        print args, kwargs

    with ErrorManager.for_all(on_default=default_error_handler):
        d = {}
        d['fake_item']
Пример #4
0
 def __init__(self, orchestrator, instance_config):
     # The Orchestrator object this manager belongs to
     self._orchestrator = orchestrator
     # The global config of the orchestrator
     self._config = orchestrator.config
     # ManagerConfig for this instance
     self._instance_config = instance_config
     # Named used for display/system purposes
     self._name = '{}{:03}'.format(self.key, instance_config.id)
     # Used to track errors, warnings and info messages in the client and the error status.
     self._error_manager = ErrorManager()
     # Set by children when they grab a peer_port
     self._peer_port = None
     # Registry for the periodic tasks
     self._periodic_tasks = []
     # Current instance of SessionStats, as last obtained from the client
     self._session_stats = None
     # Has the client been fully initialized (all initial data loaded)
     self._initialized = False
     # Initialization time from launch in seconds
     self._initialize_time_seconds = None
     # When the instance was launched
     self._launch_datetime = None
Пример #5
0
class Manager(ABC):
    key = None
    config_model = None

    def __init__(self, orchestrator, instance_config):
        # The Orchestrator object this manager belongs to
        self._orchestrator = orchestrator
        # The global config of the orchestrator
        self._config = orchestrator.config
        # ManagerConfig for this instance
        self._instance_config = instance_config
        # Named used for display/system purposes
        self._name = '{}{:03}'.format(self.key, instance_config.id)
        # Used to track errors, warnings and info messages in the client and the error status.
        self._error_manager = ErrorManager()
        # Set by children when they grab a peer_port
        self._peer_port = None
        # Registry for the periodic tasks
        self._periodic_tasks = []
        # Current instance of SessionStats, as last obtained from the client
        self._session_stats = None
        # Has the client been fully initialized (all initial data loaded)
        self._initialized = False
        # Initialization time from launch in seconds
        self._initialize_time_seconds = None
        # When the instance was launched
        self._launch_datetime = None

    @property
    def initialized(self):
        return self._initialized

    @property
    def name(self):
        return self._name

    @property
    def config(self):
        return self._config

    @property
    def instance_config(self):
        return self._instance_config

    @property
    def session_stats(self):
        return self._session_stats

    @property
    @abstractmethod
    def peer_port(self):
        pass

    @abstractmethod
    async def force_reannounce(self, info_hash):
        pass

    @abstractmethod
    async def force_recheck(self, info_hash):
        pass

    @abstractmethod
    async def move_data(self, info_hash, download_path):
        pass

    @abstractmethod
    async def pause_torrent(self, info_hash):
        pass

    @abstractmethod
    async def resume_torrent(self, info_hash):
        pass

    @abstractmethod
    async def rename_torrent(self, info_hash, name):
        pass

    @abstractmethod
    def launch(self):
        logger.info('Launching {}', self._name)
        self._launch_datetime = timezone_now()

    @abstractmethod
    async def shutdown(self):
        pass

    @abstractmethod
    def get_info_dict(self):
        return {
            'type':
            self.key,
            'name':
            self._name,
            'peer_port':
            self.peer_port,
            'config':
            self.instance_config.to_dict(),
            'initialized':
            self._initialized,
            'status':
            self._error_manager.status,
            'errors':
            self._error_manager.to_dict(),
            'session_stats':
            self._session_stats.to_dict() if self._session_stats else None,
        }

    @abstractmethod
    def get_debug_dict(self):
        data = self.get_info_dict()
        data.update({
            'initialize_time_seconds': self._initialize_time_seconds,
        })
        return data

    @abstractmethod
    async def add_torrent(self, torrent, download_path, name):
        pass

    @abstractmethod
    async def remove_torrent(self, info_hash):
        pass

    async def _run_periodic_task_if_needed(self, current_time, task):
        start = time.time()
        ran = await task.run_if_needed(current_time)
        if ran:
            logger.debug('{}.{} took {:.3f}', self._name, task.fn.__name__,
                         time.time() - start)
        return ran

    async def _run_periodic_tasks(self):
        current_time = time.time()
        for task in self._periodic_tasks:
            try:
                ran = await self._run_periodic_task_if_needed(
                    current_time, task)
                if ran:
                    self._error_manager.clear_error(task.fn.__name__)
            except CancelledError:
                raise
            except Exception:
                message = 'Periodic task {} running every {}s crashed'.format(
                    task.fn.__name__, task.interval_seconds)
                self._error_manager.add_error(severity=Severity.ERROR,
                                              key=task.fn.__name__,
                                              message=message,
                                              traceback=traceback.format_exc())
                logger.exception(message)

    def _can_clean_directory(self, directory):
        items = os.listdir(directory)
        if self._config.clean_torrent_file_on_remove:
            return all(
                f.lower().endswith('.torrent') or f == 'ReleaseInfo2.txt'
                for f in items)
        else:
            return len(items) == 0

    def clean_torrent_directories(self, download_path, torrent_name):
        try:
            if not self._config.clean_directories_on_remove:
                logger.debug(
                    'Directory clean on remove is disabled in config.')
                return
            start_dir = os.path.join(download_path, torrent_name)
            if not os.path.isdir(start_dir):
                start_dir = download_path
                if not os.path.isdir(start_dir):
                    logger.debug('Directory for {}/{} not found.'.format(
                        download_path, torrent_name))
                    return
            while self._can_clean_directory(start_dir):
                logger.info(
                    'Removing cleanable directory {}.'.format(start_dir))
                shutil.rmtree(start_dir)
                start_dir = os.path.dirname(start_dir)
        except Exception as exc:
            self._error_manager.add_error(
                Severity.ERROR,
                'clean_torrent_directories',
                'Unable to clean torrent directories for {}/{}.'.format(
                    download_path, torrent_name),
                traceback.format_exc(),
            )