u-toolkit 0.1.18__py3-none-any.whl → 0.1.20__py3-none-any.whl
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.
- u_toolkit/__init__.py +0 -9
- u_toolkit/enum.py +7 -7
- u_toolkit/function.py +1 -1
- u_toolkit/helpers.py +2 -0
- u_toolkit/merge.py +61 -3
- u_toolkit/naming.py +94 -0
- u_toolkit/signature.py +54 -16
- u_toolkit-0.1.20.dist-info/METADATA +5 -0
- u_toolkit-0.1.20.dist-info/RECORD +14 -0
- u_toolkit/alias_generators.py +0 -49
- u_toolkit/fastapi/__init__.py +0 -0
- u_toolkit/fastapi/cbv.py +0 -440
- u_toolkit/fastapi/config.py +0 -9
- u_toolkit/fastapi/exception.py +0 -163
- u_toolkit/fastapi/helpers.py +0 -18
- u_toolkit/fastapi/lifespan.py +0 -67
- u_toolkit/fastapi/pagination.py +0 -79
- u_toolkit/fastapi/responses.py +0 -67
- u_toolkit/logger.py +0 -11
- u_toolkit/object.py +0 -0
- u_toolkit/pydantic/__init__.py +0 -0
- u_toolkit/pydantic/fields.py +0 -24
- u_toolkit/pydantic/models.py +0 -41
- u_toolkit/pydantic/type_vars.py +0 -6
- u_toolkit/sqlalchemy/__init__.py +0 -0
- u_toolkit/sqlalchemy/fields.py +0 -0
- u_toolkit/sqlalchemy/function.py +0 -12
- u_toolkit/sqlalchemy/orm/__init__.py +0 -0
- u_toolkit/sqlalchemy/orm/fields.py +0 -20
- u_toolkit/sqlalchemy/orm/models.py +0 -23
- u_toolkit/sqlalchemy/table_info.py +0 -17
- u_toolkit/sqlalchemy/type_vars.py +0 -6
- u_toolkit-0.1.18.dist-info/METADATA +0 -11
- u_toolkit-0.1.18.dist-info/RECORD +0 -36
- {u_toolkit-0.1.18.dist-info → u_toolkit-0.1.20.dist-info}/WHEEL +0 -0
- {u_toolkit-0.1.18.dist-info → u_toolkit-0.1.20.dist-info}/entry_points.txt +0 -0
u_toolkit/__init__.py
CHANGED
u_toolkit/enum.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
from enum import StrEnum, auto
|
2
2
|
|
3
|
-
from .
|
3
|
+
from .naming import to_camel, to_pascal, to_snake
|
4
4
|
|
5
5
|
|
6
6
|
__all__ = [
|
@@ -15,29 +15,29 @@ __all__ = [
|
|
15
15
|
|
16
16
|
class NameEnum(StrEnum):
|
17
17
|
@staticmethod
|
18
|
-
def _generate_next_value_(name, *_, **__) -> str:
|
18
|
+
def _generate_next_value_(name: str, *_, **__) -> str:
|
19
19
|
return name
|
20
20
|
|
21
21
|
|
22
22
|
class PascalEnum(StrEnum):
|
23
23
|
@staticmethod
|
24
|
-
def _generate_next_value_(name, *_, **__) -> str:
|
24
|
+
def _generate_next_value_(name: str, *_, **__) -> str:
|
25
25
|
return to_pascal(name)
|
26
26
|
|
27
27
|
|
28
28
|
class CamelEnum(StrEnum):
|
29
29
|
@staticmethod
|
30
|
-
def _generate_next_value_(name, *_, **__) -> str:
|
30
|
+
def _generate_next_value_(name: str, *_, **__) -> str:
|
31
31
|
return to_camel(name)
|
32
32
|
|
33
33
|
|
34
34
|
class SnakeEnum(StrEnum):
|
35
35
|
@staticmethod
|
36
|
-
def _generate_next_value_(name, *_, **__) -> str:
|
36
|
+
def _generate_next_value_(name: str, *_, **__) -> str:
|
37
37
|
return to_snake(name)
|
38
38
|
|
39
39
|
|
40
40
|
class TitleEnum(StrEnum):
|
41
41
|
@staticmethod
|
42
|
-
def _generate_next_value_(name, *_, **__) -> str:
|
43
|
-
return name.replace("_", " ").title()
|
42
|
+
def _generate_next_value_(name: str, *_, **__) -> str:
|
43
|
+
return name.replace("_", " ").strip().title()
|
u_toolkit/function.py
CHANGED
u_toolkit/helpers.py
CHANGED
u_toolkit/merge.py
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
from collections.abc import Mapping
|
1
|
+
from collections.abc import Iterable, Mapping
|
2
|
+
from typing import overload
|
2
3
|
|
3
4
|
|
4
|
-
def
|
5
|
+
def _merge_dict(
|
5
6
|
target: dict,
|
6
7
|
source: Mapping,
|
7
8
|
):
|
@@ -16,7 +17,9 @@ def deep_merge_dict(
|
|
16
17
|
v = target.get(ok)
|
17
18
|
# 如果两边都是映射类型, 就可以合并
|
18
19
|
if isinstance(v, dict) and isinstance(ov, Mapping):
|
19
|
-
|
20
|
+
_merge_dict(v, ov)
|
21
|
+
elif isinstance(v, list) and isinstance(ov, Iterable):
|
22
|
+
_merge_list(v, ov)
|
20
23
|
# 如果当前值允许进行相加的操作
|
21
24
|
# 并且不是字符串和数字
|
22
25
|
# 并且旧字典与当前值类型相同
|
@@ -29,3 +32,58 @@ def deep_merge_dict(
|
|
29
32
|
# 否则使用有效的值
|
30
33
|
else:
|
31
34
|
target[ok] = v or ov
|
35
|
+
|
36
|
+
|
37
|
+
def _merge_list(target: list, source: Iterable):
|
38
|
+
for oi, ov in enumerate(source):
|
39
|
+
try:
|
40
|
+
v = target[oi]
|
41
|
+
except IndexError:
|
42
|
+
target[oi] = ov
|
43
|
+
break
|
44
|
+
|
45
|
+
if isinstance(v, dict) and isinstance(ov, Mapping):
|
46
|
+
merge(v, ov)
|
47
|
+
|
48
|
+
elif isinstance(v, list) and isinstance(ov, Iterable):
|
49
|
+
_merge_list(v, ov)
|
50
|
+
# 如果当前值允许进行相加的操作
|
51
|
+
# 并且不是字符串和数字
|
52
|
+
# 并且旧字典与当前值类型相同
|
53
|
+
elif (
|
54
|
+
hasattr(v, "__add__")
|
55
|
+
and not isinstance(v, str | int)
|
56
|
+
and type(v) is type(ov)
|
57
|
+
):
|
58
|
+
target[oi] = v + ov
|
59
|
+
else:
|
60
|
+
target[oi] = v or ov
|
61
|
+
|
62
|
+
|
63
|
+
@overload
|
64
|
+
def merge(target: list, source: Iterable): ...
|
65
|
+
@overload
|
66
|
+
def merge(target: dict, source: Mapping): ...
|
67
|
+
|
68
|
+
|
69
|
+
def merge(target, source):
|
70
|
+
for ok, ov in source.items():
|
71
|
+
v = target.get(ok)
|
72
|
+
|
73
|
+
# 如果两边都是映射类型, 就可以合并
|
74
|
+
if isinstance(v, dict) and isinstance(ov, Mapping):
|
75
|
+
_merge_dict(v, ov)
|
76
|
+
|
77
|
+
# 如果当前值允许进行相加的操作
|
78
|
+
# 并且不是字符串和数字
|
79
|
+
# 并且旧字典与当前值类型相同
|
80
|
+
elif (
|
81
|
+
hasattr(v, "__add__")
|
82
|
+
and not isinstance(v, str | int)
|
83
|
+
and type(v) is type(ov)
|
84
|
+
):
|
85
|
+
target[ok] = v + ov
|
86
|
+
|
87
|
+
# 否则使用有效的值
|
88
|
+
else:
|
89
|
+
target[ok] = v or ov
|
u_toolkit/naming.py
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
import re
|
2
|
+
from collections.abc import Callable
|
3
|
+
from typing import TypeVar, TypeVarTuple, overload
|
4
|
+
|
5
|
+
|
6
|
+
__all__ = ("to_camel", "to_pascal", "to_snake")
|
7
|
+
|
8
|
+
Ts = TypeVarTuple("Ts")
|
9
|
+
T = TypeVar("T")
|
10
|
+
|
11
|
+
|
12
|
+
def _arguments_handle(transform: Callable, *args, kwd_name: str, **kwds):
|
13
|
+
if len(args) > 1:
|
14
|
+
return tuple(transform(a) for a in args)
|
15
|
+
|
16
|
+
if args:
|
17
|
+
return transform(args[0])
|
18
|
+
|
19
|
+
return transform(kwds[kwd_name])
|
20
|
+
|
21
|
+
|
22
|
+
@overload
|
23
|
+
def to_pascal(snake: str) -> str: ...
|
24
|
+
@overload
|
25
|
+
def to_pascal(*snake: str) -> tuple[str, ...]: ...
|
26
|
+
|
27
|
+
|
28
|
+
def to_pascal(*args, **kwds):
|
29
|
+
pattern = re.compile("([0-9A-Za-z])_(?=[0-9A-Z])")
|
30
|
+
|
31
|
+
def transform(arg: str) -> str:
|
32
|
+
camel = arg.title()
|
33
|
+
return pattern.sub(lambda m: m.group(1), camel)
|
34
|
+
|
35
|
+
return _arguments_handle(transform, *args, kwd_name="snake", **kwds)
|
36
|
+
|
37
|
+
|
38
|
+
@overload
|
39
|
+
def to_camel(snake: str) -> str: ...
|
40
|
+
@overload
|
41
|
+
def to_camel(*snake: str) -> tuple[str, ...]: ...
|
42
|
+
|
43
|
+
|
44
|
+
def to_camel(*args, **kwds):
|
45
|
+
# If the string is already in camelCase and does not contain
|
46
|
+
# a digit followed by a lowercase letter, return it as it is
|
47
|
+
match_pattern = re.compile("^[a-z]+[A-Za-z0-9]*$")
|
48
|
+
search_pattern = re.compile(r"\d[a-z]")
|
49
|
+
|
50
|
+
def transform(arg: str):
|
51
|
+
if match_pattern.match(arg) and not search_pattern.search(arg):
|
52
|
+
return arg
|
53
|
+
|
54
|
+
camel = to_pascal(arg)
|
55
|
+
return re.sub("(^_*[A-Z])", lambda m: m.group(1).lower(), camel)
|
56
|
+
|
57
|
+
return _arguments_handle(transform, *args, kwd_name="snake", **kwds)
|
58
|
+
|
59
|
+
|
60
|
+
@overload
|
61
|
+
def to_snake(camel: str) -> str: ...
|
62
|
+
@overload
|
63
|
+
def to_snake(*camel: str) -> tuple[str, ...]: ...
|
64
|
+
|
65
|
+
|
66
|
+
def to_snake(*args, **kwds):
|
67
|
+
"""Convert a PascalCase, camelCase, kebab-case string to snake_case.""" # noqa: W505
|
68
|
+
|
69
|
+
# Handle the sequence of uppercase letters followed by
|
70
|
+
# a lowercase letter
|
71
|
+
def transform(arg: str):
|
72
|
+
snake = re.sub(
|
73
|
+
r"([A-Z]+)([A-Z][a-z])",
|
74
|
+
lambda m: f"{m.group(1)}_{m.group(2)}",
|
75
|
+
arg,
|
76
|
+
)
|
77
|
+
# Insert an underscore between a lowercase letter and
|
78
|
+
# an uppercase letter
|
79
|
+
snake = re.sub(
|
80
|
+
r"([a-z])([A-Z])", lambda m: f"{m.group(1)}_{m.group(2)}", snake
|
81
|
+
)
|
82
|
+
# Insert an underscore between a digit and an uppercase letter
|
83
|
+
snake = re.sub(
|
84
|
+
r"([0-9])([A-Z])", lambda m: f"{m.group(1)}_{m.group(2)}", snake
|
85
|
+
)
|
86
|
+
# Insert an underscore between a lowercase letter and a digit
|
87
|
+
snake = re.sub(
|
88
|
+
r"([a-z])([0-9])", lambda m: f"{m.group(1)}_{m.group(2)}", snake
|
89
|
+
)
|
90
|
+
# Replace hyphens with underscores to handle kebab-case
|
91
|
+
snake = snake.replace("-", "_")
|
92
|
+
return snake.lower()
|
93
|
+
|
94
|
+
return _arguments_handle(transform, *args, kwd_name="camel", **kwds)
|
u_toolkit/signature.py
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
import inspect
|
2
2
|
from collections.abc import Callable, Sequence
|
3
|
-
from
|
3
|
+
from functools import partial, update_wrapper
|
4
|
+
from typing import Annotated, Any, NamedTuple, overload
|
5
|
+
|
6
|
+
|
7
|
+
class _Undefined: ...
|
4
8
|
|
5
9
|
|
6
10
|
def list_parameters(fn: Callable, /) -> list[inspect.Parameter]:
|
@@ -8,31 +12,37 @@ def list_parameters(fn: Callable, /) -> list[inspect.Parameter]:
|
|
8
12
|
return list(signature.parameters.values())
|
9
13
|
|
10
14
|
|
15
|
+
class WithParameterResult(NamedTuple):
|
16
|
+
parameters: list[inspect.Parameter]
|
17
|
+
parameter: inspect.Parameter
|
18
|
+
parameter_index: int
|
19
|
+
|
20
|
+
|
11
21
|
@overload
|
12
22
|
def with_parameter(
|
13
23
|
fn: Callable, *, name: str, annotation: type | Annotated
|
14
|
-
) ->
|
24
|
+
) -> WithParameterResult: ...
|
15
25
|
@overload
|
16
26
|
def with_parameter(
|
17
27
|
fn: Callable, *, name: str, default: Any
|
18
|
-
) ->
|
28
|
+
) -> WithParameterResult: ...
|
19
29
|
@overload
|
20
30
|
def with_parameter(
|
21
31
|
fn: Callable, *, name: str, annotation: type | Annotated, default: Any
|
22
|
-
) ->
|
32
|
+
) -> WithParameterResult: ...
|
23
33
|
|
24
34
|
|
25
35
|
def with_parameter(
|
26
36
|
fn: Callable,
|
27
37
|
*,
|
28
38
|
name: str,
|
29
|
-
annotation: type | Annotated |
|
30
|
-
default: Any =
|
31
|
-
) ->
|
39
|
+
annotation: type | Annotated | _Undefined = _Undefined,
|
40
|
+
default: Any = _Undefined,
|
41
|
+
) -> WithParameterResult:
|
32
42
|
kwargs = {}
|
33
|
-
if annotation is not
|
43
|
+
if annotation is not _Undefined:
|
34
44
|
kwargs["annotation"] = annotation
|
35
|
-
if default is not
|
45
|
+
if default is not _Undefined:
|
36
46
|
kwargs["default"] = default
|
37
47
|
|
38
48
|
parameters = list_parameters(fn)
|
@@ -46,27 +56,55 @@ def with_parameter(
|
|
46
56
|
else:
|
47
57
|
parameters.append(parameter)
|
48
58
|
|
49
|
-
return parameters, parameter, index
|
59
|
+
return WithParameterResult(parameters, parameter, index)
|
60
|
+
|
61
|
+
|
62
|
+
def add_parameter(
|
63
|
+
fn: Callable,
|
64
|
+
*,
|
65
|
+
name: str,
|
66
|
+
annotation: type | Annotated = _Undefined,
|
67
|
+
default: Any = _Undefined,
|
68
|
+
):
|
69
|
+
"""添加参数, 会将添加参数后的新函数返回"""
|
70
|
+
p = with_parameter(
|
71
|
+
fn,
|
72
|
+
name=name,
|
73
|
+
annotation=annotation,
|
74
|
+
default=default,
|
75
|
+
)
|
76
|
+
|
77
|
+
new_fn = update_wrapper(partial(fn), fn)
|
78
|
+
update_parameters(fn, parameters=p.parameters)
|
79
|
+
return new_fn
|
50
80
|
|
51
81
|
|
52
82
|
def update_signature(
|
53
83
|
fn: Callable,
|
54
84
|
*,
|
55
|
-
parameters: Sequence[inspect.Parameter] | None =
|
56
|
-
return_annotation: type | None =
|
85
|
+
parameters: Sequence[inspect.Parameter] | None = _Undefined, # type: ignore
|
86
|
+
return_annotation: type | None = _Undefined,
|
57
87
|
):
|
58
88
|
signature = inspect.signature(fn)
|
59
|
-
if parameters is not
|
89
|
+
if parameters is not _Undefined:
|
60
90
|
signature = signature.replace(parameters=parameters)
|
61
|
-
if return_annotation is not
|
91
|
+
if return_annotation is not _Undefined:
|
62
92
|
signature = signature.replace(return_annotation=return_annotation)
|
63
93
|
|
64
94
|
setattr(fn, "__signature__", signature)
|
65
95
|
|
66
96
|
|
67
|
-
def update_parameters(
|
97
|
+
def update_parameters(
|
98
|
+
fn: Callable,
|
99
|
+
*,
|
100
|
+
parameters: Sequence[inspect.Parameter] | None = _Undefined, # type: ignore
|
101
|
+
):
|
68
102
|
update_signature(fn, parameters=parameters)
|
69
103
|
|
70
104
|
|
71
|
-
def update_return_annotation(
|
105
|
+
def update_return_annotation(
|
106
|
+
fn: Callable,
|
107
|
+
*,
|
108
|
+
return_annotation: type | None = _Undefined,
|
109
|
+
):
|
72
110
|
update_signature(fn, return_annotation=return_annotation)
|
@@ -0,0 +1,14 @@
|
|
1
|
+
u_toolkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
u_toolkit/datetime.py,sha256=GOG0xa6yKeqvFXJkImK5Pt7wsPXnHMlNKju8deniGJ4,644
|
3
|
+
u_toolkit/decorators.py,sha256=rBZfXtWVfja6YMDqF9izjAiabRVyp4pAWOlwnN0HkUw,2396
|
4
|
+
u_toolkit/enum.py,sha256=S0qsklSm7rc53W_gheTCpopej5eGOeCK-HKK_ryR2No,885
|
5
|
+
u_toolkit/function.py,sha256=HgZcWd4IydNqUdUbS6A5pXVcAponGUZ2A8YKuiwHGjg,259
|
6
|
+
u_toolkit/helpers.py,sha256=QSkDZH90FfuNB0hWI1GA2KHFk1ajZMzNBr7ysuBdFTg,161
|
7
|
+
u_toolkit/merge.py,sha256=r_GhRIg5VHzXnqOVU9l0rpdT7XXV8FHWIp-nzP7-xnA,2550
|
8
|
+
u_toolkit/naming.py,sha256=WLK-kYFJUFvUGYK7rJrL1uBVxwXNJPcDQqOidXEwkqU,2746
|
9
|
+
u_toolkit/path.py,sha256=IkyIHcU9hKBCOZfF30FrKf4CfL-MH91fjeYF9EY7eos,128
|
10
|
+
u_toolkit/signature.py,sha256=vyZgo4lXWD282Sq3Svn36peOrUlBHwl0QIGOBghczAc,2869
|
11
|
+
u_toolkit-0.1.20.dist-info/METADATA,sha256=AHyOwnhZnOB1zNzOQNKZUQHvV6VB61YRq5E6J85_NkI,113
|
12
|
+
u_toolkit-0.1.20.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
13
|
+
u_toolkit-0.1.20.dist-info/entry_points.txt,sha256=hTfAYCd5vvRiqgnJk2eBsoRIiIVB9pK8WZm3Q3jjKFU,45
|
14
|
+
u_toolkit-0.1.20.dist-info/RECORD,,
|
u_toolkit/alias_generators.py
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
from typing import TypeVarTuple, overload
|
2
|
-
|
3
|
-
from pydantic import alias_generators
|
4
|
-
from pydantic.fields import ComputedFieldInfo, FieldInfo
|
5
|
-
|
6
|
-
|
7
|
-
Ts = TypeVarTuple("Ts")
|
8
|
-
|
9
|
-
|
10
|
-
@overload
|
11
|
-
def to_camel(string: str, _: ComputedFieldInfo | FieldInfo) -> str: ...
|
12
|
-
|
13
|
-
|
14
|
-
@overload
|
15
|
-
def to_camel(string: str) -> str: ...
|
16
|
-
|
17
|
-
|
18
|
-
def to_camel(string: str, *_, **__):
|
19
|
-
if string.isupper():
|
20
|
-
return string
|
21
|
-
return alias_generators.to_camel(string)
|
22
|
-
|
23
|
-
|
24
|
-
@overload
|
25
|
-
def to_snake(string: str, _: ComputedFieldInfo | FieldInfo) -> str: ...
|
26
|
-
|
27
|
-
|
28
|
-
@overload
|
29
|
-
def to_snake(string: str) -> str: ...
|
30
|
-
|
31
|
-
|
32
|
-
def to_snake(string: str, *_, **__):
|
33
|
-
if string.isupper():
|
34
|
-
return string
|
35
|
-
return alias_generators.to_snake(string)
|
36
|
-
|
37
|
-
|
38
|
-
@overload
|
39
|
-
def to_pascal(string: str, _: ComputedFieldInfo | FieldInfo) -> str: ...
|
40
|
-
|
41
|
-
|
42
|
-
@overload
|
43
|
-
def to_pascal(string: str) -> str: ...
|
44
|
-
|
45
|
-
|
46
|
-
def to_pascal(string: str, *_, **__):
|
47
|
-
if string.isupper():
|
48
|
-
return string
|
49
|
-
return alias_generators.to_pascal(string)
|
u_toolkit/fastapi/__init__.py
DELETED
File without changes
|