Skip to content

Commit 9e71098

Browse files
authored
Merge pull request #13 from mutating/develop
0.0.12
2 parents 0e45400 + 71277e5 commit 9e71098

12 files changed

Lines changed: 83 additions & 98 deletions

File tree

.github/ISSUE_TEMPLATE/question.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name: Question or consultation
33
about: Ask anything about this project
44
title: ''
5-
labels: guestion
5+
labels: question
66
assignees: pomponchik
77

88
---

.ruff.toml

Lines changed: 0 additions & 4 deletions
This file was deleted.

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ Python type checking tools are usually very complex. In this case, we have throw
2929
- [**String deserialization**](#string-deserialization)
3030

3131

32-
3332
## Why?
3433

3534
It's been a long time since static type checking tools like [`mypy`](https://github.com/python/mypy) for `Python` have been available, and they've become very complex. The typing system has also become noticeably more complicated, providing us with more and more new types of annotations, new syntax and other tools. It seems that `Python` devs procrastinate endlessly, postponing all the really important [`CPyhton`](https://github.com/python/cpython) improvements in order to add more garbage to [`typing`](https://docs.python.org/3/library/typing.html).

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "simtypes"
7-
version = "0.0.11"
7+
version = "0.0.12"
88
authors = [{ name = "Evgeniy Blinov", email = "zheni-b@yandex.ru" }]
99
description = 'Type checking in runtime without stupid games'
1010
readme = "README.md"

simtypes/__init__.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
from simtypes.check import check as check # noqa: F401
2-
from simtypes.from_string import from_string as from_string # noqa: F401
3-
from simtypes.types.ints.natural import NaturalNumber as NaturalNumber # noqa: F401
4-
from simtypes.types.ints.non_negative import NonNegativeInt as NonNegativeInt # noqa: F401
1+
from simtypes.check import check as check
2+
from simtypes.from_string import from_string as from_string
3+
from simtypes.types.ints.natural import NaturalNumber as NaturalNumber
4+
from simtypes.types.ints.non_negative import (
5+
NonNegativeInt as NonNegativeInt,
6+
)

simtypes/check.py

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from inspect import isclass
2-
from unittest.mock import Mock, MagicMock
2+
from unittest.mock import MagicMock, Mock
33

44
try:
55
from types import UnionType # type: ignore[attr-defined, unused-ignore]
@@ -11,48 +11,45 @@
1111
except ImportError: # pragma: no cover
1212
from typing_extensions import TypeIs
1313

14-
from typing import List, Type, Union, Any, get_args, get_origin
14+
from typing import Any, List, Type, Union, get_args, get_origin
1515

1616
from denial import InnerNoneType
1717

1818
from simtypes.typing import ExpectedType
1919

2020

21-
def check(value: Any, type_hint: Type[ExpectedType], strict: bool = False, lists_are_tuples: bool = False, pass_mocks: bool = True) -> TypeIs[ExpectedType]:
22-
if type_hint is Any: # type: ignore[comparison-overlap]
21+
def check(value: Any, type_hint: Type[ExpectedType], strict: bool = False, lists_are_tuples: bool = False, pass_mocks: bool = True) -> TypeIs[ExpectedType]: # noqa: C901, PLR0911, PLR0912
22+
if type_hint is Any or (isinstance(value, (Mock, MagicMock)) and pass_mocks): # type: ignore[comparison-overlap]
2323
return True
2424

25-
elif (isinstance(value, Mock) or isinstance(value, MagicMock)) and pass_mocks:
26-
return True
27-
28-
elif type_hint is None:
25+
if type_hint is None:
2926
return value is None
3027

31-
elif isinstance(type_hint, InnerNoneType):
28+
if isinstance(type_hint, InnerNoneType):
3229
return type_hint == value
3330

3431
origin_type = get_origin(type_hint)
3532

3633
if origin_type is Union or origin_type is UnionType:
3734
return any(check(value, argument, strict=strict, lists_are_tuples=lists_are_tuples) for argument in get_args(type_hint))
3835

39-
elif origin_type is list and strict:
36+
if origin_type is list and strict:
4037
if not isinstance(value, list):
4138
return False
4239
arguments = get_args(type_hint)
4340
if not arguments:
4441
return True
4542
return all(check(subvalue, arguments[0], strict=strict, lists_are_tuples=lists_are_tuples) for subvalue in value)
4643

47-
elif origin_type is dict and strict:
44+
if origin_type is dict and strict:
4845
if not isinstance(value, dict):
4946
return False
5047
arguments = get_args(type_hint)
5148
if not arguments:
5249
return True
5350
return all(check(key, arguments[0], strict=strict, lists_are_tuples=lists_are_tuples) and check(subvalue, arguments[1], strict=strict, lists_are_tuples=lists_are_tuples) for key, subvalue in value.items())
5451

55-
elif origin_type is tuple and strict:
52+
if origin_type is tuple and strict:
5653
types_to_check: List[Union[Type[list], Type[tuple]]] = [tuple] if not lists_are_tuples else [tuple, list] # type: ignore[type-arg]
5754
if all(not isinstance(value, x) for x in types_to_check):
5855
return False
@@ -70,14 +67,13 @@ def check(value: Any, type_hint: Type[ExpectedType], strict: bool = False, lists
7067

7168
return all(check(subvalue, expected_subtype, strict=strict, lists_are_tuples=lists_are_tuples) for subvalue, expected_subtype in zip(value, arguments))
7269

73-
else:
74-
if origin_type is not None:
75-
return isinstance(value, origin_type)
70+
if origin_type is not None:
71+
return isinstance(value, origin_type)
7672

77-
if not isclass(type_hint):
78-
raise ValueError('Type must be a valid type object.')
73+
if not isclass(type_hint):
74+
raise ValueError('Type must be a valid type object.')
7975

80-
if type_hint is tuple and lists_are_tuples:
81-
return isinstance(value, tuple) or isinstance(value, list) # pragma: no cover
76+
if type_hint is tuple and lists_are_tuples:
77+
return isinstance(value, (tuple, list)) # pragma: no cover
8278

83-
return isinstance(value, type_hint)
79+
return isinstance(value, type_hint)

simtypes/from_string.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,32 @@
1-
from typing import List, Tuple, Dict, Type, Optional, Union, Any, get_origin, get_args
2-
from json import loads, JSONDecodeError
3-
from inspect import isclass
4-
from datetime import datetime, date
51
from collections.abc import Hashable
2+
from datetime import date, datetime
3+
from inspect import isclass
4+
from json import JSONDecodeError, loads
5+
from typing import Any, Dict, List, Optional, Tuple, Type, Union, get_args, get_origin
66

77
from simtypes import check
88
from simtypes.typing import ExpectedType
99

1010

11-
def convert_single_value(value: str, expected_type: Type[ExpectedType]) -> ExpectedType:
11+
def convert_single_value(value: str, expected_type: Type[ExpectedType]) -> ExpectedType: # noqa: PLR0912, PLR0911, C901
1212
if expected_type is str:
1313
return value # type: ignore[return-value]
1414

15-
elif expected_type is bool:
15+
if expected_type is bool:
1616
if value in ('True', 'true', 'yes'):
1717
return True # type: ignore[return-value]
18-
elif value in ('False', 'false', 'no'):
18+
if value in ('False', 'false', 'no'):
1919
return False # type: ignore[return-value]
20-
else:
21-
raise TypeError(f'The string "{value}" cannot be interpreted as a boolean value.')
20+
raise TypeError(f'The string "{value}" cannot be interpreted as a boolean value.')
2221

23-
elif expected_type is int:
22+
if expected_type is int:
2423
try:
2524
return int(value) # type: ignore[return-value]
2625
except ValueError as e:
2726
raise TypeError(f'The string "{value}" cannot be interpreted as an integer.') from e
2827

2928
elif expected_type is float:
30-
if value == '∞' or value == '+∞':
29+
if value in {'∞', '+∞'}:
3130
value = 'inf'
3231
elif value == '-∞':
3332
value = '-inf'
@@ -87,7 +86,7 @@ def fix_lists(collection: List[Any], type_hint_arguments: Tuple[Any, ...]) -> Op
8786
return result
8887

8988

90-
def fix_tuples(collection: List[Any], type_hint_arguments: Tuple[Any, ...]) -> Optional[Tuple[Any, ...]]:
89+
def fix_tuples(collection: List[Any], type_hint_arguments: Tuple[Any, ...]) -> Optional[Tuple[Any, ...]]: # noqa: PLR0912, PLR0911, C901
9190
if not isinstance(collection, list):
9291
return None
9392

@@ -158,7 +157,7 @@ def fix_dicts(collection: List[Any], type_hint_arguments: Tuple[Any, ...]) -> Op
158157
pair_result = {}
159158

160159
for name, meta in pair.items():
161-
element, type_hint = meta
160+
element, type_hint = meta # noqa: PLW2901
162161
origin_type = get_origin(type_hint)
163162
type_hint_arguments = get_args(type_hint)
164163
if any(x in (dict, list, tuple) for x in (type_hint, origin_type)):
@@ -221,7 +220,6 @@ def from_string(value: str, expected_type: Type[ExpectedType]) -> ExpectedType:
221220

222221
if check(result, expected_type, strict=True): # type: ignore[operator]
223222
return result # type: ignore[no-any-return]
224-
else:
225-
raise error
223+
raise error
226224

227225
return convert_single_value(value, expected_type)

simtypes/types/strings/email.py

Whitespace-only changes.

simtypes/typing.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
from typing import TypeVar
22

3-
43
ExpectedType = TypeVar('ExpectedType')

tests/units/conftest.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
import sys
2-
from typing import Tuple, List, Set, Dict, Union, Optional
2+
from typing import Dict, List, Optional, Set, Tuple, Union
33

44
import pytest
55

66

7-
@pytest.fixture(params=[1, 2])
8-
def new_style(request):
9-
return request.param
10-
11-
127
@pytest.fixture(params=[Dict, dict])
138
def dict_type(request):
149
return request.param

0 commit comments

Comments
 (0)