Skip to content

Commit

Permalink
fix dataclass convert issue
Browse files Browse the repository at this point in the history
  • Loading branch information
voidZXL committed Jan 24, 2024
1 parent 5ce7f73 commit f62733d
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 15 deletions.
14 changes: 7 additions & 7 deletions docs/en/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ utype is a data type declaration and parsing library based on Python type annota

Currently, Python does not have the mechanism to guarantee types at runtime, so when we write a function, we often need to perform type assertion and constraint checking on parameters before we can start writing the actual logic. such as
```python
def login(username, password):
def signup(username, password):
import re
if not isinstance(username, str) \
or not re.match('[0-9a-zA-Z]{3,20}', username):
Expand All @@ -43,18 +43,18 @@ However, if we can declare all types and constraints in the parameters, enforce
from utype.types import Annotated # compat 3.7+

@utype.parse
def login(
def signup(
username: Annotated[str, utype.Param(regex='[0-9a-zA-Z]{3,20}')],
password: Annotated[str, utype.Param(min_length=6)]
):
# # you can directly start coding
return username, password

print(login('alice', 123456))
print(signup('alice', 123456))
('alice', '123456')

try:
login('@invalid', 123456)
signup('@invalid', 123456)
except utype.exc.ParseError as e:
print(e)
"""
Expand All @@ -68,18 +68,18 @@ However, if we can declare all types and constraints in the parameters, enforce
import utype

@utype.parse
def login(
def signup(
username: str = utype.Param(regex='[0-9a-zA-Z]{3,20}'),
password: str = utype.Param(min_length=6)
):
# # you can directly start coding
return username, password

print(login('alice', 123456))
print(signup('alice', 123456))
('alice', '123456')

try:
login('@invalid', 123456)
signup('@invalid', 123456)
except utype.exc.ParseError as e:
print(e)
"""
Expand Down
1 change: 1 addition & 0 deletions docs/mkdocs.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ theme:
- toc.follow
- navigation.tracking
- navigation.top
- content.code.copy

repo_name: utilmeta/utype
repo_url: https://github.com/utilmeta/utype
Expand Down
1 change: 1 addition & 0 deletions docs/mkdocs.zh.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ theme:
- toc.follow
- navigation.tracking
- navigation.top
- content.code.copy

repo_name: utilmeta/utype
repo_url: https://github.com/utilmeta/utype
Expand Down
14 changes: 7 additions & 7 deletions docs/zh/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ utype 是一个基于 Python 类型注解的数据类型声明与解析库,能

目前 Python 没有在运行时解析类型与校验约束的机制,所以当我们编写一个函数时,往往需要先对参数进行类型断言和约束校验等操作,然后才能开始编写真正的逻辑,否则很可能会在运行时发生异常错误,如
```python
def login(username, password):
def signup(username, password):
import re
if not isinstance(username, str) \
or not re.match('[0-9a-zA-Z]{3,20}', username):
Expand All @@ -44,18 +44,18 @@ def login(username, password):
from utype.types import Annotated

@utype.parse
def login(
def signup(
username: Annotated[str, utype.Param(regex='[0-9a-zA-Z]{3,20}')],
password: Annotated[str, utype.Param(min_length=6)]
):
# 你可以直接开始编写逻辑了
return username, password

print(login('alice', 123456))
print(signup('alice', 123456))
('alice', '123456')

try:
login('@invalid', 123456)
signup('@invalid', 123456)
except utype.exc.ParseError as e:
print(e)
"""
Expand All @@ -69,18 +69,18 @@ def login(username, password):
import utype

@utype.parse
def login(
def signup(
username: str = utype.Param(regex='[0-9a-zA-Z]{3,20}'),
password: str = utype.Param(min_length=6)
):
# 你可以直接开始编写逻辑了
return username, password

print(login('alice', 123456))
print(signup('alice', 123456))
('alice', '123456')

try:
login('@invalid', 123456)
signup('@invalid', 123456)
except utype.exc.ParseError as e:
print(e)
"""
Expand Down
10 changes: 10 additions & 0 deletions tests/test_cls.py
Original file line number Diff line number Diff line change
Expand Up @@ -996,3 +996,13 @@ class LogicalUser(DataClass):
assert res == {'oneOf': [{'type': 'object', 'properties':
{'name': {'type': 'string', 'maxLength': 10}, 'age': {'type': 'integer'}}, 'required': ['name', 'age']},
{'type': 'array', 'prefixItems': [{'type': 'string'}, {'type': 'integer'}]}]}

def test_pass(self):
class A(Schema):
a: str = utype.Field(no_output=True)

class B(Schema):
a_or: A

b = B(a_or=[A(a=3)])
assert b.a_or.a == '3'
2 changes: 1 addition & 1 deletion utype/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
register_transformer = TypeTransformer.registry.register


VERSION = (0, 4, 0, None)
VERSION = (0, 4, 1, None)


def _get_version():
Expand Down
10 changes: 10 additions & 0 deletions utype/parser/cls.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,8 +574,18 @@ def init_dataclass(
detector=lambda cls: isinstance(getattr(cls, "__parser__", None), ClassParser),
)
def transform_dataclass(transformer: TypeTransformer, data, cls):
if isinstance(data, (list, tuple)) and not transformer.options.no_explicit_cast:
if data:
if transformer.options.no_data_loss and len(data) > 1:
raise TypeError
data = data[0]
# otherwise the data will become dict then fill the dataclass
if type(data) == cls:
return data

if transformer.options.allow_subclasses:
if isinstance(data, cls):
# subclass
return data

return init_dataclass(cls, data, context=transformer.context)

0 comments on commit f62733d

Please sign in to comment.