Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
lnielsen committed Sep 9, 2020
1 parent 8b05cf7 commit f991b10
Show file tree
Hide file tree
Showing 9 changed files with 232 additions and 25 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"restructuredtext.confPath": "${workspaceFolder}/docs"
}
15 changes: 10 additions & 5 deletions invenio_records/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ class RecordBase(dict):
Allows extensions (like system fields) to be registered on the record.
"""

def __init__(self, data, model=None):
def __init__(self, data, model=None, **kwargs):
"""Initialize instance with dictionary data and SQLAlchemy model.
:param data: Dict with record metadata.
:param model: :class:`~invenio_records.models.RecordMetadata` instance.
"""
self.model = model
for e in self._extensions:
e.pre_init(self, data, model=model)
e.pre_init(self, data, model=model, **kwargs)
super(RecordBase, self).__init__(data or {})

@property
Expand Down Expand Up @@ -217,6 +217,7 @@ def loads(cls, data, loader=None):
# The method is named with in plural to align with dumps (which is
# named with s even if it should probably have been called "dump"
# instead.
loader = loader or cls.dumper
record = loader.load(data, cls)

# Run post load extensions
Expand Down Expand Up @@ -263,7 +264,7 @@ def create(cls, data, id_=None, **kwargs):
:returns: A new :class:`Record` instance.
"""
with db.session.begin_nested():
record = cls(data)
record = cls(data, **kwargs)

if cls.send_signals:
before_record_insert.send(
Expand All @@ -272,7 +273,11 @@ def create(cls, data, id_=None, **kwargs):
)

# Validate also encodes the data
json = record._validate(**kwargs)
validate_args = {}
validate_args['format_checker'] = kwargs.pop(
'format_checker', None)
validate_args['validator'] = kwargs.pop('validator', None)
json = record._validate(**validate_args)

# Thus, we pass the encoded JSON directly to the model.
record.model = cls.model_cls(id=id_, json=json)
Expand Down Expand Up @@ -476,7 +481,7 @@ def revert(self, revision_id):
# Here we explicitly set the json column in order to not
# encode/decode the json data via the ``data`` property.
self.model.json = revision.model.json
flag_modified(self.model.json, 'json')
flag_modified(self.model, 'json')

db.session.merge(self.model)

Expand Down
2 changes: 0 additions & 2 deletions invenio_records/dumpers/elasticsearch.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,11 @@ def load(self, data, record_cls):
# Next, extract model fields
fields_data = {}
for field, (key, cast) in self._model_fields.items():
print(field)
fields_data[field] = self._load_model_field(key, cast, data)

# Initialize model if an id was provided.
if fields_data.get('id') is not None:
fields_data['data'] = data
print(fields_data)
model = record_cls.model_cls(**fields_data)
else:
model = None
Expand Down
4 changes: 2 additions & 2 deletions invenio_records/extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
class ExtensionMixin:
"""Defines the methods needed by an extension."""

def pre_init(self, record, data, model=None):
def pre_init(self, record, data, model=None, **kwargs):
"""Called when a new record instance is initialized.
Called when a new record is instantiated (i.e. during all
Expand All @@ -29,7 +29,7 @@ def pre_init(self, record, data, model=None):
def pre_dump(self, record, dumper=None):
"""Called before a record is dumped."""

def post_load(self, record):
def post_load(self, record, loader=None):
"""Called after a record is loaded."""

def post_create(self, record):
Expand Down
30 changes: 30 additions & 0 deletions invenio_records/systemfields/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"""The core of the system fields implementation."""

import inspect
from copy import deepcopy

from ..extensions import ExtensionMixin, RecordExtension, RecordMeta

Expand Down Expand Up @@ -60,6 +61,21 @@ class SystemField(ExtensionMixin):
API.
"""

def __init__(self):
"""Initialise the field."""
# The attribute is set by __set_name__ which is called by the metaclass
# during construction.
self._attr_name = None

@property
def attr_name(self):
"""Property to access the assigned class attribute name.
:returns: ``None`` if field is not assigned, otherwise the class
attribute name.
"""
return self._attr_name

#
# Data descriptor definition
#
Expand Down Expand Up @@ -110,6 +126,20 @@ def __set__(self, instance, value):
"""
raise AttributeError()

def __set_name__(self, owner, name):
"""Inject the class attribute name into the field.
This ensures that a field has access to the attribute name used on the
class. In the following example, the attribute name ``schema`` would be
set in the ``ConstantField`` object instance.
.. code-block:: python
class MyRecord(Record, SystemFieldsMixin):
schema = ConstantField(...)
"""
self._attr_name = name


class SystemFieldsExt(RecordExtension):
"""Record extension for system fields.
Expand Down
2 changes: 1 addition & 1 deletion invenio_records/systemfields/constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def __init__(self, key, value):
self.key = key
self.value = value

def pre_init(self, record, data, model=None):
def pre_init(self, record, data, model=None, **kwargs):
"""Sets the key in the record during record instantiation."""
try:
dict_lookup(data, self.key)
Expand Down
Binary file added test.db
Binary file not shown.
7 changes: 7 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,14 @@ def test_record_replace_refs(testapp, db):
})
testapp.extensions['invenio-records'].loader_cls = json_loader_factory(
JSONResolver(plugins=['demo.json_resolver']))

record.enable_jsonref = False
assert record.replace_refs() == record

record.enable_jsonref = True
out_json = record.replace_refs()
assert out_json != record

expected_json = {
'one': {
'letter': 'A',
Expand Down

0 comments on commit f991b10

Please sign in to comment.