Регистрация пространства имен, созданного до app.run - PullRequest
0 голосов
/ 21 февраля 2020

Я хочу создать службу отдыха с помощью swagger-ui, которая создает новые экземпляры программного обеспечения, назовем его A. В основном, есть:

  1. create / destroy - instance / cluster
  2. установка / удаление
  3. запуск / остановка

Это операции, которые я хочу поддерживать. Чтобы сделать вещи более интересными, я хочу разрешить запускать все эти операции в разных версиях A, если только пользователь не предоставляет сопоставление для базовых команд. Давайте рассмотрим простой пример.

Application: A
Version: 1.0
Setup: setup -a target
Uninstall: uninstall --verify

Application: A
Version: 2.0
Setup: setup -u user -a target
Uninstall: uninstall

Выше представлены две разные версии одного и того же приложения, и хотя программа установки представила новый аргумент -u в 2.0, при удалении был удален обязательный параметр --verify. Как я справляюсь с этим, я создал файл схемы (yaml), который для каждой команды определяет аргументы, что требуется, что необязательно: флаг, строка или файл или что-то еще. Я читаю этот файл схемы и сопоставляю его с объектом, который затем создает flask -restplus.Models для всех из них.

Вот моя проблема: я хочу зарегистрировать (ну, это будет звучать глупо) динамически предварительно построенное пространство имен с flask ... Что я имею в виду. Подумайте:

@api.route(...)
class Instance(Resrouce):
  @api.expect(already generated model)
  def post(self, *args):
    # create instance
    pass

Вы получаете точку. У меня есть свои модели для всего. Поэтому я в основном пробовал бесчисленное количество способов обойти регистрацию динамически созданного пространства имен, но каждый раз терпел неудачу. Я попытался создать построитель пространства имен, например:

T = TypeVar('T', bound=ResourceBase)


class NamespaceBuilder(object):
    api: Namespace
    models: Dict[str, Model]
    url_prefix: str

    def __init__(self, version_info: str, repository: ModelBuilder):
        self.url_prefix = version_info
        self.api = Namespace(version_info)

        for name, model in repository.models:
            self.api.add_model(name, model)

    def get_resource(self) -> Type[T]:
        @self.api.route(f'/{self.url_prefix}')
        class Instance(ResourceBase):
            @self.api.expect(self.models['setup'], validate=True)
            def get(self, *args):
                print(*args)
                return {}, 200

        return Instance

Ну, он, конечно, создает API и регистрирует модели, но, конечно, фактическая маршрутизация не может использоваться таким образом. Затем я также попытался поместить класс Instance вне NamespaceBuilder, но затем я не могу использовать правильный экземпляр NamespaceBuilder, чтобы снова получить правильные API и модели. В качестве последнего средства я попытался создать метаклассы одноэтапного минимума из NamespaceBuilder, чтобы он генерировал все API со всеми связанными моделями, и чтобы ресурсы считывали эту информацию через экземпляр синглтона, но застрял, потому что класс Instance должен был знать version_info. ..

# nsbuilder.py:
class NamespaceBuilder(object, metaclass=Singleton):
    api: Dict[str, Namespace]
    models: Dict[str, Any]

...

# ns.py:
api: Namespace = NamespaceBuilder.get().api('no_version_info')
models: List[Model, ...] = NamespaceBuilder.get().models('still no version info')

@api.route('/')
class Instance(ResourceBase):
    @expect(models.get('install'), verify=True)
    def post(self, *args):
        print(*args)
        return {}, 200

....

# fl.py:
api: Api = Api(blueprint)
for version_info in version_infos:
    api.add_namespace(Install.api, f'/{version_info}')

Конечно, это все еще не работает, потому что изнутри ns.py version_info недоступен, и, поскольку я не могу установить его динамически, этот подход также пошел к tra sh. Я начинаю чувствовать, что flask просто не может удовлетворить мои потребности. Я искал то же самое в django, который также, кажется, не поддерживает это поведение. Есть ли какие-либо рамки отдыха, которые я мог бы использовать, чтобы создать что-то вроде выше? В качестве альтернативы какое-нибудь извращенное хакерское решение для регистрации пространств имен, как указано выше в flask? После запуска приложения эти пространства имен будут оставаться там до тех пор, пока приложение не остановится. Я просто создаю их динамически, но я бы не хотел записывать python файлы в dis c с какой-нибудь строкой замещения magi c и использовать модуль importlib для добавления их в пространство имен flask ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...