Skip to content

"versioning": True, KeyError: 'custom_DOMAIN_KEY_versions' #1423

@yanbing2020

Description

@yanbing2020

Hi,

Recently, I tried using the eve to design a CMDB system, a situation happened.
In Schema Definition,I'd like to use custom datasource and { "versioning": True, } at the same time, when i PATCH a document, the behind Traceback happened.

Some part of my Schema Definition

"datasource": {
        "source": "resource_APP",
    },
"versioning": True,

Expected Behavior

PATCH document and versioned document will inserted to the next two mongo collections separately.

# domain_key = 'APP'
resource_APP
resource_APP_versions

example:

some code in app.py:

from micro_ops.event_hook import (
    init_register,
)

def create_app(config_object="micro_ops.settings"):
    """
    :param config_object: The configuration object to use.
    """
    app = Eve(settings="eve_settings.py")

    # init register resource
    with app.app_context():
        init_register()

    app.on_inserted_resource += inserted_resource
    app.on_updated_resource += updated_resource

    app.add_url_rule(
        "/graphql",
        view_func=GraphQLView.as_view("graphql", schema=schema, graphiql=True),
    )

    app.config.from_object(config_object)
    register_extensions(app)
    register_blueprints(app)
    register_errorhandlers(app)
    register_shellcontext(app)
    register_commands(app)
    configure_logger(app)
    return app

event_hook.py:

# -*- coding: utf-8 -*-
"""Helper utilities and decorators."""

import copy

from flask import current_app

# init register resource definition
def init_register():
    app = current_app._get_current_object()
    db_client = app.data.pymongo().db
    cursor = db_client["resource_definition"].find()
    for item in cursor:
        # print(item)
        try:
            register_item(item)
        except BaseException as identifier:
            print(identifier)
        finally:
            pass
    pass


# register an item by domain_key
def register_item(item):
    """
    register an domain_key
    """
    resource_definition = copy.deepcopy(DEFINITION_TEMPLATE)
    definition_data = item
    resource_attr_list = definition_data["object_schema"]
    if len(resource_attr_list) == 0:
        return
    schema = generate_schema(resource_attr_list)

    domain_key = definition_data["object_id"]
    resource_definition["schema"] = schema

    resource_definition["item_title"] = domain_key
    resource_definition["url"] = domain_key
    resource_definition["datasource"]["source"] = "resource_{}".format(domain_key)

    current_app.register_resource(domain_key, resource_definition)
    print("object: {} is modified and now is registered!".format(domain_key))


def generate_schema(resource_attr_list):
    # init an empty schema
    schema = {}
    for resource_attr in resource_attr_list:
        field_type = resource_attr["type"]
        field_map = copy.deepcopy(FIELD_MAP[field_type])
        if field_type == "string":
            field_map["required"] = resource_attr["required"]
            field_map["unique"] = resource_attr["unique"]

        filed_key = resource_attr["id"]
        schema[filed_key] = field_map

    return schema


FIELD_MAP = {
    "string": {
        "type": "string",
        "minlength": 1,
        "maxlength": 15,
        "required": False,
        "unique": False,
    },
}

SCHEMA_TEMPLATE = {
    "object_id": {
        "type": "string",
        "minlength": 1,
        "maxlength": 32,
        "regex": "^[A-Z]+$",
        "required": True,
        "unique": True,
    },
    "name": {
        "type": "string",
        "minlength": 1,
        "maxlength": 15,
        "required": True,
    },
    # An embedded 'strongly-typed' dictionary.
    "category": {
        "type": "dict",
        "schema": {"_id": {"type": "objectid"}, "_version": {"type": "integer"}},
        "data_relation": {
            "resource": "category",
            "field": "_id",
            "embeddable": True,
            "version": False,
        },
    },
}

DEFINITION_TEMPLATE = {
    "datasource": {
        "source": "",
    },
    "additional_lookup": {"url": r'regex("[\w]+")', "field": "name"},
    "cache_control": "max-age=10,must-revalidate",
    "cache_expires": 10,
    "schema": SCHEMA_TEMPLATE,
    "soft_delete": True,
    "versioning": True,
}

Actual Behavior

[2020-11-25 17:46:42,772] ERROR in patch: 'resource_APP_versions'
Traceback (most recent call last):
  File "/Users/abin/code/Lipotes/micro-api/.env3.6/lib/python3.6/site-packages/eve/methods/patch.py", line 239, in patch_internal
    insert_versioning_documents(resource, updated)
  File "/Users/abin/code/Lipotes/micro-api/.env3.6/lib/python3.6/site-packages/eve/versioning.py", line 159, in insert_versioning_documents
    app.data.insert(versionable_resource_name, versioned_documents)
  File "/Users/abin/code/Lipotes/micro-api/.env3.6/lib/python3.6/site-packages/eve/io/mongo/mongo.py", line 460, in insert
    datasource, _, _, _ = self._datasource_ex(resource)
  File "/Users/abin/code/Lipotes/micro-api/.env3.6/lib/python3.6/site-packages/eve/io/base.py", line 424, in _datasource_ex
    datasource, filter_, projection_, sort_ = self.datasource(resource)
  File "/Users/abin/code/Lipotes/micro-api/.env3.6/lib/python3.6/site-packages/eve/io/base.py", line 359, in datasource
    dsource = config.SOURCES[resource]
KeyError: 'resource_APP_versions'

In debugging mode, I have tried the next code, and it will successfully get dsource. and following,the versioned document will inserted to a collection named 'resource_APP_versions', which is the Expected Behavior.

dsource = config.SOURCES['APP_versions']

thanks!

Environment

  • Python version:3.6.6
  • Eve version:1.1.4
  • MacOS 10.15.7

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions