Skip to content

Commit

Permalink
Fix stuff and add support for Sequence
Browse files Browse the repository at this point in the history
  • Loading branch information
rnag committed Dec 1, 2024
1 parent 4f1a5a3 commit 0a6e25e
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 8 deletions.
16 changes: 16 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@
History
=======

0.32.0 (2024-11-30)
-------------------

**Features and Improvements**

- Add support for ``Sequence`` and ``MutableSequence``

**Bugfixes**

* Fix a bug in ``ParseError``
* Fix issue when field in ``EnvWizard`` is a dataclass, and
instance of that type is passed to constructor
* Fix some logic in ``parsers.py`` that was relying on all parsers
being subclass of :class:`AbstractParser`, as they can now be a function
instead.

0.31.0 (2024-11-30)
-------------------

Expand Down
3 changes: 0 additions & 3 deletions dataclass_wizard/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ def message(self) -> str:
obj_type=self.name(self.obj_type))

if self.json_object:
self.kwargs['json_object'] = json.dumps(self.json_object, default=str)
from .utils.json_util import safe_dumps
self.kwargs['json_object'] = safe_dumps(self.json_object)

Expand Down Expand Up @@ -297,7 +296,6 @@ def message(self) -> str:

msg = self._TEMPLATE.format(
cls=self.class_name,
# json_string=json.dumps(self.obj, default=str),
json_string=safe_dumps(self.obj),
fields=self.fields,
json_key=self.json_key)
Expand Down Expand Up @@ -335,7 +333,6 @@ def message(self) -> str:
msg = self._TEMPLATE.format(
cls=self.class_name,
nested_cls=self.nested_class_name,
# json_string=json.dumps(self.obj, default=str),
json_string=safe_dumps(self.obj),
field=self.field_name,
o=self.obj,
Expand Down
14 changes: 14 additions & 0 deletions dataclass_wizard/loaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
NamedTupleMeta,
SupportsFloat, AnyStr, Text, Callable, Optional
)
from collections.abc import Sequence as ABCSequence, MutableSequence as ABCMutableSequence

from uuid import UUID

from .abstractions import AbstractLoader, AbstractParser
Expand Down Expand Up @@ -438,6 +440,18 @@ def get_parser_for_annotation(cls, ann_type: Type[T],
cls.get_parser_for_annotation
)

elif base_type in (ABCSequence, ABCMutableSequence):

load_hook = cls.load_to_iterable
# Re-map to list, e.g. `Sequence[int]` -> `list[int]`
ann_type = list[ann_type] if (
ann_type := get_args(ann_type)[0]) else list

return IterableParser(
base_cls, extras, ann_type, load_hook,
cls.get_parser_for_annotation
)

else:
load_hook = hooks.get(base_type)

Expand Down
13 changes: 8 additions & 5 deletions dataclass_wizard/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,8 @@ class TupleParser(AbstractParser[Type[S], S]):
__slots__ = ('hook',
'elem_parsers',
'total_count',
'required_count')
'required_count',
'elem_types')

# Base type of the object which is instantiable
# ex. `Tuple[bool, int]` -> `tuple`
Expand All @@ -378,7 +379,7 @@ def __post_init__(self, cls: Type,

# Get the subscripted values
# ex. `Tuple[bool, int]` -> (bool, int)
elem_types = get_args(self.base_type)
self.elem_types = elem_types = get_args(self.base_type)
self.base_type = get_origin(self.base_type)
# A collection with a parser for each type argument
elem_parsers = tuple(get_parser(t, cls, extras)
Expand All @@ -391,7 +392,8 @@ def __post_init__(self, cls: Type,
# this should exclude the parsers for `Optional` or `Union` types
# that have `None` in the list of args.
self.required_count: int = len(tuple(p for p in elem_parsers
if None not in p))
if not isinstance(p, AbstractParser)
or None not in p))

self.elem_parsers = elem_parsers or None

Expand All @@ -410,8 +412,9 @@ def __call__(self, o: S) -> S:
desired_count = str(self.total_count)

# self.elem_parsers can be None at this moment
elem_parsers_types = [p.base_type for p in self.elem_parsers] \
if self.elem_parsers else []
elem_parsers_types = [getattr(p, 'base_type', tp) for p, tp in
zip(self.elem_parsers, self.elem_types)] \
if self.elem_parsers else self.elem_types

raise ParseError(
e, o, elem_parsers_types,
Expand Down

0 comments on commit 0a6e25e

Please sign in to comment.