Skip to content

Commit

Permalink
Merge branch 'refactoring'
Browse files Browse the repository at this point in the history
  • Loading branch information
Fatal1ty committed Feb 9, 2022
2 parents 63ecf6d + 8d3a62c commit ea6597f
Show file tree
Hide file tree
Showing 47 changed files with 1,968 additions and 1,241 deletions.
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ jobs:
pip install --upgrade pip
pip install .
pip install -r requirements-dev.txt
pip install tzdata
- name: Run tests with coverage
run: pytest --cov=mashumaro --cov=tests
- name: Upload Coverage
Expand Down
212 changes: 140 additions & 72 deletions README.md

Large diffs are not rendered by default.

217 changes: 217 additions & 0 deletions docs/2to3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
Migration from version 2 to version 3
--------------------------------------------------------------------------------

* [Moving serialization format mixins](#moving-serialization-format-mixins)
* [Removing `use_bytes` parameter](#removing-use_bytes-parameter)
* [Removing `use_enum` parameter](#removing-use_enum-parameter)
* [Removing `use_datetime` parameter](#removing-use_datetime-parameter)
* [Changing `from_json`, `from_msgpack`, `from_yaml` signature](#changing-from_json-from_msgpack-from_yaml-signature)
* [Changing `to_json`, `to_msgpack`, `to_yaml` signature](#changing-to_json-to_msgpack-to_yaml-signature)

### Moving serialization format mixins

You might need to alter your imports if you've used the following mixins:
* `DataClassJSONMixin`
* `DataClassMessagePackMixin`
* `DataClassYAMLMixin`

Tne new imports will look like this:

```python
from mashumaro.mixins.json import DataClassJSONMixin
from mashumaro.mixins.msgpack import DataClassMessagePackMixin
from mashumaro.mixins.yaml import DataClassYAMLMixin
```

### Removing `use_bytes` parameter

Parameter `use_bytes` was removed from `from_dict` / `to_dict` methods.
If you've used it to pass bytes or bytearray values as is, you can do the same
with [dialect](https://github.com/Fatal1ty/mashumaro#dialects) and
[pass_through](https://github.com/Fatal1ty/mashumaro/tree/master#passing-field-values-as-is)
features:

```python
from dataclasses import dataclass

from mashumaro import DataClassDictMixin, pass_through
from mashumaro.config import BaseConfig, ADD_DIALECT_SUPPORT
from mashumaro.dialect import Dialect

class BytesDialect(Dialect):
serialization_strategy = {
bytes: pass_through,
bytearray: pass_through,
}

@dataclass
class A(DataClassDictMixin):
bytes: bytes
bytearray: bytearray

class Config(BaseConfig):
code_generation_options = [ADD_DIALECT_SUPPORT]

obj = A(b"\x00", bytearray(b"\x00"))
dct = {"bytes": b"\x00", "bytearray": bytearray(b"\x00")}

assert A.from_dict(dct, dialect=BytesDialect) == obj
assert obj.to_dict(dialect=BytesDialect) == dct
```

### Removing `use_enum` parameter

Parameter `use_enum` was removed from `from_dict` / `to_dict` methods.
If you've used it to pass enum values as is, you can do the same
with [dialect](https://github.com/Fatal1ty/mashumaro#dialects) and
[pass_through](https://github.com/Fatal1ty/mashumaro/tree/master#passing-field-values-as-is)
features:

```python
from dataclasses import dataclass
from enum import Enum

from mashumaro import DataClassDictMixin, pass_through
from mashumaro.config import BaseConfig, ADD_DIALECT_SUPPORT
from mashumaro.dialect import Dialect

class MyEnum(Enum):
a = 1
b = 2

class EnumDialect(Dialect):
serialization_strategy = {
MyEnum: pass_through,
}

@dataclass
class A(DataClassDictMixin):
my_enum: MyEnum

class Config(BaseConfig):
code_generation_options = [ADD_DIALECT_SUPPORT]

obj = A(MyEnum.a)
dct = {"my_enum": MyEnum.a}

assert A.from_dict(dct, dialect=EnumDialect) == obj
assert obj.to_dict(dialect=EnumDialect) == dct
```

### Removing `use_datetime` parameter

Parameter `use_datetime` was removed from `from_dict` / `to_dict` methods.
If you've used it to pass datetime, date and time values as is, you can do
the same with [dialect](https://github.com/Fatal1ty/mashumaro#dialects) and
[pass_through](https://github.com/Fatal1ty/mashumaro/tree/master#passing-field-values-as-is)
features:

```python
from dataclasses import dataclass
from datetime import date, datetime, time

from mashumaro import DataClassDictMixin, pass_through
from mashumaro.config import BaseConfig, ADD_DIALECT_SUPPORT
from mashumaro.dialect import Dialect

class DatetimeDialect(Dialect):
serialization_strategy = {
date: pass_through,
datetime: pass_through,
time: pass_through,
}

@dataclass
class A(DataClassDictMixin):
datetime: datetime
date: date
time: time

class Config(BaseConfig):
code_generation_options = [ADD_DIALECT_SUPPORT]

obj = A(
datetime=datetime(2022, 2, 9, 12, 0),
date=date(2022, 2, 9),
time=time(12, 0),
)
dct = {
"datetime": datetime(2022, 2, 9, 12, 0),
"date": date(2022, 2, 9),
"time": time(12, 0),
}

assert A.from_dict(dct, dialect=DatetimeDialect) == obj
assert obj.to_dict(dialect=DatetimeDialect) == dct
```

### Changing `from_json`, `from_msgpack`, `from_yaml` signature

In version 2 methods `from_json`, `from_msgpack`, `from_yaml` had the following
signature:
```python
@classmethod
def from_*( # where * is json, msgpack, yaml
cls,
data: EncodedData,
decoder: Decoder = ...,
dict_params: Mapping = ...,
**decoder_kwargs,
)
```

In version 3 these methods have a slightly different signature:
```python
@classmethod
def from_*( # where * is json, msgpack, yaml
cls,
data: EncodedData,
decoder: Decoder = ...,
**from_dict_kwargs,
)
```

As you can see, the `dict_params` positional argument was removed in order
to pass keyword arguments to underlying `from_dict` method. Decoder parameters
were removed because they can be easily passed to decoder using
a lambda function, a partial object or something else:

```python
A.from_json(
data,
decoder=lambda data: json.loads(data, parse_float=decimal.Decimal),
)
```

### Changing `to_json`, `to_msgpack`, `to_yaml` signature

In version 2 methods `to_json`, `to_msgpack`, `to_yaml` had the following
signature:
```python
def to_*( # where * is json, msgpack, yaml
self,
encoder: Encoder = ...
dict_params: Mapping = ...,
**encoder_kwargs,
)
```

In version 3 these methods have a slightly different signature:
```python
def to_*( # where * is json, msgpack, yaml
self,
encoder: Encoder = ...,
**to_dict_kwargs,
)
```

As you can see, the `dict_params` positional argument was removed in order
to pass keyword arguments to underlying `to_dict` method. Encoder parameters
were removed because they can be easily passed to encoder using
a lambda function, a partial object or something else:

```python
dataclass_obj.to_json(
encoder=lambda data: json.dumps(data, ensure_ascii=False),
)
```
11 changes: 3 additions & 8 deletions mashumaro/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
from mashumaro.exceptions import MissingField
from mashumaro.helper import field_options
from mashumaro.serializer.base.dict import DataClassDictMixin
from mashumaro.serializer.json import DataClassJSONMixin
from mashumaro.serializer.msgpack import DataClassMessagePackMixin
from mashumaro.serializer.yaml import DataClassYAMLMixin
from mashumaro.helper import field_options, pass_through
from mashumaro.mixins.dict import DataClassDictMixin

__all__ = [
"MissingField",
"DataClassDictMixin",
"DataClassJSONMixin",
"DataClassMessagePackMixin",
"DataClassYAMLMixin",
"field_options",
"pass_through",
]
2 changes: 1 addition & 1 deletion mashumaro/config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Any, Callable, Dict, List, Optional, Type, Union

from mashumaro.core.const import PEP_586_COMPATIBLE
from mashumaro.dialect import Dialect
from mashumaro.meta.macros import PEP_586_COMPATIBLE
from mashumaro.types import SerializationStrategy

if PEP_586_COMPATIBLE:
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import re


def parse_timezone(s: str):
def parse_timezone(s: str) -> datetime.timezone:
regexp = re.compile(r"^UTC(([+-][0-2][0-9]):([0-5][0-9]))?$")
match = regexp.match(s)
if not match:
Expand Down
File renamed without changes.
Loading

0 comments on commit ea6597f

Please sign in to comment.