Skip to content

Commit 1d01044

Browse files
committed
Moved addition of include_type_field to resource to simplify codecs and ensure it is listed first
1 parent 9ce59ab commit 1d01044

7 files changed

Lines changed: 107 additions & 103 deletions

File tree

src/odin/codecs/dict_codec.py

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from odin import ResourceAdapter, bases, resources
2-
from odin.utils import getmeta
32

43
TYPE_SERIALIZERS = {}
54

@@ -10,12 +9,8 @@ def __init__(self, include_virtual_fields=True, include_type_field=True):
109
self.include_type_field = include_type_field
1110

1211
def default(self, o):
13-
if isinstance(o, (resources.ResourceBase, ResourceAdapter)):
14-
meta = getmeta(o)
15-
obj = o.to_dict(self.include_virtual_fields)
16-
if self.include_type_field:
17-
obj[meta.type_field] = meta.resource_name
18-
return obj
12+
if isinstance(o, resources.ResourceBase | ResourceAdapter):
13+
return o.to_dict(self.include_virtual_fields, self.include_type_field)
1914
elif isinstance(o, bases.ResourceIterable):
2015
return list(o)
2116
elif o.__class__ in TYPE_SERIALIZERS:
@@ -35,9 +30,11 @@ def encode(self, o):
3530
3631
:param d: Dict to load
3732
38-
:param resource: A resource type, resource name or list of resources and names to use as the base for creating a
39-
resource. If a list is supplied the first item will be used if a resource type is not supplied.
40-
:raises ValidationError: During building of the object graph and issues discovered are raised as a ValidationError.
33+
:param resource: A resource type, resource name or list of resources and names to
34+
use as the base for creating a resource. If a list is supplied the first item
35+
will be used if a resource type is not supplied.
36+
:raises ValidationError: During building of the object graph and issues discovered
37+
are raised as a ValidationError.
4138
4239
"""
4340

@@ -46,8 +43,9 @@ def dump(resource, cls=OdinEncoder, **kwargs):
4643
"""
4744
Dump a resource structure into a nested :py:class:`dict`.
4845
49-
While a resource includes a *to_dict* method this method is not recursive. The dict codec recursively iterates
50-
through the resource structure to produce a full dict. This is useful for testing for example.
46+
While a resource includes a *to_dict* method this method is not recursive. The dict
47+
codec recursively iterates through the resource structure to produce a full dict.
48+
This is useful for testing for example.
5149
5250
:param resource: The root resource to dump
5351
:param cls: Encoder class to utilise
@@ -66,13 +64,13 @@ def _encode_dict(dct):
6664
return {k: _encode(o) for k, o in dct.items()}
6765

6866
def _encode(o):
69-
if isinstance(o, (list, tuple)):
67+
if isinstance(o, list | tuple):
7068
return _encode_list(o)
7169
elif isinstance(o, dict):
7270
return _encode_dict(o)
7371
else:
7472
o = _default(o)
75-
if isinstance(o, (list, tuple, dict)):
73+
if isinstance(o, list | tuple | dict):
7674
return _encode(o)
7775
return o
7876

src/odin/codecs/json_codec.py

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
from odin import ResourceAdapter, bases, resources, serializers
77
from odin.exceptions import CodecDecodeError, CodecEncodeError
8-
from odin.utils import getmeta
98

109
LIST_TYPES = (bases.ResourceIterable, typing.ValuesView, typing.KeysView)
1110
JSON_TYPES = {
@@ -18,9 +17,7 @@
1817

1918

2019
class OdinEncoder(json.JSONEncoder):
21-
"""
22-
Encoder for Odin resources.
23-
"""
20+
"""Encoder for Odin resources."""
2421

2522
def __init__(
2623
self, include_virtual_fields=True, include_type_field=True, *args, **kwargs
@@ -30,12 +27,8 @@ def __init__(
3027
self.include_type_field = include_type_field
3128

3229
def default(self, o):
33-
if isinstance(o, (resources.ResourceBase, ResourceAdapter)):
34-
meta = getmeta(o)
35-
obj = o.to_dict(self.include_virtual_fields)
36-
if self.include_type_field:
37-
obj[meta.type_field] = meta.resource_name
38-
return obj
30+
if isinstance(o, resources.ResourceBase | ResourceAdapter):
31+
return o.to_dict(self.include_virtual_fields, self.include_type_field)
3932

4033
elif isinstance(o, LIST_TYPES):
4134
return list(o)
@@ -53,11 +46,12 @@ def load(fp, resource=None, full_clean=True, default_to_not_supplied=False):
5346
See :py:meth:`loads` for more details of the loading operation.
5447
5548
:param fp: a file pointer to read JSON data from.
56-
:param resource: A resource type, resource name or list of resources and names to use as the base for creating a
57-
resource. If a list is supplied the first item will be used if a resource type is not supplied.
49+
:param resource: A resource type, resource name or list of resources and names to
50+
use as the base for creating a resource. If a list is supplied the first item
51+
will be used if a resource type is not supplied.
5852
:param full_clean: Do a full clean of the object as part of the loading process.
59-
:param default_to_not_supplied: Used for loading partial resources. Any fields not supplied are replaced with
60-
NOT_SUPPLIED.
53+
:param default_to_not_supplied: Used for loading partial resources. Any fields not
54+
supplied are replaced with NOT_SUPPLIED.
6155
:returns: A resource object or object graph of resources loaded from file.
6256
6357
"""
@@ -68,18 +62,21 @@ def loads(s, resource=None, full_clean=True, default_to_not_supplied=False):
6862
"""
6963
Load from a JSON encoded string.
7064
71-
If a ``resource`` value is supplied it is used as the base resource for the supplied JSON. I one is not supplied a
72-
resource type field ``$`` is used to obtain the type represented by the dictionary. A ``ValidationError`` will be
73-
raised if either of these values are supplied and not compatible. It is valid for a type to be supplied in the file
74-
to be a child object from within the inheritance tree.
65+
If a ``resource`` value is supplied it is used as the base resource for the
66+
supplied JSON. I one is not supplied a resource type field ``$`` is used to obtain
67+
the type represented by the dictionary. A ``ValidationError`` will be raised if
68+
either of these values are supplied and not compatible. It is valid for a type to
69+
be supplied in the file to be a child object from within the inheritance tree.
7570
7671
:param s: String to load and parse.
77-
:param resource: A resource type, resource name or list of resources and names to use as the base for creating a
78-
resource. If a list is supplied the first item will be used if a resource type is not supplied.
72+
:param resource: A resource type, resource name or list of resources and names to
73+
use as the base for creating a resource. If a list is supplied the first item
74+
will be used if a resource type is not supplied.
7975
:param full_clean: Do a full clean of the object as part of the loading process.
80-
:param default_to_not_supplied: Used for loading partial resources. Any fields not supplied are replaced with
81-
NOT_SUPPLIED.
82-
:returns: A resource object or object graph of resources parsed from supplied string.
76+
:param default_to_not_supplied: Used for loading partial resources. Any fields not
77+
supplied are replaced with NOT_SUPPLIED.
78+
:returns: A resource object or object graph of resources parsed from supplied
79+
string.
8380
8481
"""
8582
try:
@@ -95,7 +92,8 @@ def dump(resource, fp, cls=OdinEncoder, **kwargs):
9592
Dump to a JSON encoded file.
9693
9794
:param resource: The root resource to dump to a JSON encoded file.
98-
:param cls: Encoder to use serializing to a string; default is the :py:class:`OdinEncoder`.
95+
:param cls: Encoder to use serializing to a string; default is the
96+
:py:class:`OdinEncoder`.
9997
:param fp: The file pointer that represents the output file.
10098
10199
"""
@@ -110,7 +108,8 @@ def dumps(resource, cls=OdinEncoder, **kwargs):
110108
Dump to a JSON encoded string.
111109
112110
:param resource: The root resource to dump to a JSON encoded file.
113-
:param cls: Encoder to use serializing to a string; default is the :py:class:`OdinEncoder`.
111+
:param cls: Encoder to use serializing to a string; default is the
112+
:py:class:`OdinEncoder`.
114113
:returns: JSON encoded string.
115114
116115
"""

src/odin/codecs/msgpack_codec.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Codec to load/save Message Pack (msgpack) documents."""
2+
23
import datetime
34
import uuid
45
from typing import TextIO
@@ -11,7 +12,6 @@
1112
) from None # noqa
1213

1314
from odin import ResourceAdapter, bases, resources, serializers
14-
from odin.utils import getmeta
1515

1616
TYPE_SERIALIZERS = {
1717
datetime.date: serializers.date_iso_format,
@@ -31,11 +31,8 @@ def __init__(self, include_virtual_fields: bool = True, *args, **kwargs):
3131
self.include_virtual_fields = include_virtual_fields
3232

3333
def default(self, o):
34-
if isinstance(o, (resources.ResourceBase, ResourceAdapter)):
35-
meta = getmeta(o)
36-
obj = o.to_dict(self.include_virtual_fields)
37-
obj[meta.type_field] = meta.resource_name
38-
return obj
34+
if isinstance(o, resources.ResourceBase | ResourceAdapter):
35+
return o.to_dict(self.include_virtual_fields, True)
3936

4037
elif isinstance(o, bases.ResourceIterable):
4138
return list(o)
@@ -55,7 +52,8 @@ def load(
5552
See :py:meth:`loads` for more details of the loading operation.
5653
5754
:param fp: a file pointer to read MessagePack data from.
58-
:param resource: A resource instance or a resource name to use as the base for creating a resource.
55+
:param resource: A resource instance or a resource name to use as the base for
56+
creating a resource.
5957
:param full_clean: Do a full clean of the object as part of the loading process.
6058
:param default_to_not_supplied:
6159
:returns: A resource object or object graph of resources loaded from file.
@@ -73,16 +71,20 @@ def loads(
7371
):
7472
"""Load from a MessagePack encoded string/bytes.
7573
76-
If a ``resource`` value is supplied it is used as the base resource for the supplied MessagePack data. I one is not
77-
supplied a resource type field ``$`` is used to obtain the type represented by the dictionary. A ``ValidationError``
78-
will be raised if either of these values are supplied and not compatible. It is valid for a type to be supplied in
79-
the file to be a child object from within the inheritance tree.
74+
If a ``resource`` value is supplied it is used as the base resource for the
75+
supplied MessagePack data. I one is not supplied a resource type field ``$`` is
76+
used to obtain the type represented by the dictionary. A ``ValidationError``
77+
will be raised if either of these values are supplied and not compatible. It is
78+
valid for a type to be supplied in the file to be a child object from within the
79+
inheritance tree.
8080
8181
:param s: String to load and parse.
82-
:param resource: A resource instance or a resource name to use as the base for creating a resource.
82+
:param resource: A resource instance or a resource name to use as the base for
83+
creating a resource.
8384
:param full_clean: Do a full clean of the object as part of the loading process.
8485
:param default_to_not_supplied:
85-
:returns: A resource object or object graph of resources parsed from supplied string.
86+
:returns: A resource object or object graph of resources parsed from supplied
87+
string.
8688
"""
8789
return resources.build_object_graph(
8890
msgpack.loads(s), resource, full_clean, False, default_to_not_supplied
@@ -94,13 +96,14 @@ def dump(
9496
fp: TextIO,
9597
cls=OdinPacker,
9698
include_virtual_fields: bool = True,
97-
**kwargs
99+
**kwargs,
98100
):
99101
"""Dump to a MessagePack encoded file.
100102
101103
:param include_virtual_fields:
102104
:param resource: The root resource to dump to a MessagePack encoded file.
103-
:param cls: Encoder to use serializing to a string; default is the :py:class:`OdinEncoder`.
105+
:param cls: Encoder to use serializing to a string; default is the
106+
:py:class:`OdinEncoder`.
104107
:param fp: The file pointer that represents the output file.
105108
"""
106109
fp.write(cls(include_virtual_fields, **kwargs).pack(resource))
@@ -110,13 +113,14 @@ def dumps(
110113
resource: resources.ResourceBase,
111114
cls=OdinPacker,
112115
include_virtual_fields: bool = True,
113-
**kwargs
116+
**kwargs,
114117
):
115118
"""Dump to a MessagePack encoded string.
116119
117120
:param include_virtual_fields:
118121
:param resource: The root resource to dump to a MessagePack encoded file.
119-
:param cls: Encoder to use serializing to a string; default is the :py:class:`OdinEncoder`.
122+
:param cls: Encoder to use serializing to a string; default is the
123+
:py:class:`OdinEncoder`.
120124
:returns: MessagePack encoded string.
121125
"""
122126
return cls(include_virtual_fields, **kwargs).pack(resource)

src/odin/codecs/toml_codec.py

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from odin import ResourceAdapter, resources
44
from odin.exceptions import CodecDecodeError
55
from odin.resources import ResourceBase
6-
from odin.utils import getmeta
76

87
try:
98
import toml
@@ -21,17 +20,20 @@ def load(fp, resource=None, full_clean=True, default_to_not_supplied=False):
2120
"""
2221
Load a resource from a TOML encoded file.
2322
24-
If a ``resource`` value is supplied it is used as the base resource for the supplied YAML. If one is not
25-
supplied, a resource type field ``$`` is used to obtain the type represented by the dictionary. A
26-
``ValidationError`` will be raised if either of these values are supplied and not compatible. It is valid for a
27-
type to be supplied in the file to be a child object from within the inheritance tree.
23+
If a ``resource`` value is supplied it is used as the base resource for the
24+
supplied YAML. If one is not supplied, a resource type field ``$`` is used to
25+
obtain the type represented by the dictionary. A ``ValidationError`` will be
26+
raised if either of these values are supplied and not compatible. It is valid for a
27+
type to be supplied in the file to be a child object from within the inheritance
28+
tree.
2829
2930
:param fp: a file pointer to read TOML data format.
30-
:param resource: A resource type, resource name or list of resources and names to use as the base for creating a
31-
resource. If a list is supplied the first item will be used if a resource type is not supplied.
31+
:param resource: A resource type, resource name or list of resources and names to
32+
use as the base for creating a resource. If a list is supplied the first item
33+
will be used if a resource type is not supplied.
3234
:param full_clean: Do a full clean of the object as part of the loading process.
33-
:param default_to_not_supplied: Used for loading partial resources. Any fields not supplied are replaced with
34-
NOT_SUPPLIED.
35+
:param default_to_not_supplied: Used for loading partial resources. Any fields not
36+
supplied are replaced with NOT_SUPPLIED.
3537
:returns: A resource object or object graph of resources loaded from file.
3638
3739
"""
@@ -53,17 +55,19 @@ def load(fp, resource=None, full_clean=True, default_to_not_supplied=False):
5355
def loads(s, resource=None, full_clean=True, default_to_not_supplied=False):
5456
"""Load a resource from a TOML encoded string.
5557
56-
If a ``resource`` value is supplied it is used as the base resource for the supplied YAML. If one is not
57-
supplied, a resource type field ``$`` is used to obtain the type represented by the dictionary. A
58-
``ValidationError`` will be raised if either of these values are supplied and not compatible. It is valid for a
59-
type to be supplied in the file to be a child object from within the inheritance tree.
58+
If a ``resource`` value is supplied it is used as the base resource for the
59+
supplied YAML. If one is not supplied, a resource type field ``$`` is used to
60+
obtain the type represented by the dictionary. A ``ValidationError`` will be raised
61+
if either of these values are supplied and not compatible. It is valid for a type
62+
to be supplied in the file to be a child object from within the inheritance tree.
6063
6164
:param s: a string containing TOML.
62-
:param resource: A resource type, resource name or list of resources and names to use as the base for creating a
63-
resource. If a list is supplied the first item will be used if a resource type is not supplied.
65+
:param resource: A resource type, resource name or list of resources and names to
66+
use as the base for creating a resource. If a list is supplied the first item
67+
will be used if a resource type is not supplied.
6468
:param full_clean: Do a full clean of the object as part of the loading process.
65-
:param default_to_not_supplied: Used for loading partial resources. Any fields not supplied are replaced with
66-
NOT_SUPPLIED.
69+
:param default_to_not_supplied: Used for loading partial resources. Any fields not
70+
supplied are replaced with NOT_SUPPLIED.
6771
:returns: A resource object or object graph of resources loaded from file.
6872
6973
"""
@@ -97,11 +101,7 @@ def __init__(
97101
self.include_type_field = include_type_field
98102

99103
def resource_to_dict(self, v):
100-
resource_dict = v.to_dict(self.include_virtual_fields)
101-
if self.include_type_field:
102-
meta = getmeta(v)
103-
resource_dict[meta.type_field] = meta.resource_name
104-
return resource_dict
104+
return v.to_dict(self.include_virtual_fields, self.include_type_field)
105105

106106
def dump_value(self, v):
107107
if isinstance(v, ResourceBase | ResourceAdapter):
@@ -133,7 +133,8 @@ def dump(
133133
134134
:param resource: The root resource to dump to a JSON encoded file.
135135
:param fp: The file pointer that represents the output file.
136-
:param encoder: Encoder to use serializing to a string; default is the :py:class:`OdinEncoder`.
136+
:param encoder: Encoder to use serializing to a string; default is the
137+
:py:class:`OdinEncoder`.
137138
:param include_virtual_fields: Include virtual fields in the output
138139
:param kwargs: Additional keyword arguments for the encoder.
139140
"""
@@ -154,7 +155,8 @@ def dumps(
154155
"""Dump to a TOML encoded file.
155156
156157
:param resource: The root resource to dump to a JSON encoded file.
157-
:param encoder: Encoder to use serializing to a string; default is the :py:class:`OdinEncoder`.
158+
:param encoder: Encoder to use serializing to a string; default is the
159+
:py:class:`OdinEncoder`.
158160
:param include_virtual_fields: Include virtual fields in the output
159161
:param kwargs: Additional keyword arguments for the encoder.
160162
:returns: TOML encoded string.

0 commit comments

Comments
 (0)