oarepo-runtime 1.5.89__tar.gz → 1.5.90__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {oarepo_runtime-1.5.89/oarepo_runtime.egg-info → oarepo_runtime-1.5.90}/PKG-INFO +1 -1
- oarepo_runtime-1.5.90/oarepo_runtime/services/components.py +276 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90/oarepo_runtime.egg-info}/PKG-INFO +1 -1
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/setup.cfg +1 -1
- oarepo_runtime-1.5.89/oarepo_runtime/services/components.py +0 -128
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/LICENSE +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/MANIFEST.in +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/README.md +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/cli/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/cli/assets.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/cli/base.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/cli/cf.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/cli/check.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/cli/configuration.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/cli/fixtures.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/cli/index.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/cli/validate.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/asynchronous.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/catalogue.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/datastreams.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/errors.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/ext.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/fixtures.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/json.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/readers/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/readers/attachments.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/readers/excel.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/readers/json.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/readers/service.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/readers/yaml.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/semi_asynchronous.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/synchronous.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/transformers.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/types.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/utils.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/writers/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/writers/attachments_file.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/writers/attachments_service.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/writers/service.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/writers/utils.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/writers/validation_errors.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/writers/yaml.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/ext.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/ext_config.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/i18n/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/info/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/info/check.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/info/views.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/profile.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/proxies.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/dumpers/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/dumpers/edtf_interval.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/dumpers/multilingual_dumper.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/entity_resolvers/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/entity_resolvers/proxies.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/mappings/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/mappings/rdm_parent_mapping.json +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/owners/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/owners/registry.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/relations/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/relations/base.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/relations/internal.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/relations/lookup.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/relations/pid_relation.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/systemfields/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/systemfields/featured_file.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/systemfields/has_draftcheck.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/systemfields/icu.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/systemfields/mapping.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/systemfields/owner.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/systemfields/record_status.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/systemfields/selectors.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/systemfields/synthetic.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/resources/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/resources/file_resource.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/resources/json_serializer.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/resources/localized_ui_json_serializer.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/config/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/config/link_conditions.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/config/permissions_presets.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/config/service.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/custom_fields/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/custom_fields/mappings.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/entity/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/entity/config.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/entity/schema.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/entity/service.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/expansions/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/expansions/expandable_fields.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/expansions/service.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/facets/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/facets/base.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/facets/date.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/facets/enum.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/facets/facet_groups_names.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/facets/max_facet.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/facets/nested_facet.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/facets/params.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/facets/year_histogram.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/files/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/files/components.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/files/service.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/generators.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/permissions/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/permissions/generators.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/records/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/records/links.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/relations/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/relations/components.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/relations/errors.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/relations/mapping.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/results.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/schema/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/schema/cf.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/schema/i18n.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/schema/i18n_ui.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/schema/i18n_validation.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/schema/marshmallow.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/schema/marshmallow_to_json_schema.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/schema/oneofschema.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/schema/polymorphic.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/schema/rdm.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/schema/ui.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/schema/validation.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/search.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/tasks.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/translations/cs/LC_MESSAGES/messages.mo +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/translations/cs/LC_MESSAGES/messages.po +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/translations/default_translations.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/translations/en/LC_MESSAGES/messages.mo +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/translations/en/LC_MESSAGES/messages.po +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/translations/messages.pot +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/uow.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/utils/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/utils/functools.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/utils/path.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime.egg-info/SOURCES.txt +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime.egg-info/dependency_links.txt +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime.egg-info/entry_points.txt +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime.egg-info/requires.txt +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime.egg-info/top_level.txt +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/pyproject.toml +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/setup.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/tests/marshmallow_to_json/__init__.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/tests/marshmallow_to_json/test_datacite_ui_schema.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/tests/marshmallow_to_json/test_simple_schema.py +0 -0
- {oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/tests/pkg_data/__init__.py +0 -0
@@ -0,0 +1,276 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import inspect
|
4
|
+
from collections import defaultdict
|
5
|
+
from dataclasses import dataclass, field
|
6
|
+
from typing import Type
|
7
|
+
|
8
|
+
from flask import current_app
|
9
|
+
from invenio_accounts.models import User
|
10
|
+
from invenio_drafts_resources.services.records.config import (
|
11
|
+
RecordServiceConfig as DraftsRecordServiceConfig,
|
12
|
+
)
|
13
|
+
from invenio_rdm_records.services.config import RDMRecordServiceConfig
|
14
|
+
from invenio_records import Record
|
15
|
+
from invenio_records_resources.services import FileServiceConfig
|
16
|
+
from invenio_records_resources.services.records.config import (
|
17
|
+
RecordServiceConfig as RecordsRecordServiceConfig,
|
18
|
+
)
|
19
|
+
|
20
|
+
from oarepo_runtime.services.custom_fields import (
|
21
|
+
CustomFields,
|
22
|
+
CustomFieldsMixin,
|
23
|
+
InlinedCustomFields,
|
24
|
+
)
|
25
|
+
from oarepo_runtime.services.generators import RecordOwners
|
26
|
+
|
27
|
+
try:
|
28
|
+
from invenio_drafts_resources.services.records.uow import ParentRecordCommitOp
|
29
|
+
except ImportError:
|
30
|
+
from invenio_records_resources.services.uow import (
|
31
|
+
RecordCommitOp as ParentRecordCommitOp,
|
32
|
+
)
|
33
|
+
|
34
|
+
from invenio_records_resources.services.records.components import ServiceComponent
|
35
|
+
|
36
|
+
|
37
|
+
class OwnersComponent(ServiceComponent):
|
38
|
+
def create(self, identity, *, record, **kwargs):
|
39
|
+
"""Create handler."""
|
40
|
+
self.add_owner(identity, record)
|
41
|
+
|
42
|
+
def add_owner(self, identity, record, commit=False):
|
43
|
+
if not hasattr(identity, "id") or not isinstance(identity.id, int):
|
44
|
+
return
|
45
|
+
|
46
|
+
owners = getattr(record.parent, "owners", None)
|
47
|
+
if owners is not None:
|
48
|
+
user = User.query.filter_by(id=identity.id).first()
|
49
|
+
record.parent.owners.add(user)
|
50
|
+
if commit:
|
51
|
+
self.uow.register(ParentRecordCommitOp(record.parent))
|
52
|
+
|
53
|
+
def update(self, identity, *, record, **kwargs):
|
54
|
+
"""Update handler."""
|
55
|
+
self.add_owner(identity, record, commit=True)
|
56
|
+
|
57
|
+
def update_draft(self, identity, *, record, **kwargs):
|
58
|
+
"""Update handler."""
|
59
|
+
self.add_owner(identity, record, commit=True)
|
60
|
+
|
61
|
+
def search_drafts(self, identity, search, params, **kwargs):
|
62
|
+
new_term = RecordOwners().query_filter(identity)
|
63
|
+
if new_term:
|
64
|
+
return search.filter(new_term)
|
65
|
+
return search
|
66
|
+
|
67
|
+
|
68
|
+
from datetime import datetime
|
69
|
+
|
70
|
+
|
71
|
+
class DateIssuedComponent(ServiceComponent):
|
72
|
+
def publish(self, identity, data=None, record=None, errors=None, **kwargs):
|
73
|
+
"""Create a new record."""
|
74
|
+
if "dateIssued" not in record["metadata"]:
|
75
|
+
record["metadata"]["dateIssued"] = datetime.today().strftime("%Y-%m-%d")
|
76
|
+
|
77
|
+
|
78
|
+
class CFRegistry:
|
79
|
+
def __init__(self):
|
80
|
+
self.custom_field_names = defaultdict(list)
|
81
|
+
|
82
|
+
def lookup(self, record_type: Type[Record]):
|
83
|
+
if record_type not in self.custom_field_names:
|
84
|
+
for fld in inspect.getmembers(
|
85
|
+
record_type, lambda x: isinstance(x, CustomFieldsMixin)
|
86
|
+
):
|
87
|
+
self.custom_field_names[record_type].append(fld[1])
|
88
|
+
return self.custom_field_names[record_type]
|
89
|
+
|
90
|
+
|
91
|
+
cf_registry = CFRegistry()
|
92
|
+
|
93
|
+
|
94
|
+
class CustomFieldsComponent(ServiceComponent):
|
95
|
+
def create(self, identity, data=None, record=None, **kwargs):
|
96
|
+
"""Create a new record."""
|
97
|
+
self._set_cf_to_record(record, data)
|
98
|
+
|
99
|
+
def update(self, identity, data=None, record=None, **kwargs):
|
100
|
+
"""Update a record."""
|
101
|
+
self._set_cf_to_record(record, data)
|
102
|
+
|
103
|
+
def _set_cf_to_record(self, record, data):
|
104
|
+
for cf in cf_registry.lookup(type(record)):
|
105
|
+
if isinstance(cf, CustomFields):
|
106
|
+
setattr(record, cf.attr_name, data.get(cf.key, {}))
|
107
|
+
elif isinstance(cf, InlinedCustomFields):
|
108
|
+
config = current_app.config.get(cf.config_key, {})
|
109
|
+
for c in config:
|
110
|
+
record[c.name] = data.get(c.name)
|
111
|
+
|
112
|
+
|
113
|
+
def process_service_configs(service_config, *additional_components):
|
114
|
+
processed_components = []
|
115
|
+
target_classes = {
|
116
|
+
RDMRecordServiceConfig,
|
117
|
+
DraftsRecordServiceConfig,
|
118
|
+
RecordsRecordServiceConfig,
|
119
|
+
FileServiceConfig,
|
120
|
+
}
|
121
|
+
|
122
|
+
for end_index, cls in enumerate(type(service_config).mro()):
|
123
|
+
if cls in target_classes:
|
124
|
+
break
|
125
|
+
|
126
|
+
# We need this because if the "build" function is present in service_config,
|
127
|
+
# there are two service_config instances in the MRO (Method Resolution Order) output.
|
128
|
+
start_index = 2 if hasattr(service_config, "build") else 1
|
129
|
+
|
130
|
+
service_configs = type(service_config).mro()[start_index : end_index + 1]
|
131
|
+
for config in service_configs:
|
132
|
+
if hasattr(config, "build"):
|
133
|
+
config = config.build(current_app)
|
134
|
+
|
135
|
+
if hasattr(config, "components"):
|
136
|
+
component_property = config.components
|
137
|
+
if isinstance(component_property, list):
|
138
|
+
processed_components.extend(component_property)
|
139
|
+
elif isinstance(component_property, tuple):
|
140
|
+
processed_components.extend(list(component_property))
|
141
|
+
else:
|
142
|
+
raise ValueError(f"{config} component's definition is not supported")
|
143
|
+
|
144
|
+
processed_components.extend(additional_components)
|
145
|
+
processed_components = _sort_components(processed_components)
|
146
|
+
return processed_components
|
147
|
+
|
148
|
+
|
149
|
+
@dataclass
|
150
|
+
class ComponentPlacement:
|
151
|
+
"""Component placement in the list of components.
|
152
|
+
|
153
|
+
This is a helper class used in the component ordering algorithm.
|
154
|
+
"""
|
155
|
+
|
156
|
+
component: Type[ServiceComponent]
|
157
|
+
"""Component to be ordered."""
|
158
|
+
|
159
|
+
depends_on: list[ComponentPlacement] = field(default_factory=list)
|
160
|
+
"""List of components this one depends on.
|
161
|
+
|
162
|
+
The components must be classes of ServiceComponent or '*' to denote
|
163
|
+
that this component depends on all other components and should be placed last.
|
164
|
+
"""
|
165
|
+
|
166
|
+
affects: list[ComponentPlacement] = field(default_factory=list)
|
167
|
+
"""List of components that depend on this one.
|
168
|
+
|
169
|
+
This is a temporary list used for evaluation of '*' dependencies
|
170
|
+
but does not take part in the sorting algorithm."""
|
171
|
+
|
172
|
+
def __hash__(self) -> int:
|
173
|
+
return id(self.component)
|
174
|
+
|
175
|
+
def __eq__(self, other: ComponentPlacement) -> bool:
|
176
|
+
return self.component is other.component
|
177
|
+
|
178
|
+
|
179
|
+
def _sort_components(components):
|
180
|
+
"""Sort components based on their dependencies while trying to
|
181
|
+
keep the initial order as far as possible."""
|
182
|
+
|
183
|
+
placements: list[ComponentPlacement] = _prepare_component_placement(components)
|
184
|
+
placements = _propagate_dependencies(placements)
|
185
|
+
|
186
|
+
ret = []
|
187
|
+
while placements:
|
188
|
+
without_dependencies = [p for p in placements if not p.depends_on]
|
189
|
+
if not without_dependencies:
|
190
|
+
raise ValueError("Circular dependency detected in components.")
|
191
|
+
for p in without_dependencies:
|
192
|
+
ret.append(p.component)
|
193
|
+
placements.remove(p)
|
194
|
+
for p2 in placements:
|
195
|
+
if p in p2.depends_on:
|
196
|
+
p2.depends_on.remove(p)
|
197
|
+
return ret
|
198
|
+
|
199
|
+
|
200
|
+
def _matching_placements(placements, dep_class_or_factory):
|
201
|
+
for pl in placements:
|
202
|
+
pl_component = pl.component
|
203
|
+
if not inspect.isclass(pl_component):
|
204
|
+
pl_component = type(pl_component(service=object()))
|
205
|
+
if issubclass(pl_component, dep_class_or_factory):
|
206
|
+
yield pl
|
207
|
+
|
208
|
+
|
209
|
+
def _prepare_component_placement(components) -> list[ComponentPlacement]:
|
210
|
+
"""Convert components to ComponentPlacement instances and resolve dependencies."""
|
211
|
+
placements = []
|
212
|
+
for idx, c in enumerate(components):
|
213
|
+
placement = ComponentPlacement(component=c)
|
214
|
+
placements.append(placement)
|
215
|
+
|
216
|
+
# direct dependencies
|
217
|
+
for idx, placement in enumerate(placements):
|
218
|
+
placements_without_this = placements[:idx] + placements[idx + 1 :]
|
219
|
+
for dep in getattr(placement.component, "depends_on", []):
|
220
|
+
if dep == "*":
|
221
|
+
continue
|
222
|
+
for pl in _matching_placements(placements_without_this, dep):
|
223
|
+
placement.depends_on.append(pl)
|
224
|
+
pl.affects.append(placement)
|
225
|
+
|
226
|
+
for dep in getattr(placement.component, "affects", []):
|
227
|
+
if dep == "*":
|
228
|
+
continue
|
229
|
+
for pl in _matching_placements(placements_without_this, dep):
|
230
|
+
placement.affects.append(pl)
|
231
|
+
pl.depends_on.append(placement)
|
232
|
+
|
233
|
+
# star dependencies
|
234
|
+
for idx, placement in enumerate(placements):
|
235
|
+
placements_without_this = placements[:idx] + placements[idx + 1 :]
|
236
|
+
if "*" in getattr(placement.component, "depends_on", []):
|
237
|
+
for pl in placements_without_this:
|
238
|
+
# if this placement is not in placements that pl depends on
|
239
|
+
# (added via direct dependencies above), add it
|
240
|
+
if placement not in pl.depends_on:
|
241
|
+
placement.depends_on.append(pl)
|
242
|
+
pl.affects.append(placement)
|
243
|
+
|
244
|
+
if "*" in getattr(placement.component, "affects", []):
|
245
|
+
for pl in placements_without_this:
|
246
|
+
# if this placement is not in placements that pl affects
|
247
|
+
# (added via direct dependencies above), add it
|
248
|
+
if placement not in pl.affects:
|
249
|
+
placement.affects.append(pl)
|
250
|
+
pl.depends_on.append(placement)
|
251
|
+
return placements
|
252
|
+
|
253
|
+
|
254
|
+
def _propagate_dependencies(
|
255
|
+
placements: list[ComponentPlacement],
|
256
|
+
) -> list[ComponentPlacement]:
|
257
|
+
# now propagate dependencies
|
258
|
+
dependency_propagated = True
|
259
|
+
while dependency_propagated:
|
260
|
+
dependency_propagated = False
|
261
|
+
for placement in placements:
|
262
|
+
for dep in placement.depends_on:
|
263
|
+
for dep_of_dep in dep.depends_on:
|
264
|
+
if dep_of_dep not in placement.depends_on:
|
265
|
+
placement.depends_on.append(dep_of_dep)
|
266
|
+
dep_of_dep.affects.append(placement)
|
267
|
+
dependency_propagated = True
|
268
|
+
|
269
|
+
for dep in placement.affects:
|
270
|
+
for dep_of_dep in dep.affects:
|
271
|
+
if dep_of_dep not in placement.affects:
|
272
|
+
placement.affects.append(dep_of_dep)
|
273
|
+
dep_of_dep.depends_on.append(placement)
|
274
|
+
dependency_propagated = True
|
275
|
+
|
276
|
+
return placements
|
@@ -1,128 +0,0 @@
|
|
1
|
-
import inspect
|
2
|
-
from collections import defaultdict
|
3
|
-
from typing import Type
|
4
|
-
|
5
|
-
from flask import current_app
|
6
|
-
from invenio_accounts.models import User
|
7
|
-
from invenio_records import Record
|
8
|
-
|
9
|
-
from oarepo_runtime.services.custom_fields import CustomFieldsMixin, CustomFields, InlinedCustomFields
|
10
|
-
from oarepo_runtime.services.generators import RecordOwners
|
11
|
-
from invenio_rdm_records.services.config import RDMRecordServiceConfig
|
12
|
-
from invenio_drafts_resources.services.records.config import RecordServiceConfig as DraftsRecordServiceConfig
|
13
|
-
from invenio_records_resources.services.records.config import RecordServiceConfig as RecordsRecordServiceConfig
|
14
|
-
from invenio_records_resources.services import FileServiceConfig
|
15
|
-
try:
|
16
|
-
from invenio_drafts_resources.services.records.uow import ParentRecordCommitOp
|
17
|
-
except ImportError:
|
18
|
-
from invenio_records_resources.services.uow import (
|
19
|
-
RecordCommitOp as ParentRecordCommitOp,
|
20
|
-
)
|
21
|
-
|
22
|
-
from invenio_records_resources.services.records.components import ServiceComponent
|
23
|
-
|
24
|
-
|
25
|
-
class OwnersComponent(ServiceComponent):
|
26
|
-
def create(self, identity, *, record, **kwargs):
|
27
|
-
"""Create handler."""
|
28
|
-
self.add_owner(identity, record)
|
29
|
-
|
30
|
-
def add_owner(self, identity, record, commit=False):
|
31
|
-
if not hasattr(identity, "id") or not isinstance(identity.id, int):
|
32
|
-
return
|
33
|
-
|
34
|
-
owners = getattr(record.parent, "owners", None)
|
35
|
-
if owners is not None:
|
36
|
-
user = User.query.filter_by(id=identity.id).first()
|
37
|
-
record.parent.owners.add(user)
|
38
|
-
if commit:
|
39
|
-
self.uow.register(ParentRecordCommitOp(record.parent))
|
40
|
-
|
41
|
-
def update(self, identity, *, record, **kwargs):
|
42
|
-
"""Update handler."""
|
43
|
-
self.add_owner(identity, record, commit=True)
|
44
|
-
|
45
|
-
def update_draft(self, identity, *, record, **kwargs):
|
46
|
-
"""Update handler."""
|
47
|
-
self.add_owner(identity, record, commit=True)
|
48
|
-
|
49
|
-
def search_drafts(self, identity, search, params, **kwargs):
|
50
|
-
new_term = RecordOwners().query_filter(identity)
|
51
|
-
if new_term:
|
52
|
-
return search.filter(new_term)
|
53
|
-
return search
|
54
|
-
|
55
|
-
|
56
|
-
from datetime import datetime
|
57
|
-
|
58
|
-
|
59
|
-
class DateIssuedComponent(ServiceComponent):
|
60
|
-
def publish(self, identity, data=None, record=None, errors=None, **kwargs):
|
61
|
-
"""Create a new record."""
|
62
|
-
if "dateIssued" not in record["metadata"]:
|
63
|
-
record["metadata"]["dateIssued"] = datetime.today().strftime("%Y-%m-%d")
|
64
|
-
|
65
|
-
class CFRegistry:
|
66
|
-
def __init__(self):
|
67
|
-
self.custom_field_names = defaultdict(list)
|
68
|
-
|
69
|
-
def lookup(self, record_type: Type[Record]):
|
70
|
-
if record_type not in self.custom_field_names:
|
71
|
-
for fld in inspect.getmembers(record_type, lambda x: isinstance(x, CustomFieldsMixin)):
|
72
|
-
self.custom_field_names[record_type].append(fld[1])
|
73
|
-
return self.custom_field_names[record_type]
|
74
|
-
|
75
|
-
cf_registry = CFRegistry()
|
76
|
-
|
77
|
-
class CustomFieldsComponent(ServiceComponent):
|
78
|
-
def create(self, identity, data=None, record=None, **kwargs):
|
79
|
-
"""Create a new record."""
|
80
|
-
self._set_cf_to_record(record, data)
|
81
|
-
|
82
|
-
def update(self, identity, data=None, record=None, **kwargs):
|
83
|
-
"""Update a record."""
|
84
|
-
self._set_cf_to_record(record, data)
|
85
|
-
|
86
|
-
def _set_cf_to_record(self, record, data):
|
87
|
-
for cf in cf_registry.lookup(type(record)):
|
88
|
-
if isinstance(cf, CustomFields):
|
89
|
-
setattr(record, cf.attr_name, data.get(cf.key, {}))
|
90
|
-
elif isinstance(cf, InlinedCustomFields):
|
91
|
-
config = current_app.config.get(cf.config_key, {})
|
92
|
-
for c in config:
|
93
|
-
record[c.name] =data.get(c.name)
|
94
|
-
|
95
|
-
def process_service_configs(service_config):
|
96
|
-
|
97
|
-
processed_components = []
|
98
|
-
target_classes = {
|
99
|
-
RDMRecordServiceConfig,
|
100
|
-
DraftsRecordServiceConfig,
|
101
|
-
RecordsRecordServiceConfig,
|
102
|
-
FileServiceConfig
|
103
|
-
}
|
104
|
-
|
105
|
-
for end_index, cls in enumerate(type(service_config).mro()):
|
106
|
-
if cls in target_classes:
|
107
|
-
break
|
108
|
-
|
109
|
-
# We need this because if the "build" function is present in service_config,
|
110
|
-
# there are two service_config instances in the MRO (Method Resolution Order) output.
|
111
|
-
start_index = 2 if hasattr(service_config, "build") else 1
|
112
|
-
|
113
|
-
service_configs = type(service_config).mro()[start_index:end_index + 1]
|
114
|
-
for config in service_configs:
|
115
|
-
|
116
|
-
if hasattr(config, "build"):
|
117
|
-
config = config.build(current_app)
|
118
|
-
|
119
|
-
if hasattr(config, 'components'):
|
120
|
-
component_property = config.components
|
121
|
-
if isinstance(component_property, list):
|
122
|
-
processed_components.extend(component_property)
|
123
|
-
elif isinstance(component_property, tuple):
|
124
|
-
processed_components.extend(list (component_property))
|
125
|
-
else:
|
126
|
-
raise ValueError(f"{config} component's definition is not supported")
|
127
|
-
|
128
|
-
return processed_components
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/readers/__init__.py
RENAMED
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/readers/attachments.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/readers/service.py
RENAMED
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/semi_asynchronous.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/writers/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/datastreams/writers/service.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/dumpers/edtf_interval.py
RENAMED
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/entity_resolvers/__init__.py
RENAMED
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/entity_resolvers/proxies.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/relations/__init__.py
RENAMED
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/relations/internal.py
RENAMED
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/relations/pid_relation.py
RENAMED
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/systemfields/__init__.py
RENAMED
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/systemfields/featured_file.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/systemfields/mapping.py
RENAMED
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/systemfields/owner.py
RENAMED
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/systemfields/record_status.py
RENAMED
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/systemfields/selectors.py
RENAMED
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/records/systemfields/synthetic.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/config/link_conditions.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/custom_fields/__init__.py
RENAMED
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/custom_fields/mappings.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/expansions/__init__.py
RENAMED
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/expansions/service.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/facets/facet_groups_names.py
RENAMED
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/facets/nested_facet.py
RENAMED
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/facets/year_histogram.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/permissions/__init__.py
RENAMED
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/permissions/generators.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/relations/__init__.py
RENAMED
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/relations/components.py
RENAMED
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/relations/mapping.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/schema/i18n_validation.py
RENAMED
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/schema/marshmallow.py
RENAMED
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/schema/oneofschema.py
RENAMED
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/schema/polymorphic.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/services/schema/validation.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime/translations/default_translations.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/oarepo_runtime.egg-info/dependency_links.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/tests/marshmallow_to_json/test_datacite_ui_schema.py
RENAMED
File without changes
|
{oarepo_runtime-1.5.89 → oarepo_runtime-1.5.90}/tests/marshmallow_to_json/test_simple_schema.py
RENAMED
File without changes
|
File without changes
|