ddutils 0.2.3__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ddutils-0.2.3 → ddutils-0.2.4}/PKG-INFO +77 -2
- {ddutils-0.2.3 → ddutils-0.2.4}/README.md +76 -1
- {ddutils-0.2.3 → ddutils-0.2.4}/ddutils/annotation_helpers.py +1 -1
- {ddutils-0.2.3 → ddutils-0.2.4}/ddutils/convertors.py +12 -1
- ddutils-0.2.4/ddutils/value_helpers.py +30 -0
- {ddutils-0.2.3 → ddutils-0.2.4}/pyproject.toml +1 -1
- {ddutils-0.2.3 → ddutils-0.2.4}/pyproject.toml.orig +1 -1
- {ddutils-0.2.3 → ddutils-0.2.4}/LICENSE +0 -0
- {ddutils-0.2.3 → ddutils-0.2.4}/ddutils/__init__.py +0 -0
- {ddutils-0.2.3 → ddutils-0.2.4}/ddutils/class_helpers.py +0 -0
- {ddutils-0.2.3 → ddutils-0.2.4}/ddutils/datetime_helpers.py +0 -0
- {ddutils-0.2.3 → ddutils-0.2.4}/ddutils/function_exceptions_extractor.py +0 -0
- {ddutils-0.2.3 → ddutils-0.2.4}/ddutils/function_helpers.py +0 -0
- {ddutils-0.2.3 → ddutils-0.2.4}/ddutils/module_getter.py +0 -0
- {ddutils-0.2.3 → ddutils-0.2.4}/ddutils/object_getter.py +0 -0
- {ddutils-0.2.3 → ddutils-0.2.4}/ddutils/py.typed +0 -0
- {ddutils-0.2.3 → ddutils-0.2.4}/ddutils/safe_decorators.py +0 -0
- {ddutils-0.2.3 → ddutils-0.2.4}/ddutils/scoped_registry.py +0 -0
- {ddutils-0.2.3 → ddutils-0.2.4}/ddutils/sequence_helpers.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ddutils
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Domain Driven Utils Library
|
|
5
5
|
Keywords: python,ddutils
|
|
6
6
|
Author: davyddd
|
|
@@ -84,16 +84,23 @@ is_subclass(List[str], dict) # False
|
|
|
84
84
|
|
|
85
85
|
### is_complex_sequence
|
|
86
86
|
|
|
87
|
-
Checks whether a type annotation represents a sequence type, excluding `str`, `bytes`, and `bytearray
|
|
87
|
+
Checks whether a type annotation represents a sequence type, excluding `str`, `bytes`, and `bytearray`
|
|
88
|
+
and their subclasses (a `str`-based `Enum` is not a complex sequence).
|
|
88
89
|
|
|
89
90
|
```python
|
|
91
|
+
from enum import Enum
|
|
90
92
|
from typing import List, Tuple
|
|
91
93
|
from ddutils.annotation_helpers import is_complex_sequence
|
|
92
94
|
|
|
93
95
|
|
|
96
|
+
class Kind(str, Enum):
|
|
97
|
+
A = 'a'
|
|
98
|
+
|
|
99
|
+
|
|
94
100
|
is_complex_sequence(List[int]) # True
|
|
95
101
|
is_complex_sequence(Tuple[str, ...]) # True
|
|
96
102
|
is_complex_sequence(str) # False
|
|
103
|
+
is_complex_sequence(Kind) # False
|
|
97
104
|
is_complex_sequence(dict) # False
|
|
98
105
|
```
|
|
99
106
|
|
|
@@ -330,6 +337,30 @@ delta = timedelta(seconds=5, milliseconds=500)
|
|
|
330
337
|
convert_timedelta_to_milliseconds(delta) # 5500
|
|
331
338
|
```
|
|
332
339
|
|
|
340
|
+
### convert_to_builtin
|
|
341
|
+
|
|
342
|
+
Casts a value to its builtin base type (see [get_builtin_base_type](#get_builtin_base_type)):
|
|
343
|
+
a `str` subclass becomes a plain `str`, an `Enum` member becomes its `.value` cast the same way.
|
|
344
|
+
Raises `TypeError` for a value without a builtin base.
|
|
345
|
+
|
|
346
|
+
```python
|
|
347
|
+
from enum import Enum
|
|
348
|
+
from ddutils.convertors import convert_to_builtin
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
class Kind(str, Enum):
|
|
352
|
+
A = 'a'
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
class UserId(int):
|
|
356
|
+
pass
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
convert_to_builtin(Kind.A) # 'a' (not 'Kind.A', which `str(Kind.A)` would give)
|
|
360
|
+
convert_to_builtin(UserId(2)) # 2
|
|
361
|
+
convert_to_builtin(object()) # TypeError
|
|
362
|
+
```
|
|
363
|
+
|
|
333
364
|
## Datetime Helpers
|
|
334
365
|
|
|
335
366
|
Utilities for working with dates and times.
|
|
@@ -491,6 +522,50 @@ AST-based introspection for extracting exceptions from function source code.
|
|
|
491
522
|
Parses a function’s source code to find all `raise` statements and identify the exception types they use.
|
|
492
523
|
Returns an iterator of `ExceptionInfo` objects describing each raised exception.
|
|
493
524
|
|
|
525
|
+
## Value Helpers
|
|
526
|
+
|
|
527
|
+
Runtime counterparts of the annotation helpers: they inspect values, not type hints.
|
|
528
|
+
|
|
529
|
+
### get_builtin_base_type
|
|
530
|
+
|
|
531
|
+
Returns the builtin type a value should be treated as, looking past subclasses: `bool`, `int`, `float`, `str` or `bytes`
|
|
532
|
+
(`bool` is checked before `int`). An `Enum` member is looked at through its `.value`.
|
|
533
|
+
Raises `TypeError` for any other value. Useful for APIs that dispatch on the exact type (serializers, query builders).
|
|
534
|
+
|
|
535
|
+
```python
|
|
536
|
+
from enum import Enum
|
|
537
|
+
from ddutils.value_helpers import get_builtin_base_type
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
class Kind(str, Enum):
|
|
541
|
+
A = 'a'
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
class UserId(int):
|
|
545
|
+
pass
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
get_builtin_base_type(UserId(2)) # <class 'int'>
|
|
549
|
+
get_builtin_base_type(True) # <class 'bool'>
|
|
550
|
+
get_builtin_base_type(Kind.A) # <class 'str'>
|
|
551
|
+
get_builtin_base_type(object()) # TypeError
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
### is_complex_sequence_value
|
|
555
|
+
|
|
556
|
+
Checks whether a value is a sequence other than `str`, `bytes` or `bytearray` (subclasses included).
|
|
557
|
+
Sets and mappings are not sequences. The runtime counterpart of [is_complex_sequence](#is_complex_sequence).
|
|
558
|
+
|
|
559
|
+
```python
|
|
560
|
+
from ddutils.value_helpers import is_complex_sequence_value
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
is_complex_sequence_value([1, 2]) # True
|
|
564
|
+
is_complex_sequence_value((1, 2)) # True
|
|
565
|
+
is_complex_sequence_value('abc') # False
|
|
566
|
+
is_complex_sequence_value({1, 2}) # False
|
|
567
|
+
```
|
|
568
|
+
|
|
494
569
|
## Sequence Helpers
|
|
495
570
|
|
|
496
571
|
Safe operations on sequence types.
|
|
@@ -66,16 +66,23 @@ is_subclass(List[str], dict) # False
|
|
|
66
66
|
|
|
67
67
|
### is_complex_sequence
|
|
68
68
|
|
|
69
|
-
Checks whether a type annotation represents a sequence type, excluding `str`, `bytes`, and `bytearray
|
|
69
|
+
Checks whether a type annotation represents a sequence type, excluding `str`, `bytes`, and `bytearray`
|
|
70
|
+
and their subclasses (a `str`-based `Enum` is not a complex sequence).
|
|
70
71
|
|
|
71
72
|
```python
|
|
73
|
+
from enum import Enum
|
|
72
74
|
from typing import List, Tuple
|
|
73
75
|
from ddutils.annotation_helpers import is_complex_sequence
|
|
74
76
|
|
|
75
77
|
|
|
78
|
+
class Kind(str, Enum):
|
|
79
|
+
A = 'a'
|
|
80
|
+
|
|
81
|
+
|
|
76
82
|
is_complex_sequence(List[int]) # True
|
|
77
83
|
is_complex_sequence(Tuple[str, ...]) # True
|
|
78
84
|
is_complex_sequence(str) # False
|
|
85
|
+
is_complex_sequence(Kind) # False
|
|
79
86
|
is_complex_sequence(dict) # False
|
|
80
87
|
```
|
|
81
88
|
|
|
@@ -312,6 +319,30 @@ delta = timedelta(seconds=5, milliseconds=500)
|
|
|
312
319
|
convert_timedelta_to_milliseconds(delta) # 5500
|
|
313
320
|
```
|
|
314
321
|
|
|
322
|
+
### convert_to_builtin
|
|
323
|
+
|
|
324
|
+
Casts a value to its builtin base type (see [get_builtin_base_type](#get_builtin_base_type)):
|
|
325
|
+
a `str` subclass becomes a plain `str`, an `Enum` member becomes its `.value` cast the same way.
|
|
326
|
+
Raises `TypeError` for a value without a builtin base.
|
|
327
|
+
|
|
328
|
+
```python
|
|
329
|
+
from enum import Enum
|
|
330
|
+
from ddutils.convertors import convert_to_builtin
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
class Kind(str, Enum):
|
|
334
|
+
A = 'a'
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
class UserId(int):
|
|
338
|
+
pass
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
convert_to_builtin(Kind.A) # 'a' (not 'Kind.A', which `str(Kind.A)` would give)
|
|
342
|
+
convert_to_builtin(UserId(2)) # 2
|
|
343
|
+
convert_to_builtin(object()) # TypeError
|
|
344
|
+
```
|
|
345
|
+
|
|
315
346
|
## Datetime Helpers
|
|
316
347
|
|
|
317
348
|
Utilities for working with dates and times.
|
|
@@ -473,6 +504,50 @@ AST-based introspection for extracting exceptions from function source code.
|
|
|
473
504
|
Parses a function’s source code to find all `raise` statements and identify the exception types they use.
|
|
474
505
|
Returns an iterator of `ExceptionInfo` objects describing each raised exception.
|
|
475
506
|
|
|
507
|
+
## Value Helpers
|
|
508
|
+
|
|
509
|
+
Runtime counterparts of the annotation helpers: they inspect values, not type hints.
|
|
510
|
+
|
|
511
|
+
### get_builtin_base_type
|
|
512
|
+
|
|
513
|
+
Returns the builtin type a value should be treated as, looking past subclasses: `bool`, `int`, `float`, `str` or `bytes`
|
|
514
|
+
(`bool` is checked before `int`). An `Enum` member is looked at through its `.value`.
|
|
515
|
+
Raises `TypeError` for any other value. Useful for APIs that dispatch on the exact type (serializers, query builders).
|
|
516
|
+
|
|
517
|
+
```python
|
|
518
|
+
from enum import Enum
|
|
519
|
+
from ddutils.value_helpers import get_builtin_base_type
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
class Kind(str, Enum):
|
|
523
|
+
A = 'a'
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
class UserId(int):
|
|
527
|
+
pass
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
get_builtin_base_type(UserId(2)) # <class 'int'>
|
|
531
|
+
get_builtin_base_type(True) # <class 'bool'>
|
|
532
|
+
get_builtin_base_type(Kind.A) # <class 'str'>
|
|
533
|
+
get_builtin_base_type(object()) # TypeError
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### is_complex_sequence_value
|
|
537
|
+
|
|
538
|
+
Checks whether a value is a sequence other than `str`, `bytes` or `bytearray` (subclasses included).
|
|
539
|
+
Sets and mappings are not sequences. The runtime counterpart of [is_complex_sequence](#is_complex_sequence).
|
|
540
|
+
|
|
541
|
+
```python
|
|
542
|
+
from ddutils.value_helpers import is_complex_sequence_value
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
is_complex_sequence_value([1, 2]) # True
|
|
546
|
+
is_complex_sequence_value((1, 2)) # True
|
|
547
|
+
is_complex_sequence_value('abc') # False
|
|
548
|
+
is_complex_sequence_value({1, 2}) # False
|
|
549
|
+
```
|
|
550
|
+
|
|
476
551
|
## Sequence Helpers
|
|
477
552
|
|
|
478
553
|
Safe operations on sequence types.
|
|
@@ -34,7 +34,7 @@ def is_subclass(annotation: Any, *base_types: Any) -> bool:
|
|
|
34
34
|
|
|
35
35
|
def is_complex_sequence(annotation: Any) -> bool:
|
|
36
36
|
annotation_origin = get_annotation_origin(annotation)
|
|
37
|
-
return
|
|
37
|
+
return not is_subclass(annotation_origin, *NON_COMPLEX_SEQUENCE_TYPES) and is_subclass(annotation_origin, Sequence)
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
def get_complex_sequence_element_annotation(annotation: Any) -> Any:
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from datetime import timedelta
|
|
2
|
-
from typing import Protocol
|
|
2
|
+
from typing import Any, Protocol
|
|
3
|
+
|
|
4
|
+
from ddutils.value_helpers import get_builtin_base_type, unwrap_enum
|
|
3
5
|
|
|
4
6
|
|
|
5
7
|
class ClassInstanceWithDict(Protocol):
|
|
@@ -21,3 +23,12 @@ def convert_to_repr(obj: ClassInstanceWithDict) -> str:
|
|
|
21
23
|
|
|
22
24
|
def convert_timedelta_to_milliseconds(delta: timedelta) -> int:
|
|
23
25
|
return int(delta.total_seconds() * 1000)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def convert_to_builtin(value: Any) -> bool | int | float | str | bytes:
|
|
29
|
+
"""
|
|
30
|
+
Cast a value to its builtin base type (see `get_builtin_base_type`): a `str` subclass becomes a plain `str`,
|
|
31
|
+
an `Enum` member becomes its `.value` cast the same way. Raises `TypeError` for a value without a builtin base.
|
|
32
|
+
"""
|
|
33
|
+
value = unwrap_enum(value)
|
|
34
|
+
return get_builtin_base_type(value)(value)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from collections.abc import Sequence
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from ddutils.annotation_helpers import NON_COMPLEX_SEQUENCE_TYPES
|
|
6
|
+
|
|
7
|
+
# `bool` goes before `int` because `bool` is a subclass of `int`
|
|
8
|
+
BUILTIN_BASE_TYPES = (bool, int, float, str, bytes)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def unwrap_enum(value: Any) -> Any:
|
|
12
|
+
return value.value if isinstance(value, Enum) else value
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_builtin_base_type(value: Any) -> type:
|
|
16
|
+
"""
|
|
17
|
+
Return the builtin type a value should be treated as, looking past subclasses: `bool`, `int`, `float`, `str`
|
|
18
|
+
or `bytes`. An `Enum` member is looked at through its `.value`. Raises `TypeError` for any other value.
|
|
19
|
+
"""
|
|
20
|
+
value = unwrap_enum(value)
|
|
21
|
+
for base_type in BUILTIN_BASE_TYPES:
|
|
22
|
+
if isinstance(value, base_type):
|
|
23
|
+
return base_type
|
|
24
|
+
|
|
25
|
+
raise TypeError(f'Value of type `{type(value).__name__}` has no builtin base type')
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def is_complex_sequence_value(value: Any) -> bool:
|
|
29
|
+
"""Return whether a value is a sequence other than `str`, `bytes` or `bytearray`; subclasses are handled."""
|
|
30
|
+
return isinstance(value, Sequence) and not isinstance(value, NON_COMPLEX_SEQUENCE_TYPES)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|