Exemplo n.º 1
0
def call_api(url: str, *, method: str, error_msg: str, debug: bool,
             **kwargs) -> Optional[Any]:
    """
    Выполнить POST запрос
    """
    payload = form_request(method=method, **kwargs)

    if debug:
        # запомнить, что мы запросили, скрыть секреты
        if 'secret_key' in kwargs:
            kwargs['secret_key'] = '***'
        logger.debug(f'---> {method}({dict_as_args(kwargs)})')

    r = requests.post(url, json=payload)

    if r.status_code == 200:
        body = r.json()

        if 'result' in body:
            result = body['result']

            if debug:
                # запомнить, что мы получили
                logger.debug(f'<--- {method}: <' + str(result)[0:100] + '>')

            return result

        else:
            post_mortem = body['error']
    else:
        post_mortem = r.content.decode('utf-8')

    logger.critical(post_mortem)
    fail(error_msg, reason=ConnectionError)
    return None
Exemplo n.º 2
0
    def __init__(self,
                 source: Optional[Collection] = None,
                 window: int = 0,
                 sentinel: Any = object()):
        """
        Создание экземпляра. Можно задать базовую коллекцию, размер и объект для пустых слотов

        :param source: исходная коллекция элементов, на базе которой надо собрать экземпляр
        :param window: максимальное количество элементов (ширина окна вычисления)
        :param sentinel: элемент для заполнения пустых ячеек (можно добавить свой)
        """
        self._sentinel = sentinel
        self._data = []
        self._len = 0
        self._index = 0

        if source:
            # есть коллекция-прототип из которой можно взять данные
            if window:
                self.window = window
            else:
                self.window = len(source)
            self.restore()
            self.populate(source)

        elif window:
            # создаём пустую карусель
            self.window = window
            self.restore()

        else:
            fail(
                f'Для создания экземпляра {s_type(self)} необходимо либо указать длину и/или \n'
                'дать коллекцию из которой будет собран экземпляр.',
                reason=ValueError)
Exemplo n.º 3
0
    def get_instance(cls) -> T:
        """
        Получить валидный экземпляр
        """
        if not cls.__instance:
            fail(f'Класс {s_type(cls)} ещё не имеет хранимого экземпляра!',
                 reason=ValueError)

        return cls.__instance
Exemplo n.º 4
0
    def unregister(cls) -> None:
        """
        Удалить валидный экземпляр
        """
        if not cls.has_instance():
            fail(f'Класс {s_type(cls)} ещё не имеет хранимого экземпляра!',
                 reason=ValueError)

        cls.__instance = None
Exemplo n.º 5
0
    def register_force(cls, instance: T) -> None:
        """
        Добавить валидный экземпляр
        """
        if cls.__instance:
            fail(f'Класс {s_type(cls)} уже имеет хранимый экземпляр!',
                 reason=ValueError)

        cls.__instance = instance
Exemplo n.º 6
0
    def register(cls, instance: T) -> None:
        """
        Добавить валидный экземпляр
        """
        if not isinstance(instance, cls):
            fail(
                f'Класс {s_type(cls)} не добавляет посторонние типы!\n'
                'При необходимости используйте метод register_force',
                reason=ValueError)

        cls.register_force(instance)
Exemplo n.º 7
0
    def __init__(self, *args, **kwargs):
        """
        Автоматическая инициация
        """
        if args:
            fail(
                f'{s_type(self)} подразумевает создание только из именованных атрибутов',
                reason=ValueError)

        for key, value in kwargs.items():
            setattr(self, key, value)
Exemplo n.º 8
0
    def get_instance(mcs, required_cls):
        """
        Обращение от потомка за экземпляром себя
        """
        if isinstance(required_cls, type):
            if required_cls in mcs._instances:
                return mcs._instances[required_cls]
        else:
            if type(required_cls) in mcs._instances:
                return mcs._instances[type(required_cls)]

        fail(f'Метакласс {mcs} не содержит экземпляров {s_type(required_cls)}!', reason=KeyError)
Exemplo n.º 9
0
        def wrapper(*args, **kwargs) -> Any:
            """
            Враппер
            """
            iteration = 0
            while True:
                try:
                    result = func(*args, **kwargs)
                    break
                except case as exc:
                    iteration += 1

                    if verbose:
                        logger.warning(f'{exc} в функции {func.__name__}'
                                       f' (итерация {iteration})')

                    if repeats and iteration > repeats:
                        fail(exc)

                    time.sleep(delay)
Exemplo n.º 10
0
    def __setitem__(self, key: Union[int, slice], value: Any) -> None:
        """
        Записать элемент по индексу.
        Обеспечивается обычный доступ к внутреннему хранилищу, просто со смещением индекса

        :param key: ключ индексации, только int
        :param value: данные для записи (любой тип)
        """
        if not isinstance(key, int):
            fail(
                f"Тип {s_type(self)} поддерживает работу только с индексами типа int!",
                reason=IndexError)

        if not self._len:
            fail(
                f'Попытка присвоить элемент по индексу {key} в пустой объект {s_type(self)}',
                reason=IndexError)

        self._data[self.get_real_index(key)] = value
        return
Exemplo n.º 11
0
    def __getitem__(self, item: Union[int, slice]) -> Any:
        """
        Обратиться к элементу по индексу.
        Обеспечивается обычный доступ к внутреннему хранилищу, просто со смещением индекса

        :param item: ключ индексации
        :return: содержимое внутреннего хранилища
        """
        if isinstance(item, int):
            if not self._len:
                fail(
                    f'Попытка получить элемент из пустого объекта {s_type(self)}',
                    reason=IndexError)

            result = self._data[self.get_real_index(item)]

            if result is self._sentinel:
                fail(
                    f'В экземпляре {s_type(self)} нет элемента с индексом {item!r}',
                    reason=IndexError)

            return result

        if isinstance(item, slice):
            return self.get_contents()[item]

        fail(
            f"Тип {s_type(self)} поддерживает работу только с индексами int и slice!",
            reason=IndexError)
Exemplo n.º 12
0
    def extract_json(cls, config_name: str, path: str) -> dict:
        """
        Вытащить данные из JSON файла
        """
        if not os.path.exists(path):
            fail(f'Не найден файл конфигурации: "{path}"',
                 reason=FileNotFoundError)

        with open(path, mode='r', encoding='utf-8') as file:
            data = json.load(file)

        if config_name not in data:
            fail(f'В конфиге не представлен раздел "{config_name}"',
                 reason=KeyError)

        config = {**data.get(cls.default_config_name, {}), **data[config_name]}

        if config:
            return config

        fail(
            f'Не удалось загрузить конфигурацию "{config_name}" из файла: "{path}"',
            reason=KeyError)