Skip to content

Commit 6c31d1a

Browse files
committed
Typing improvements
1 parent 349bbdd commit 6c31d1a

25 files changed

Lines changed: 359 additions & 383 deletions

src/odin/codecs/toml_codec.py

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Dict, Optional, Sequence, Type, Union
1+
from collections.abc import Sequence
22

33
from odin import ResourceAdapter, resources
44
from odin.exceptions import CodecDecodeError
@@ -21,10 +21,10 @@ def load(fp, resource=None, full_clean=True, default_to_not_supplied=False):
2121
"""
2222
Load a resource from a TOML encoded file.
2323
24-
If a ``resource`` value is supplied it is used as the base resource for the supplied YAML. If one is not supplied a
25-
resource type field ``$`` is used to 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 type to be supplied in the file
27-
to be a child object from within the inheritance tree.
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.
2828
2929
:param fp: a file pointer to read TOML data format.
3030
:param resource: A resource type, resource name or list of resources and names to use as the base for creating a
@@ -53,10 +53,10 @@ def load(fp, resource=None, full_clean=True, default_to_not_supplied=False):
5353
def loads(s, resource=None, full_clean=True, default_to_not_supplied=False):
5454
"""Load a resource from a TOML encoded string.
5555
56-
If a ``resource`` value is supplied it is used as the base resource for the supplied YAML. If one is not supplied a
57-
resource type field ``$`` is used to obtain the type represented by the dictionary. A ``ValidationError`` will be
58-
raised if either of these values are supplied and not compatible. It is valid for a type to be supplied in the file
59-
to be a child object from within the inheritance tree.
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.
6060
6161
:param s: a string containing TOML.
6262
:param resource: A resource type, resource name or list of resources and names to use as the base for creating a
@@ -90,7 +90,7 @@ def __init__(
9090
include_virtual_fields: bool = True,
9191
include_type_field: bool = True,
9292
*args,
93-
**kwargs
93+
**kwargs,
9494
):
9595
super().__init__(*args, **kwargs)
9696
self.include_virtual_fields = include_virtual_fields
@@ -104,7 +104,7 @@ def resource_to_dict(self, v):
104104
return resource_dict
105105

106106
def dump_value(self, v):
107-
if isinstance(v, (ResourceBase, ResourceAdapter)):
107+
if isinstance(v, ResourceBase | ResourceAdapter):
108108
resource_dict = self.resource_to_dict(v)
109109
return self.dump_inline_table(resource_dict)
110110

@@ -113,21 +113,21 @@ def dump_value(self, v):
113113
return super().dump_value(v)
114114

115115

116-
RT = Union[
117-
ResourceBase,
118-
ResourceAdapter,
119-
Sequence[ResourceBase],
120-
Sequence[ResourceAdapter],
121-
Dict,
122-
]
116+
RT = (
117+
ResourceBase
118+
| ResourceAdapter
119+
| Sequence[ResourceBase]
120+
| Sequence[ResourceAdapter]
121+
| dict,
122+
)
123123

124124

125125
def dump(
126126
resource: RT,
127127
fp,
128-
encoder: Optional[Type[OdinEncoder]] = None,
128+
encoder: type[OdinEncoder] | None = None,
129129
include_virtual_fields: bool = True,
130-
**kwargs
130+
**kwargs,
131131
):
132132
"""Dump to a TOML encoded file.
133133
@@ -139,17 +139,17 @@ def dump(
139139
"""
140140
encoder = (encoder or OdinEncoder)(include_virtual_fields, **kwargs)
141141

142-
if isinstance(resource, (ResourceBase, ResourceAdapter)):
142+
if isinstance(resource, ResourceBase | ResourceAdapter):
143143
resource = encoder.resource_to_dict(resource)
144144

145145
toml.dump(resource, fp, encoder)
146146

147147

148148
def dumps(
149149
resource: RT,
150-
encoder: Optional[Type[OdinEncoder]] = None,
150+
encoder: type[OdinEncoder] | None = None,
151151
include_virtual_fields: bool = True,
152-
**kwargs
152+
**kwargs,
153153
) -> str:
154154
"""Dump to a TOML encoded file.
155155
@@ -161,7 +161,7 @@ def dumps(
161161
"""
162162
encoder = (encoder or OdinEncoder)(include_virtual_fields, **kwargs)
163163

164-
if isinstance(resource, (ResourceBase, ResourceAdapter)):
164+
if isinstance(resource, ResourceBase | ResourceAdapter):
165165
resource = encoder.resource_to_dict(resource)
166166

167167
return toml.dumps(resource, encoder)

src/odin/codecs/yaml_codec.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Codec to load/save Yaml documents."""
2+
23
from io import StringIO
3-
from typing import TextIO, Union
4+
from typing import TextIO
45

56
from odin import ResourceAdapter, bases, resources
67
from odin.exceptions import CodecEncodeError
@@ -31,7 +32,7 @@ def __init__(
3132
include_virtual_fields: bool = True,
3233
include_type_field: bool = True,
3334
*args,
34-
**kwargs
35+
**kwargs,
3536
):
3637
SafeDumper.__init__(self, stream, *args, **kwargs)
3738
self.include_virtual_fields = include_virtual_fields
@@ -51,17 +52,17 @@ def represent_resource(self, data):
5152

5253

5354
def load(
54-
fp: Union[TextIO, str],
55+
fp: TextIO | str,
5556
resource: resources.ResourceBase = None,
5657
full_clean: bool = True,
5758
default_to_not_supplied: bool = False,
5859
):
5960
"""Load a resource from a YAML encoded file.
6061
61-
If a ``resource`` value is supplied it is used as the base resource for the supplied YAML. I one is not supplied a
62-
resource type field ``$`` is used to obtain the type represented by the dictionary. A ``ValidationError`` will be
63-
raised if either of these values are supplied and not compatible. It is valid for a type to be supplied in the file
64-
to be a child object from within the inheritance tree.
62+
If a ``resource`` value is supplied it is used as the base resource for the supplied YAML. I one is not supplied
63+
a resource type field ``$`` is used to obtain the type represented by the dictionary. A ``ValidationError`` will
64+
be raised if either of these values are supplied and not compatible. It is valid for a type to be supplied in the
65+
file to be a child object from within the inheritance tree.
6566
6667
:param fp: a file pointer to read YAML data fromat.
6768
:param resource: A resource type, resource name or list of resources and names to use as the base for creating a

src/odin/contrib/geo/datatypes.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import math
2-
from typing import Tuple
32

43
__all__ = ("latitude", "longitude", "latlng", "point")
54

65

7-
def to_dms(value: float, absolute: bool = False) -> Tuple[float, float, float]:
6+
def to_dms(value: float, absolute: bool = False) -> tuple[float, float, float]:
87
"""
98
Split a float value into DMS (degree, minute, second) parts
109
@@ -22,7 +21,7 @@ def to_dms(value: float, absolute: bool = False) -> Tuple[float, float, float]:
2221
return (-degree if invert else degree), minute, second
2322

2423

25-
def to_dm(value: float, absolute: bool = False) -> Tuple[float, float]:
24+
def to_dm(value: float, absolute: bool = False) -> tuple[float, float]:
2625
"""
2726
Split a float value into DM (degree, minute) parts
2827
@@ -45,7 +44,7 @@ class latitude(float): # NoQA
4544

4645
def __new__(cls, x):
4746
lat = float.__new__(cls, x)
48-
if lat > 90.0 or lat < -90.0:
47+
if lat > 90.0 or lat < -90.0: # noqa: PLR2004
4948
raise ValueError(f"not in range -90.0 -> 90.0: '{x}'")
5049
return lat
5150

@@ -61,7 +60,7 @@ class longitude(float): # NoQA
6160

6261
def __new__(cls, x):
6362
lng = float.__new__(cls, x)
64-
if lng > 180.0 or lng < -180.0:
63+
if lng > 180.0 or lng < -180.0: # noqa: PLR2004
6564
raise ValueError(f"not in range -180.0 -> 180.0: '{x}'")
6665
return lng
6766

@@ -70,14 +69,12 @@ def __str__(self):
7069
return result + ("W" if self < 0 else "E")
7170

7271

73-
class latlng(tuple):
74-
"""
75-
Combination latitude and longitude value.
76-
"""
72+
class latlng(tuple): # noqa: N801 - This is for consistency
73+
"""Combination latitude and longitude value."""
7774

7875
def __new__(cls, *args):
7976
# Unpack a tuple, list or latlng instance.
80-
if len(args) == 1 and isinstance(args[0], (tuple, list)):
77+
if len(args) == 1 and isinstance(args[0], tuple | list):
8178
args = args[0]
8279
try:
8380
lat, lng = args
@@ -100,13 +97,14 @@ def __str__(self):
10097
return "({}, {})".format(*self)
10198

10299

103-
class point(tuple):
104-
"""
105-
A point in cartesian space. This type can be either 2D (on a plain) or 3D (includes a z-axis).
100+
class point(tuple): # noqa: N801 - This is for consistency
101+
"""A point in cartesian space.
102+
103+
This type can be either 2D (on a plain) or 3D (includes a z-axis).
106104
"""
107105

108106
def __new__(cls, *args):
109-
if len(args) == 1 and isinstance(args[0], (tuple, list)):
107+
if len(args) == 1 and isinstance(args[0], tuple | list):
110108
args = args[0]
111109
if len(args) in (2, 3):
112110
return tuple.__new__(cls, (float(x) for x in args))
@@ -130,7 +128,7 @@ def z(self):
130128

131129
@property
132130
def is_3d(self):
133-
return len(self) == 3
131+
return len(self) == 3 # noqa: PLR2004
134132

135133
def __repr__(self):
136134
return ("point({}, {}, {})" if self.is_3d else "point({}, {})").format(*self)

src/odin/contrib/json_schema/__init__.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
"""JSON schema support for Odin."""
2+
23
import json
3-
from typing import Any, Dict, Final, List, Sequence, TextIO, Tuple, Type, Union
4+
from collections.abc import Sequence
5+
from typing import Any, Final, TextIO
46

57
import odin
68
import odin.validators
@@ -42,14 +44,14 @@ class JSONSchema:
4244
"""JSON Schema representation of an Odin resource."""
4345

4446
def __init__(
45-
self, resource: Type[ResourceBase], *, require_type_field: bool = True
47+
self, resource: type[ResourceBase], *, require_type_field: bool = True
4648
):
4749
self.resource = resource
4850
self.require_type_field = require_type_field
4951

5052
self.defs = {}
5153

52-
def to_dict(self) -> Dict[str, Any]:
54+
def to_dict(self) -> dict[str, Any]:
5355
"""Convert the schema to a dictionary."""
5456
meta = getmeta(self.resource)
5557

@@ -62,7 +64,7 @@ def to_dict(self) -> Dict[str, Any]:
6264

6365
return schema
6466

65-
def _resource_to_schema(self, meta: ResourceOptions) -> Dict[str, Any]:
67+
def _resource_to_schema(self, meta: ResourceOptions) -> dict[str, Any]:
6668
"""Convert a resource to a JSON schema."""
6769
schema = {
6870
"type": "object",
@@ -79,14 +81,14 @@ def _required_fields(self, meta: ResourceOptions) -> Sequence[str]:
7981
required.append(meta.type_field)
8082
return required
8183

82-
def _fields_to_properties(self, meta: ResourceOptions) -> Dict[str, Any]:
84+
def _fields_to_properties(self, meta: ResourceOptions) -> dict[str, Any]:
8385
"""Convert a set of fields to JSON schema properties."""
8486
properties = {meta.type_field: {"const": meta.resource_name}}
8587
for field in meta.fields:
8688
properties[field.name] = self._field_to_schema(field)
8789
return properties
8890

89-
def _field_to_schema(self, field: odin.Field) -> Dict[str, Any]:
91+
def _field_to_schema(self, field: odin.Field) -> dict[str, Any]:
9092
"""Convert a field to a JSON schema."""
9193
if isinstance(field, odin.CompositeField):
9294
schema = self._composite_field_to_schema(field)
@@ -103,9 +105,7 @@ def _field_to_schema(self, field: odin.Field) -> Dict[str, Any]:
103105

104106
return schema
105107

106-
def _field_type(
107-
self, field: odin.Field
108-
) -> Tuple[Union[str, List[str]], Dict[str, Any]]:
108+
def _field_type(self, field: odin.Field) -> tuple[str | list[str], dict[str, Any]]:
109109
"""Get the type of a field."""
110110

111111
field_type = type(field)
@@ -139,7 +139,7 @@ def _field_type(
139139

140140
return ([type_name, "null"] if field.null else type_name), schema
141141

142-
def _composite_field_to_schema(self, field: odin.CompositeField) -> Dict[str, Any]:
142+
def _composite_field_to_schema(self, field: odin.CompositeField) -> dict[str, Any]:
143143
"""Convert a composite field to a JSON schema."""
144144

145145
# Handle abstract resources
@@ -165,7 +165,7 @@ def _composite_field_to_schema(self, field: odin.CompositeField) -> Dict[str, An
165165

166166
return schema
167167

168-
def _schema_def(self, resource: Type[ResourceBase]) -> Dict[str, str]:
168+
def _schema_def(self, resource: type[ResourceBase]) -> dict[str, str]:
169169
"""Convert a resource to a JSON schema definition."""
170170
meta = getmeta(resource)
171171
ref = meta.resource_name
@@ -175,13 +175,13 @@ def _schema_def(self, resource: Type[ResourceBase]) -> Dict[str, str]:
175175
return {"$ref": f"#/$defs/{ref}"}
176176

177177

178-
def dumps(resource: Type[ResourceBase]) -> str:
178+
def dumps(resource: type[ResourceBase]) -> str:
179179
"""Dump a JSON schema for the given resource."""
180180
schema = JSONSchema(resource).to_dict()
181181
return json.dumps(schema, indent=2)
182182

183183

184-
def dump(resource: Type[ResourceBase], fp: TextIO):
184+
def dump(resource: type[ResourceBase], fp: TextIO):
185185
"""Dump a JSON schema for the given resource."""
186186
schema = JSONSchema(resource).to_dict()
187187
json.dump(schema, fp, indent=2)

src/odin/contrib/rich/theme.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
"""Rich Theme definition."""
2-
from typing import Dict
32

43
from rich import get_console
54
from rich.style import Style
65
from rich.theme import Theme
76

8-
ODIN_STYLES: Dict[str, Style] = {
7+
ODIN_STYLES: dict[str, Style] = {
98
"odin.resource.name": Style(color="bright_cyan"),
109
"odin.resource.error": Style(color="red", underline=True),
1110
"odin.field.name": Style(color="bright_blue"),

src/odin/contrib/rich/validation_tree.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Integration with Rich for nicer CLI's!"""
2-
from typing import Iterable, Union
2+
3+
from collections.abc import Iterable
34

45
from rich.tree import Tree
56

@@ -11,7 +12,7 @@ def _all_str(iterable: Iterable) -> bool:
1112
return all(isinstance(item, str) for item in iterable)
1213

1314

14-
def _validation_error_to_tree(error_messages: Union[list, dict], tree: Tree):
15+
def _validation_error_to_tree(error_messages: list | dict, tree: Tree):
1516
"""Internal recursive method."""
1617

1718
if isinstance(error_messages, dict):

0 commit comments

Comments
 (0)