oarepo-runtime 1.5.28__py3-none-any.whl → 1.5.30__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -27,13 +27,15 @@ class LocalizedUIJSONSerializer(MarshmallowSerializer):
27
27
  self.object_schema_cls = object_schema_cls
28
28
  self.list_schema_cls = list_schema_cls
29
29
 
30
- def dump_obj(self, obj):
30
+ def dump_obj(self, obj, *args, **kwargs):
31
31
  """Dump the object using object schema class."""
32
- return self.object_schema_cls(
33
- context={**self.schema_context, "locale": get_locale()}
34
- ).dump(obj)
32
+ ctx = {**self.schema_context, "locale": get_locale()}
33
+ if "extra_context" in kwargs:
34
+ ctx |= kwargs["extra_context"]
35
35
 
36
- def dump_list(self, obj_list):
36
+ return self.object_schema_cls(context=ctx).dump(obj)
37
+
38
+ def dump_list(self, obj_list, *args, **kwargs):
37
39
  """Dump the list of objects."""
38
40
  ctx = {
39
41
  "object_schema_cls": self.object_schema_cls,
@@ -41,6 +43,9 @@ class LocalizedUIJSONSerializer(MarshmallowSerializer):
41
43
  ctx.update(self.schema_context)
42
44
  ctx["locale"] = get_locale()
43
45
 
46
+ if "extra_context" in kwargs:
47
+ ctx |= kwargs["extra_context"]
48
+
44
49
  if self.list_schema_cls is None:
45
50
  return self.object_schema_cls(context=self.schema_context).dump(
46
51
  obj_list, many=True
@@ -0,0 +1,192 @@
1
+ import typing
2
+
3
+ from marshmallow import Schema, ValidationError
4
+
5
+
6
+ class OneOfSchema(Schema):
7
+ """
8
+ This is a special kind of schema that actually multiplexes other schemas
9
+ based on object type. When serializing values, it uses get_obj_type() method
10
+ to get object type name. Then it uses `type_schemas` name-to-Schema mapping
11
+ to get schema for that particular object type, serializes object using that
12
+ schema and adds an extra "type" field with name of object type.
13
+ Deserialization is reverse.
14
+
15
+ Example:
16
+
17
+ class Foo(object):
18
+ def __init__(self, foo):
19
+ self.foo = foo
20
+
21
+ class Bar(object):
22
+ def __init__(self, bar):
23
+ self.bar = bar
24
+
25
+ class FooSchema(marshmallow.Schema):
26
+ foo = marshmallow.fields.String(required=True)
27
+
28
+ @marshmallow.post_load
29
+ def make_foo(self, data, **kwargs):
30
+ return Foo(**data)
31
+
32
+ class BarSchema(marshmallow.Schema):
33
+ bar = marshmallow.fields.Integer(required=True)
34
+
35
+ @marshmallow.post_load
36
+ def make_bar(self, data, **kwargs):
37
+ return Bar(**data)
38
+
39
+ class MyUberSchema(marshmallow.OneOfSchema):
40
+ type_schemas = {
41
+ 'foo': FooSchema,
42
+ 'bar': BarSchema,
43
+ }
44
+
45
+ def get_obj_type(self, obj):
46
+ if isinstance(obj, Foo):
47
+ return 'foo'
48
+ elif isinstance(obj, Bar):
49
+ return 'bar'
50
+ else:
51
+ raise Exception('Unknown object type: %s' % repr(obj))
52
+
53
+ MyUberSchema().dump([Foo(foo='hello'), Bar(bar=123)], many=True)
54
+ # => [{'type': 'foo', 'foo': 'hello'}, {'type': 'bar', 'bar': 123}]
55
+
56
+ You can control type field name added to serialized object representation by
57
+ setting `type_field` class property.
58
+ """
59
+
60
+ type_field = "type"
61
+ type_field_remove = True
62
+ type_schemas: typing.Mapping[str, typing.Union[typing.Type[Schema], Schema]] = {}
63
+
64
+ def get_obj_type(self, obj):
65
+ """Returns name of the schema during dump() calls, given the object
66
+ being dumped."""
67
+ return obj.__class__.__name__
68
+
69
+ def get_data_type(self, data):
70
+ """Returns name of the schema during load() calls, given the data being
71
+ loaded. Defaults to looking up `type_field` in the data."""
72
+ data_type = data.get(self.type_field)
73
+ if self.type_field in data and self.type_field_remove:
74
+ data.pop(self.type_field)
75
+ return data_type
76
+
77
+ def dump(self, obj, *, many=None, **kwargs):
78
+ errors = {}
79
+ result_data = []
80
+ result_errors = {}
81
+ many = self.many if many is None else bool(many)
82
+ if not many:
83
+ result = result_data = self._dump(obj, **kwargs)
84
+ else:
85
+ for idx, o in enumerate(obj):
86
+ try:
87
+ result = self._dump(o, **kwargs)
88
+ result_data.append(result)
89
+ except ValidationError as error:
90
+ result_errors[idx] = error.normalized_messages()
91
+ result_data.append(error.valid_data)
92
+
93
+ result = result_data
94
+ errors = result_errors
95
+
96
+ if not errors:
97
+ return result
98
+ else:
99
+ exc = ValidationError(errors, data=obj, valid_data=result)
100
+ raise exc
101
+
102
+ def _dump(self, obj, *, update_fields=True, **kwargs):
103
+ obj_type = self.get_obj_type(obj)
104
+ if obj_type is None:
105
+ return (
106
+ None,
107
+ {"_schema": "Unknown object class: %s" % obj.__class__.__name__},
108
+ )
109
+
110
+ type_schema = self.type_schemas.get(obj_type)
111
+ if not type_schema:
112
+ return None, {"_schema": "Unsupported object type: %s" % obj_type}
113
+
114
+ schema = type_schema if isinstance(type_schema, Schema) else type_schema()
115
+
116
+ schema.context.update(getattr(self, "context", {}))
117
+
118
+ result = schema.dump(obj, many=False, **kwargs)
119
+ if result is not None:
120
+ result[self.type_field] = obj_type
121
+ return result
122
+
123
+ def load(self, data, *, many=None, partial=None, unknown=None, **kwargs):
124
+ errors = {}
125
+ result_data = []
126
+ result_errors = {}
127
+ many = self.many if many is None else bool(many)
128
+ if partial is None:
129
+ partial = self.partial
130
+ if not many:
131
+ try:
132
+ result_data = self._load(
133
+ data, partial=partial, unknown=unknown, **kwargs
134
+ )
135
+ except ValidationError as error:
136
+ result_errors = error.normalized_messages()
137
+ result_data = error.valid_data
138
+ else:
139
+ for idx, item in enumerate(data):
140
+ try:
141
+ result = self._load(item, partial=partial, **kwargs)
142
+ result_data.append(result)
143
+ except ValidationError as error:
144
+ result_errors[idx] = error.normalized_messages()
145
+ result_data.append(error.valid_data)
146
+
147
+ result = result_data
148
+ errors = result_errors
149
+
150
+ if not errors:
151
+ return result
152
+ else:
153
+ exc = ValidationError(errors, data=data, valid_data=result)
154
+ raise exc
155
+
156
+ def _load(self, data, *, partial=None, unknown=None, **kwargs):
157
+ if not isinstance(data, dict):
158
+ raise ValidationError({"_schema": "Invalid data type: %s" % data})
159
+
160
+ data = dict(data)
161
+ unknown = unknown or self.unknown
162
+ data_type = self.get_data_type(data)
163
+
164
+ if data_type is None:
165
+ raise ValidationError(
166
+ {self.type_field: ["Missing data for required field."]}
167
+ )
168
+
169
+ try:
170
+ type_schema = self.type_schemas.get(data_type)
171
+ except TypeError as error:
172
+ # data_type could be unhashable
173
+ raise ValidationError(
174
+ {self.type_field: ["Invalid value: %s" % data_type]}
175
+ ) from error
176
+ if not type_schema:
177
+ raise ValidationError(
178
+ {self.type_field: ["Unsupported value: %s" % data_type]}
179
+ )
180
+
181
+ schema = type_schema if isinstance(type_schema, Schema) else type_schema()
182
+
183
+ schema.context.update(getattr(self, "context", {}))
184
+
185
+ return schema.load(data, many=False, partial=partial, unknown=unknown, **kwargs)
186
+
187
+ def validate(self, data, *, many=None, partial=None):
188
+ try:
189
+ self.load(data, many=many, partial=partial)
190
+ except ValidationError as ve:
191
+ return ve.messages
192
+ return {}
@@ -1,8 +1,8 @@
1
1
  from functools import cached_property
2
2
 
3
3
  import marshmallow as ma
4
- from marshmallow_oneofschema import OneOfSchema
5
-
4
+ #from marshmallow_oneofschema import OneOfSchema
5
+ from oarepo_runtime.services.schema.oneofschema import OneOfSchema
6
6
 
7
7
  class PolymorphicSchema(OneOfSchema):
8
8
  type_field_remove = False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: oarepo-runtime
3
- Version: 1.5.28
3
+ Version: 1.5.30
4
4
  Summary: A set of runtime extensions of Invenio repository
5
5
  Description-Content-Type: text/markdown
6
6
  License-File: LICENSE
@@ -66,7 +66,7 @@ oarepo_runtime/records/systemfields/selectors.py,sha256=VlbV3FKP2h3PLU7H4-YsI4qr
66
66
  oarepo_runtime/records/systemfields/synthetic.py,sha256=zRsQdekcgsrD9R2UuI2kgVLjyQMIT8j3HAYav_e-xfM,4238
67
67
  oarepo_runtime/resources/__init__.py,sha256=v8BGrOTu_FjKzd0eozV7Q4GoGxyfybsL2cI-tbP5Pys,185
68
68
  oarepo_runtime/resources/file_resource.py,sha256=Ta3bFce7l0xwqkkOMOEu9mxbB8BbKj5HUHRHmidhnl8,414
69
- oarepo_runtime/resources/localized_ui_json_serializer.py,sha256=4Kle34k-_uu3Y9JJ2vAXcQ9DqYRxXgy-_iZhiFuukmE,1684
69
+ oarepo_runtime/resources/localized_ui_json_serializer.py,sha256=3V9cJaG_e1PMXKVX_wKfBp1LmbeForwHyBNYdyha4uQ,1878
70
70
  oarepo_runtime/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
71
  oarepo_runtime/services/components.py,sha256=9wt9CmoCFA8Utbb8eNA-Mvzo5LCApHT9zHpWIWZNyXY,1506
72
72
  oarepo_runtime/services/generators.py,sha256=V582uA813AIXnFhzqUwakmDgBOI1SQe3XZeJtUXNbwM,872
@@ -100,7 +100,8 @@ oarepo_runtime/services/schema/i18n.py,sha256=myyg0tU8up0BmMt9IESKD91w5KC0V9v8Qa
100
100
  oarepo_runtime/services/schema/i18n_ui.py,sha256=18tA6uA067TP_wcit47hTel2M4hz88wYtwBgaeZDrew,1880
101
101
  oarepo_runtime/services/schema/i18n_validation.py,sha256=fyMTi2Rw-KiHv7c7HN61zGxRVa9sAjAEEkAL5wUyKNo,236
102
102
  oarepo_runtime/services/schema/marshmallow.py,sha256=LmcSxvbZ9jIhkNHCqqxt1SA2UNijoDmIzqli1MkoTrE,1153
103
- oarepo_runtime/services/schema/polymorphic.py,sha256=CkvXVUiXbrsLWFgoNnjjpUviQyzRMCmpsD3GWfV0WZA,494
103
+ oarepo_runtime/services/schema/oneofschema.py,sha256=X_pXzrkYcLGGAtGN1qltrz45OzD_atrJHkHkp3L01xg,6660
104
+ oarepo_runtime/services/schema/polymorphic.py,sha256=f9yC7MGVynAFGM0fXIq0NbqGJxI65Xpi8GaM2ZM4c6Q,561
104
105
  oarepo_runtime/services/schema/ui.py,sha256=caRca4vuUVoLew3gkhbPQYGaLXB8C67E5jxz45-9zkE,3663
105
106
  oarepo_runtime/services/schema/validation.py,sha256=fahqKGDdIYWux5ZeoljrEe8VD2fDZR9VpfvYmTYAmpw,1050
106
107
  oarepo_runtime/translations/default_translations.py,sha256=060GBlA1ghWxfeumo6NqxCCZDb-6OezOuF6pr-_GEOQ,104
@@ -114,9 +115,9 @@ oarepo_runtime/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
114
115
  oarepo_runtime/utils/functools.py,sha256=gKS9YZtlIYcDvdNA9cmYO00yjiXBYV1jg8VpcRUyQyg,1324
115
116
  oarepo_runtime/utils/path.py,sha256=V1NVyk3m12_YLbj7QHYvUpE1wScO78bYsX1LOLeXDkI,3108
116
117
  tests/pkg_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
117
- oarepo_runtime-1.5.28.dist-info/LICENSE,sha256=h2uWz0OaB3EN-J1ImdGJZzc7yvfQjvHVYdUhQ-H7ypY,1064
118
- oarepo_runtime-1.5.28.dist-info/METADATA,sha256=ck-L-b49r3ffcCAjvGjsUxW173E2ay8T_-sx7q1LYkY,4680
119
- oarepo_runtime-1.5.28.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
120
- oarepo_runtime-1.5.28.dist-info/entry_points.txt,sha256=QrlXAKuPDVBinaSh_v3yO9_Nb9ZNmJCJ0VFcCW-z0Jg,327
121
- oarepo_runtime-1.5.28.dist-info/top_level.txt,sha256=bHhlkT1_RQC4IkfTQCqA3iN4KCB6cSFQlsXpQMSP-bE,21
122
- oarepo_runtime-1.5.28.dist-info/RECORD,,
118
+ oarepo_runtime-1.5.30.dist-info/LICENSE,sha256=h2uWz0OaB3EN-J1ImdGJZzc7yvfQjvHVYdUhQ-H7ypY,1064
119
+ oarepo_runtime-1.5.30.dist-info/METADATA,sha256=-RxYSie_VM-QdwV_3we-zToS-EeWEmGaYgG4HYVaOvw,4680
120
+ oarepo_runtime-1.5.30.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
121
+ oarepo_runtime-1.5.30.dist-info/entry_points.txt,sha256=QrlXAKuPDVBinaSh_v3yO9_Nb9ZNmJCJ0VFcCW-z0Jg,327
122
+ oarepo_runtime-1.5.30.dist-info/top_level.txt,sha256=bHhlkT1_RQC4IkfTQCqA3iN4KCB6cSFQlsXpQMSP-bE,21
123
+ oarepo_runtime-1.5.30.dist-info/RECORD,,