From 3671cad3d29a200752afdb09a7e19de837db5ecb Mon Sep 17 00:00:00 2001 From: Ronald Krist Date: Tue, 13 Feb 2024 15:25:53 +0100 Subject: [PATCH] generating record items and lists --- .../datatypes/components/__init__.py | 4 + .../datatypes/components/model/__init__.py | 4 + .../datatypes/components/model/record_item.py | 88 ++++ .../datatypes/components/model/record_list.py | 87 ++++ .../datatypes/components/model/ui.py | 7 +- oarepo_model_builder/invenio/__init__.py | 2 + .../invenio/invenio_record_item.py | 7 + .../invenio/invenio_record_list.py | 7 + .../invenio/templates/record_item.py.jinja2 | 10 + .../invenio/templates/record_list.py.jinja2 | 10 + .../templates/service_config.py.jinja2 | 13 +- setup.cfg | 2 + tests/test_datatype_prepare.py | 384 +++++++++--------- tests/test_model_saver.py | 50 ++- tests/test_simple_builders.py | 8 +- 15 files changed, 485 insertions(+), 198 deletions(-) create mode 100644 oarepo_model_builder/datatypes/components/model/record_item.py create mode 100644 oarepo_model_builder/datatypes/components/model/record_list.py create mode 100644 oarepo_model_builder/invenio/invenio_record_item.py create mode 100644 oarepo_model_builder/invenio/invenio_record_list.py create mode 100644 oarepo_model_builder/invenio/templates/record_item.py.jinja2 create mode 100644 oarepo_model_builder/invenio/templates/record_list.py.jinja2 diff --git a/oarepo_model_builder/datatypes/components/__init__.py b/oarepo_model_builder/datatypes/components/__init__.py index 15617e1a..21d471b0 100644 --- a/oarepo_model_builder/datatypes/components/__init__.py +++ b/oarepo_model_builder/datatypes/components/__init__.py @@ -27,6 +27,8 @@ PIDModelComponent, ProxyModelComponent, RecordDumperModelComponent, + RecordItemModelComponent, + RecordListModelComponent, RecordMetadataModelComponent, RecordModelComponent, ResourceModelComponent, @@ -83,4 +85,6 @@ StringMarshmallowComponent, NumberMarshmallowComponent, EDTFIntervalDumperModelComponent, + RecordListModelComponent, + RecordItemModelComponent, ] diff --git a/oarepo_model_builder/datatypes/components/model/__init__.py b/oarepo_model_builder/datatypes/components/model/__init__.py index 54b30b4c..10babb80 100644 --- a/oarepo_model_builder/datatypes/components/model/__init__.py +++ b/oarepo_model_builder/datatypes/components/model/__init__.py @@ -13,6 +13,8 @@ from .proxy import ProxyModelComponent from .record import RecordModelComponent from .record_dumper import RecordDumperModelComponent +from .record_item import RecordItemModelComponent +from .record_list import RecordListModelComponent from .record_metadata import RecordMetadataModelComponent from .resource import ResourceModelComponent from .sample import SampleModelComponent @@ -46,4 +48,6 @@ "ExtResourceModelComponent", "SortModelComponent", "EDTFIntervalDumperModelComponent", + "RecordListModelComponent", + "RecordItemModelComponent", ] diff --git a/oarepo_model_builder/datatypes/components/model/record_item.py b/oarepo_model_builder/datatypes/components/model/record_item.py new file mode 100644 index 00000000..500088c5 --- /dev/null +++ b/oarepo_model_builder/datatypes/components/model/record_item.py @@ -0,0 +1,88 @@ +import marshmallow as ma + +from oarepo_model_builder.datatypes import DataTypeComponent, ModelDataType +from oarepo_model_builder.utils.python_name import ( + convert_config_to_qualified_name, + package_name, +) +from oarepo_model_builder.validation.utils import ImportSchema + +from .service import ServiceModelComponent + +# from .app import AppModelComponent +# from .defaults import DefaultsModelComponent +from .utils import set_default + + +class RecordItemClassSchema(ma.Schema): + class Meta: + unknown = ma.RAISE + + generate = ma.fields.Bool(metadata={"doc": "Generate the service config"}) + class_ = ma.fields.Str( + attribute="class", + data_key="class", + metadata={"doc": "Qualified name of the service config class"}, + ) + base_classes = ma.fields.List( + ma.fields.Str(), + attribute="base-classes", + data_key="base-classes", + metadata={"doc": "List of base classes"}, + ) + extra_code = ma.fields.Str( + attribute="extra-code", + data_key="extra-code", + metadata={"doc": "Extra code to be put below the service config class"}, + ) + components = ma.fields.List( + ma.fields.String(), metadata={"doc": "List of service components"} + ) + module = ma.fields.String(metadata={"doc": "Class module"}) + imports = ma.fields.List( + ma.fields.Nested(ImportSchema), metadata={"doc": "List of python imports"} + ) + skip = ma.fields.Boolean() + + +class RecordItemModelComponent(DataTypeComponent): + eligible_datatypes = [ModelDataType] + depends_on = [ServiceModelComponent] + + class ModelSchema(ma.Schema): + record_item = ma.fields.Nested( + RecordItemClassSchema, + attribute="record-item", + data_key="record-item", + metadata={"doc": "Record item class settings"}, + ) + + def before_model_prepare(self, datatype, *, context, **kwargs): + record_prefix = datatype.definition["module"]["prefix"] + + service_package = package_name(datatype.definition["service-config"]["module"]) + + record_item_config = set_default(datatype, "record-item", {}) + + record_item_config.setdefault("generate", True) + record_item_module = record_item_config.setdefault( + "module", + f"{service_package}.results", + ) + record_item_config.setdefault( + "class", + f"{record_item_module}.{record_prefix}RecordItem", + ) + record_item_config.setdefault("extra-code", "") + record_item_config.setdefault( + "base-classes", + [ + "oarepo_runtime.services.results.RecordItem", + ], + ) + record_item_config.setdefault("components", []) + record_item_config.setdefault( + "imports", + [], + ) + convert_config_to_qualified_name(record_item_config) diff --git a/oarepo_model_builder/datatypes/components/model/record_list.py b/oarepo_model_builder/datatypes/components/model/record_list.py new file mode 100644 index 00000000..39c62a77 --- /dev/null +++ b/oarepo_model_builder/datatypes/components/model/record_list.py @@ -0,0 +1,87 @@ +import marshmallow as ma + +from oarepo_model_builder.datatypes import DataTypeComponent, ModelDataType +from oarepo_model_builder.utils.python_name import ( + convert_config_to_qualified_name, + package_name, +) +from oarepo_model_builder.validation.utils import ImportSchema + +from .app import AppModelComponent +from .defaults import DefaultsModelComponent +from .service import ServiceModelComponent +from .utils import set_default + + +class RecordListClassSchema(ma.Schema): + class Meta: + unknown = ma.RAISE + + generate = ma.fields.Bool(metadata={"doc": "Generate the service config"}) + class_ = ma.fields.Str( + attribute="class", + data_key="class", + metadata={"doc": "Qualified name of the service config class"}, + ) + base_classes = ma.fields.List( + ma.fields.Str(), + attribute="base-classes", + data_key="base-classes", + metadata={"doc": "List of base classes"}, + ) + extra_code = ma.fields.Str( + attribute="extra-code", + data_key="extra-code", + metadata={"doc": "Extra code to be put below the service config class"}, + ) + components = ma.fields.List( + ma.fields.String(), metadata={"doc": "List of service components"} + ) + module = ma.fields.String(metadata={"doc": "Class module"}) + imports = ma.fields.List( + ma.fields.Nested(ImportSchema), metadata={"doc": "List of python imports"} + ) + skip = ma.fields.Boolean() + + +class RecordListModelComponent(DataTypeComponent): + eligible_datatypes = [ModelDataType] + depends_on = [DefaultsModelComponent, AppModelComponent, ServiceModelComponent] + + class ModelSchema(ma.Schema): + record_list = ma.fields.Nested( + RecordListClassSchema, + attribute="record-list", + data_key="record-list", + metadata={"doc": "Record list class settings"}, + ) + + def before_model_prepare(self, datatype, *, context, **kwargs): + record_prefix = datatype.definition["module"]["prefix"] + + service_package = package_name(datatype.definition["service-config"]["module"]) + + record_list_config = set_default(datatype, "record-list", {}) + + record_list_config.setdefault("generate", True) + record_list_module = record_list_config.setdefault( + "module", + f"{service_package}.results", + ) + record_list_config.setdefault( + "class", + f"{record_list_module}.{record_prefix}RecordList", + ) + record_list_config.setdefault("extra-code", "") + record_list_config.setdefault( + "base-classes", + [ + "oarepo_runtime.services.results.RecordList", + ], + ) + record_list_config.setdefault("components", []) + record_list_config.setdefault( + "imports", + [], + ) + convert_config_to_qualified_name(record_list_config) diff --git a/oarepo_model_builder/datatypes/components/model/ui.py b/oarepo_model_builder/datatypes/components/model/ui.py index 526eb19e..1cc51c56 100644 --- a/oarepo_model_builder/datatypes/components/model/ui.py +++ b/oarepo_model_builder/datatypes/components/model/ui.py @@ -49,9 +49,7 @@ class Meta: schema_context_args = ma.fields.Dict( attribute="schema-context-args", data_key="schema-context-args", - metadata={ - "doc": "Extra args for ui marshmallow schema context" - }, + metadata={"doc": "Extra args for ui marshmallow schema context"}, ) imports = ma.fields.List( ma.fields.Nested(ImportSchema), metadata={"doc": "List of python imports"} @@ -101,5 +99,6 @@ def before_model_prepare(self, datatype, **kwargs): "format_serializer_cls", "flask_resources.serializers.JSONSerializer" ) json.setdefault( - "schema-context-args", {'"object_key"': '"ui"', '"identity"': "{{ flask.g{g.identity} }}"} + "schema-context-args", + {'"object_key"': '"ui"', '"identity"': "{{ flask.g{g.identity} }}"}, ) diff --git a/oarepo_model_builder/invenio/__init__.py b/oarepo_model_builder/invenio/__init__.py index dd28e9f9..00ff83b1 100644 --- a/oarepo_model_builder/invenio/__init__.py +++ b/oarepo_model_builder/invenio/__init__.py @@ -21,4 +21,6 @@ # utils and included "ext-resource": "templates/ext_resource.py.jinja2", "edtf-interval-record-dumper": "templates/edtf_interval_record_dumper.py.jinja2", + "record-item": "templates/record_item.py.jinja2", + "record-list": "templates/record_list.py.jinja2", } diff --git a/oarepo_model_builder/invenio/invenio_record_item.py b/oarepo_model_builder/invenio/invenio_record_item.py new file mode 100644 index 00000000..1abf25ad --- /dev/null +++ b/oarepo_model_builder/invenio/invenio_record_item.py @@ -0,0 +1,7 @@ +from .invenio_base import InvenioBaseClassPythonBuilder + + +class InvenioRecordItemBuilder(InvenioBaseClassPythonBuilder): + TYPE = "invenio_record_item" + section = "record-item" + template = "record-item" diff --git a/oarepo_model_builder/invenio/invenio_record_list.py b/oarepo_model_builder/invenio/invenio_record_list.py new file mode 100644 index 00000000..c39dc1cf --- /dev/null +++ b/oarepo_model_builder/invenio/invenio_record_list.py @@ -0,0 +1,7 @@ +from .invenio_base import InvenioBaseClassPythonBuilder + + +class InvenioRecordListBuilder(InvenioBaseClassPythonBuilder): + TYPE = "invenio_record_list" + section = "record-list" + template = "record-list" diff --git a/oarepo_model_builder/invenio/templates/record_item.py.jinja2 b/oarepo_model_builder/invenio/templates/record_item.py.jinja2 new file mode 100644 index 00000000..b0520da7 --- /dev/null +++ b/oarepo_model_builder/invenio/templates/record_item.py.jinja2 @@ -0,0 +1,10 @@ +{{ vars.record_item|imports }} +{% for c in vars.record_item.components %} +{{ c|code_imports }} +{% endfor %} + +class {{ vars.record_item|class_header }}: + """{{ vars.record.class|base_name }} record item.""" + components = [ {% for b in vars.record_item.base_classes %}*{{ b|base_name }}.components{% if not loop.last %}, {% endif %}{% endfor %}{% for c in vars.record_item.components %}, {{ c|extra_code }} {% endfor %}] + +{{ vars.record_item|extra_code }} \ No newline at end of file diff --git a/oarepo_model_builder/invenio/templates/record_list.py.jinja2 b/oarepo_model_builder/invenio/templates/record_list.py.jinja2 new file mode 100644 index 00000000..3ed987d4 --- /dev/null +++ b/oarepo_model_builder/invenio/templates/record_list.py.jinja2 @@ -0,0 +1,10 @@ +{{ vars.record_list|imports }} +{% for c in vars.record_list.components %} +{{ c|code_imports }} +{% endfor %} + +class {{ vars.record_list|class_header }}: + """{{ vars.record.class|base_name }} record list.""" + components = [ {% for b in vars.record_list.base_classes %}*{{ b|base_name }}.components{% if not loop.last %}, {% endif %}{% endfor %}{% for c in vars.record_list.components %}, {{ c|extra_code }} {% endfor %}] + +{{ vars.record_list|extra_code }} \ No newline at end of file diff --git a/oarepo_model_builder/invenio/templates/service_config.py.jinja2 b/oarepo_model_builder/invenio/templates/service_config.py.jinja2 index 7453c4f1..037b5f6d 100644 --- a/oarepo_model_builder/invenio/templates/service_config.py.jinja2 +++ b/oarepo_model_builder/invenio/templates/service_config.py.jinja2 @@ -4,17 +4,20 @@ {{ vars.permissions.class|imports }} {{ vars.marshmallow.class|imports }} {{ vars.search_options.class|imports }} -{{ vars.service_config.result_list_class|imports }} -{{ vars.service_config.result_item_class|imports }} +{{ vars.record_item.class|imports }} +{{ vars.record_list.class|imports }} {% for c in vars.service_config.components %} {{ c|code_imports }} {% endfor %} class {{ vars.service_config|class_header }}: """{{ vars.record.class|base_name }} service config.""" - result_item_cls = {{ vars.service_config.result_item_class|base_name }} - result_list_cls = {{ vars.service_config.result_list_class|base_name }} - + {% if not vars.record_item.skip %} + result_item_cls = {{ vars.record_item.class|base_name }} + {% endif %} + {% if not vars.record_list.skip %} + result_list_cls = {{ vars.record_list.class|base_name }} + {% endif %} PERMISSIONS_PRESETS = [{% for p in vars.permissions.presets %}"{{ p }}"{{ ", " if not loop.last else "" }} {% endfor %}] url_prefix = "{{ vars.resource_config.base_url }}" diff --git a/setup.cfg b/setup.cfg index 6b73e058..9e6d532f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -160,6 +160,8 @@ oarepo_model_builder.builders.record = 1050-invenio_version = oarepo_model_builder.invenio.invenio_version:InvenioVersionBuilder 2000-model_saver = oarepo_model_builder.builders.model_saver:ModelSaverBuilder 2010-model_registration = oarepo_model_builder.builders.model_saver:ModelRegistrationBuilder + 2020-invenio_record_item = oarepo_model_builder.invenio.invenio_record_item:InvenioRecordItemBuilder + 2030-invenio_record_list = oarepo_model_builder.invenio.invenio_record_list:InvenioRecordListBuilder #### #### Extended schema profile diff --git a/tests/test_datatype_prepare.py b/tests/test_datatype_prepare.py index 3f906530..b9887490 100644 --- a/tests/test_datatype_prepare.py +++ b/tests/test_datatype_prepare.py @@ -1,5 +1,6 @@ from oarepo_model_builder.schema import ModelSchema + def test_prepare_datatype(): module = "my.test" model = ModelSchema( @@ -24,265 +25,286 @@ def test_prepare_datatype(): record_section = model.get_schema_section(profile="record", section="record") assert record_section.definition == { - "api-blueprint": { - "alias": "my_test_record", - "extra_code": "", - "function": "my.test.views.records.api.create_api_blueprint", - "generate": True, - "imports": [], - "module": "my.test.views.records.api", + "type": "model", + "properties": { + "metadata": { + "type": "object", + "properties": {}, + "marshmallow": { + "module": "my.test.services.records.schema", + "generate": True, + "class": "my.test.services.records.schema.TestMetadataSchema", + "extra-code": "", + "base-classes": ["marshmallow.Schema"], + }, + "ui": { + "marshmallow": { + "generate": True, + "module": "my.test.services.records.ui_schema", + "class": "my.test.services.records.ui_schema.TestMetadataUISchema", + "extra-code": "", + "base-classes": ["marshmallow.Schema"], + } + }, + } }, - "app-blueprint": { + "searchable": True, + "model-name": "My Test Record", + "module": { + "qualified": "my.test", "alias": "my_test_record", - "extra_code": "", - "function": "my.test.views.records.app.create_app_blueprint", + "path": "my/test", + "base": "test", + "base-upper": "TEST", + "base-title": "Test", + "kebab-module": "my-test", + "prefix": "Test", + "prefix-upper": "TEST", + "prefix-snake": "test", + "suffix": "test", + "suffix-upper": "TEST", + "suffix-snake": "test", + }, + "sample": {"file": "data/sample_data.yaml"}, + "ext-resource": {"generate": True, "skip": False}, + "search-options": { "generate": True, + "module": "my.test.services.records.search", + "extra-code": "", + "class": "my.test.services.records.search.TestSearchOptions", + "base-classes": [ + "invenio_records_resources.services.SearchOptions{InvenioSearchOptions}" + ], "imports": [], - "module": "my.test.views.records.app", + "sort-options-field": "sort_options", }, "config": { - "extra_code": "", "generate": True, - "imports": [], "module": "my.test.config", + "extra_code": "", + "imports": [], }, "ext": { - "alias": "my.test", - "base-classes": [], + "generate": True, + "module": "my.test.ext", "class": "my.test.ext.TestExt", + "base-classes": [], + "extra_code": "", + "alias": "my.test", + "imports": [], + }, + "api-blueprint": { + "generate": True, + "alias": "my_test_record", "extra_code": "", + "module": "my.test.views.records.api", + "function": "my.test.views.records.api.create_api_blueprint", + "imports": [], + }, + "app-blueprint": { "generate": True, + "alias": "my_test_record", + "extra_code": "", + "module": "my.test.views.records.app", + "function": "my.test.views.records.app.create_app_blueprint", "imports": [], - "module": "my.test.ext", }, - "ext-resource": {"generate": True, "skip": False}, "facets": { - "extra-code": "", "generate": True, "module": "my.test.services.records.facets", + "extra-code": "", }, - "json-schema-settings": { - "alias": "my_test_record", - "file": "my/test/records/jsonschemas/test-1.0.0.json", + "record": { "generate": True, - "module": "my.test.records.jsonschemas", - "name": "test-1.0.0.json", - "version": "1.0.0", - }, - "json-serializer": { - "base-classes": ["oarepo_runtime.resources.LocalizedUIJSONSerializer"], - "class": "my.test.resources.records.ui.TestUIJSONSerializer", + "module": "my.test.records.api", + "class": "my.test.records.api.TestRecord", + "base-classes": [ + "invenio_records_resources.records.api.Record{InvenioRecord}" + ], + "imports": [], "extra-code": "", - "format_serializer_cls": "flask_resources.serializers.JSONSerializer", + }, + "resource": { "generate": True, + "config-key": "TEST_RECORD_RESOURCE_CLASS", + "module": "my.test.resources.records.resource", + "class": "my.test.resources.records.resource.TestResource", + "proxy": "current_resource", + "extra-code": "", + "base-classes": ["invenio_records_resources.resources.RecordResource"], "imports": [], - "list_schema_cls": "flask_resources.BaseListSchema", - "module": "my.test.resources.records.ui", - "schema-context-args": {'"object_key"': '"ui"', '"identity"': "{{ flask.g{g.identity} }}"} }, - "mapping": { - "alias": "my_test_record", - "file": "my/test/records/mappings/os-v2/my_test_record/test-1.0.0.json", + "resource-config": { "generate": True, - "index": "my_test_record-test-1.0.0", - "module": "my.test.records.mappings", - }, - "marshmallow": { - "base-classes": ["marshmallow.Schema"], - "class": "my.test.services.records.schema.TestSchema", + "base-url": "/my-test/", + "base-html-url": "/my-test/", + "config-key": "TEST_RECORD_RESOURCE_CONFIG", + "module": "my.test.resources.records.config", + "class": "my.test.resources.records.config.TestResourceConfig", "extra-code": "", - "generate": True, - "module": "my.test.services.records.schema", + "base-classes": [ + "invenio_records_resources.resources.RecordResourceConfig" + ], + "imports": [], }, - "model-name": "My Test Record", - "module": { + "saved-model": { + "file": "my/test/models/records.json", + "module": "my.test.models", "alias": "my_test_record", - "base": "test", - "base-title": "Test", - "base-upper": "TEST", - "kebab-module": "my-test", - "path": "my/test", - "prefix": "Test", - "prefix-snake": "test", - "prefix-upper": "TEST", - "qualified": "my.test", - "suffix": "test", - "suffix-snake": "test", - "suffix-upper": "TEST", }, - "permissions": { - "base-classes": ["invenio_records_permissions.RecordPermissionPolicy"], - "class": "my.test.services.records.permissions.TestPermissionPolicy", - "extra-code": "", + "proxy": {"module": "my.test.proxies", "generate": True}, + "json-schema-settings": { "generate": True, - "imports": [], - "module": "my.test.services.records.permissions", - "presets": ["everyone"], + "alias": "my_test_record", + "version": "1.0.0", + "module": "my.test.records.jsonschemas", + "name": "test-1.0.0.json", + "file": "my/test/records/jsonschemas/test-1.0.0.json", }, "pid": { - "context-class": "invenio_records_resources.records.systemfields.pid.PIDFieldContext", - "extra-code": "", - "field-args": ["create=True"], - "field-class": "invenio_records_resources.records.systemfields.pid.PIDField", "generate": True, - "imports": [], + "type": "mytcrd", "module": "my.test.records.api", + "provider-class": "my.test.records.api.TestIdProvider", "provider-base-classes": [ "invenio_pidstore.providers.recordid_v2.RecordIdProviderV2" ], - "provider-class": "my.test.records.api.TestIdProvider", - "type": "mytcrd", - }, - "properties": { - "metadata": { - "marshmallow": { - "base-classes": ["marshmallow.Schema"], - "class": "my.test.services.records.schema.TestMetadataSchema", - "extra-code": "", - "generate": True, - "module": "my.test.services.records.schema", - }, - "properties": {}, - "type": "object", - "ui": { - "marshmallow": { - "base-classes": ["marshmallow.Schema"], - "class": "my.test.services.records.ui_schema.TestMetadataUISchema", - "extra-code": "", - "generate": True, - "module": "my.test.services.records.ui_schema", - } - }, - } - }, - "proxy": {"generate": True, "module": "my.test.proxies"}, - "record": { - "base-classes": [ - "invenio_records_resources.records.api.Record{InvenioRecord}" - ], - "class": "my.test.records.api.TestRecord", - "extra-code": "", - "generate": True, + "field-class": "invenio_records_resources.records.systemfields.pid.PIDField", + "context-class": "invenio_records_resources.records.systemfields.pid.PIDFieldContext", + "field-args": ["create=True"], "imports": [], - "module": "my.test.records.api", + "extra-code": "", }, "record-dumper": { - "base-classes": ["oarepo_runtime.records.dumpers.SearchDumper"], + "generate": True, + "module": "my.test.records.dumpers.dumper", "class": "my.test.records.dumpers.dumper.TestDumper", + "base-classes": ["oarepo_runtime.records.dumpers.SearchDumper"], + "extra-code": "", "extensions": [ "{{my.test.records.dumpers.edtf.TestEDTFIntervalDumperExt}}()" ], - "extra-code": "", - "generate": True, "imports": [], - "module": "my.test.records.dumpers.dumper", - }, - "edtf-interval-dumper": { - "base-classes": [ - "oarepo_runtime.records.dumpers.edtf_interval.EDTFIntervalDumperExt" - ], - "class": "my.test.records.dumpers.edtf.TestEDTFIntervalDumperExt", - "extensions": [], - "extra-code": "", - "generate": True, - "imports": [], - "module": "my.test.records.dumpers.edtf", }, "record-metadata": { - "alembic": "my.test.alembic", - "alias": "my_test_record", + "generate": True, + "module": "my.test.records.models", + "class": "my.test.records.models.TestMetadata", "base-classes": [ "invenio_db.db{db.Model}", "invenio_records.models.RecordMetadataBase", ], - "class": "my.test.records.models.TestMetadata", "extra-code": "", - "generate": True, "imports": [], - "module": "my.test.records.models", "table": "test_metadata", + "alias": "my_test_record", "use-versioning": True, + "alembic": "my.test.alembic", }, - "resource": { - "base-classes": ["invenio_records_resources.resources.RecordResource"], - "class": "my.test.resources.records.resource.TestResource", - "config-key": "TEST_RECORD_RESOURCE_CLASS", - "extra-code": "", + "service-config": { "generate": True, - "imports": [], - "module": "my.test.resources.records.resource", - "proxy": "current_resource", + "config-key": "TEST_RECORD_SERVICE_CONFIG", + "module": "my.test.services.records.config", + "class": "my.test.services.records.config.TestServiceConfig", + "extra-code": "", + "service-id": "test", + "base-classes": [ + "oarepo_runtime.services.config.service.PermissionsPresetsConfigMixin", + "invenio_records_resources.services.RecordServiceConfig{InvenioRecordServiceConfig}", + ], + "components": [], + "result-list-class": "oarepo_runtime.services.results.RecordList", + "result-item-class": "invenio_records_resources.services.records.results.RecordItem", }, - "resource-config": { + "service": { + "generate": True, + "config-key": "TEST_RECORD_SERVICE_CLASS", + "proxy": "current_service", + "module": "my.test.services.records.service", + "class": "my.test.services.records.service.TestService", + "extra-code": "", "base-classes": [ - "invenio_records_resources.resources.RecordResourceConfig" + "invenio_records_resources.services.RecordService{InvenioRecordService}" ], - "base-html-url": "/my-test/", - "base-url": "/my-test/", - "class": "my.test.resources.records.config.TestResourceConfig", - "config-key": "TEST_RECORD_RESOURCE_CONFIG", + "imports": [], + }, + "ui": { + "marshmallow": { + "generate": True, + "module": "my.test.services.records.ui_schema", + "class": "my.test.services.records.ui_schema.TestUISchema", + "extra-code": "", + "base-classes": ["oarepo_runtime.services.schema.ui.InvenioUISchema"], + "imports": [], + } + }, + "json-serializer": { + "module": "my.test.resources.records.ui", + "class": "my.test.resources.records.ui.TestUIJSONSerializer", + "base-classes": ["oarepo_runtime.resources.LocalizedUIJSONSerializer"], + "imports": [], "extra-code": "", "generate": True, - "imports": [], - "module": "my.test.resources.records.config", + "list_schema_cls": "flask_resources.BaseListSchema", + "format_serializer_cls": "flask_resources.serializers.JSONSerializer", + "schema-context-args": { + '"object_key"': '"ui"', + '"identity"': "{{ flask.g{g.identity} }}", + }, }, - "sample": {"file": "data/sample_data.yaml"}, - "saved-model": { + "mapping": { + "generate": True, "alias": "my_test_record", - "file": "my/test/models/records.json", - "module": "my.test.models", + "module": "my.test.records.mappings", + "index": "my_test_record-test-1.0.0", + "file": "my/test/records/mappings/os-v2/my_test_record/test-1.0.0.json", }, - "search-options": { - "base-classes": [ - "invenio_records_resources.services.SearchOptions{InvenioSearchOptions}" - ], - "class": "my.test.services.records.search.TestSearchOptions", + "marshmallow": { + "generate": True, + "module": "my.test.services.records.schema", + "class": "my.test.services.records.schema.TestSchema", "extra-code": "", + "base-classes": ["marshmallow.Schema"], + }, + "permissions": { "generate": True, + "presets": ["everyone"], + "extra-code": "", + "module": "my.test.services.records.permissions", + "class": "my.test.services.records.permissions.TestPermissionPolicy", + "base-classes": ["invenio_records_permissions.RecordPermissionPolicy"], "imports": [], - "module": "my.test.services.records.search", - "sort-options-field": "sort_options", }, - "searchable": True, - "service": { + "edtf-interval-dumper": { + "generate": True, + "module": "my.test.records.dumpers.edtf", + "class": "my.test.records.dumpers.edtf.TestEDTFIntervalDumperExt", "base-classes": [ - "invenio_records_resources.services.RecordService{InvenioRecordService}" + "oarepo_runtime.records.dumpers.edtf_interval.EDTFIntervalDumperExt" ], - "class": "my.test.services.records.service.TestService", - "config-key": "TEST_RECORD_SERVICE_CLASS", "extra-code": "", - "generate": True, + "extensions": [], "imports": [], - "module": "my.test.services.records.service", - "proxy": "current_service", }, - "service-config": { - "base-classes": [ - "oarepo_runtime.services.config.service.PermissionsPresetsConfigMixin", - "invenio_records_resources.services.RecordServiceConfig{InvenioRecordServiceConfig}", - ], - "class": "my.test.services.records.config.TestServiceConfig", - "components": [], - "config-key": "TEST_RECORD_SERVICE_CONFIG", + "record-list": { + "generate": True, + "module": "my.test.services.records.results", + "class": "my.test.services.records.results.TestRecordList", "extra-code": "", + "base-classes": ["oarepo_runtime.services.results.RecordList"], + "components": [], + "imports": [], + }, + "record-item": { "generate": True, - "module": "my.test.services.records.config", - "service-id": "test", - "result-item-class": "invenio_records_resources.services.records.results.RecordItem", - "result-list-class": "oarepo_runtime.services.results.RecordList", + "module": "my.test.services.records.results", + "class": "my.test.services.records.results.TestRecordItem", + "extra-code": "", + "base-classes": ["oarepo_runtime.services.results.RecordItem"], + "components": [], + "imports": [], }, "sortable": [], - "type": "model", - "ui": { - "marshmallow": { - "base-classes": ["oarepo_runtime.services.schema.ui.InvenioUISchema"], - "class": "my.test.services.records.ui_schema.TestUISchema", - "extra-code": "", - "generate": True, - "imports": [], - "module": "my.test.services.records.ui_schema", - } - }, } diff --git a/tests/test_model_saver.py b/tests/test_model_saver.py index 04fcad62..750fcf4d 100644 --- a/tests/test_model_saver.py +++ b/tests/test_model_saver.py @@ -205,8 +205,8 @@ def test_model_saver(): "invenio_records_resources.services.RecordServiceConfig{InvenioRecordServiceConfig}", ], "components": [], - "result-item-class": "invenio_records_resources.services.records.results.RecordItem", "result-list-class": "oarepo_runtime.services.results.RecordList", + "result-item-class": "invenio_records_resources.services.records.results.RecordItem", }, "service": { "generate": True, @@ -239,7 +239,10 @@ def test_model_saver(): "generate": True, "list_schema_cls": "flask_resources.BaseListSchema", "format_serializer_cls": "flask_resources.serializers.JSONSerializer", - "schema-context-args": {'"identity"': '{{ flask.g{g.identity} }}', '"object_key"': '"ui"'}, + "schema-context-args": { + '"object_key"': '"ui"', + '"identity"': "{{ flask.g{g.identity} }}", + }, }, "mapping": { "generate": True, @@ -275,6 +278,24 @@ def test_model_saver(): "extensions": [], "imports": [], }, + "record-list": { + "generate": True, + "module": "test.services.records.results", + "class": "test.services.records.results.TestRecordList", + "extra-code": "", + "base-classes": ["oarepo_runtime.services.results.RecordList"], + "components": [], + "imports": [], + }, + "record-item": { + "generate": True, + "module": "test.services.records.results", + "class": "test.services.records.results.TestRecordItem", + "extra-code": "", + "base-classes": ["oarepo_runtime.services.results.RecordItem"], + "components": [], + "imports": [], + }, "sortable": [], "properties": { "a": {"type": "keyword"}, @@ -550,8 +571,8 @@ def test_model_saver_invenio(): "invenio_records_resources.services.RecordServiceConfig{InvenioRecordServiceConfig}", ], "components": [], - "result-item-class": "invenio_records_resources.services.records.results.RecordItem", "result-list-class": "oarepo_runtime.services.results.RecordList", + "result-item-class": "invenio_records_resources.services.records.results.RecordItem", }, "service": { "generate": True, @@ -574,7 +595,10 @@ def test_model_saver_invenio(): "generate": True, "list_schema_cls": "flask_resources.BaseListSchema", "format_serializer_cls": "flask_resources.serializers.JSONSerializer", - "schema-context-args": {'"identity"': '{{ flask.g{g.identity} }}', '"object_key"': '"ui"'}, + "schema-context-args": { + '"object_key"': '"ui"', + '"identity"': "{{ flask.g{g.identity} }}", + }, }, "mapping": { "generate": True, @@ -603,6 +627,24 @@ def test_model_saver_invenio(): "extensions": [], "imports": [], }, + "record-list": { + "generate": True, + "module": "test.services.records.results", + "class": "test.services.records.results.TestRecordList", + "extra-code": "", + "base-classes": ["oarepo_runtime.services.results.RecordList"], + "components": [], + "imports": [], + }, + "record-item": { + "generate": True, + "module": "test.services.records.results", + "class": "test.services.records.results.TestRecordItem", + "extra-code": "", + "base-classes": ["oarepo_runtime.services.results.RecordItem"], + "components": [], + "imports": [], + }, "sortable": [], "properties": { "$schema": { diff --git a/tests/test_simple_builders.py b/tests/test_simple_builders.py index e755820f..3427c320 100644 --- a/tests/test_simple_builders.py +++ b/tests/test_simple_builders.py @@ -373,14 +373,14 @@ def test_service_config(): from test.services.records.permissions import TestPermissionPolicy from test.services.records.schema import TestSchema from test.services.records.search import TestSearchOptions -from oarepo_runtime.services.results import RecordList -from invenio_records_resources.services.records.results import RecordItem +from test.services.records.results import TestRecordItem +from test.services.records.results import TestRecordList class TestServiceConfig(PermissionsPresetsConfigMixin, InvenioRecordServiceConfig): """TestRecord service config.""" - result_item_cls = RecordItem - result_list_cls = RecordList + result_item_cls = TestRecordItem + result_list_cls = TestRecordList PERMISSIONS_PRESETS = ["everyone"] url_prefix = "/test/" base_permission_policy_cls = TestPermissionPolicy