u-toolkit 0.1.19__tar.gz → 0.1.20__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.
Files changed (48) hide show
  1. u_toolkit-0.1.20/PKG-INFO +5 -0
  2. {u_toolkit-0.1.19 → u_toolkit-0.1.20}/pyproject.toml +1 -14
  3. {u_toolkit-0.1.19 → u_toolkit-0.1.20}/src/u_toolkit/enum.py +1 -1
  4. u_toolkit-0.1.20/src/u_toolkit/merge.py +89 -0
  5. u_toolkit-0.1.20/src/u_toolkit/naming.py +94 -0
  6. u_toolkit-0.1.20/src/u_toolkit/signature.py +110 -0
  7. u_toolkit-0.1.20/uv.lock +189 -0
  8. u_toolkit-0.1.19/PKG-INFO +0 -11
  9. u_toolkit-0.1.19/src/u_toolkit/__init__.py +0 -9
  10. u_toolkit-0.1.19/src/u_toolkit/alias_generators.py +0 -49
  11. u_toolkit-0.1.19/src/u_toolkit/fastapi/cbv.py +0 -440
  12. u_toolkit-0.1.19/src/u_toolkit/fastapi/config.py +0 -9
  13. u_toolkit-0.1.19/src/u_toolkit/fastapi/exception.py +0 -163
  14. u_toolkit-0.1.19/src/u_toolkit/fastapi/helpers.py +0 -18
  15. u_toolkit-0.1.19/src/u_toolkit/fastapi/lifespan.py +0 -67
  16. u_toolkit-0.1.19/src/u_toolkit/fastapi/pagination.py +0 -79
  17. u_toolkit-0.1.19/src/u_toolkit/fastapi/responses.py +0 -67
  18. u_toolkit-0.1.19/src/u_toolkit/logger.py +0 -11
  19. u_toolkit-0.1.19/src/u_toolkit/merge.py +0 -31
  20. u_toolkit-0.1.19/src/u_toolkit/pydantic/fields.py +0 -24
  21. u_toolkit-0.1.19/src/u_toolkit/pydantic/models.py +0 -41
  22. u_toolkit-0.1.19/src/u_toolkit/pydantic/type_vars.py +0 -6
  23. u_toolkit-0.1.19/src/u_toolkit/signature.py +0 -72
  24. u_toolkit-0.1.19/src/u_toolkit/sqlalchemy/__init__.py +0 -0
  25. u_toolkit-0.1.19/src/u_toolkit/sqlalchemy/fields.py +0 -0
  26. u_toolkit-0.1.19/src/u_toolkit/sqlalchemy/function.py +0 -12
  27. u_toolkit-0.1.19/src/u_toolkit/sqlalchemy/orm/__init__.py +0 -0
  28. u_toolkit-0.1.19/src/u_toolkit/sqlalchemy/orm/fields.py +0 -20
  29. u_toolkit-0.1.19/src/u_toolkit/sqlalchemy/orm/models.py +0 -23
  30. u_toolkit-0.1.19/src/u_toolkit/sqlalchemy/table_info.py +0 -17
  31. u_toolkit-0.1.19/src/u_toolkit/sqlalchemy/type_vars.py +0 -6
  32. u_toolkit-0.1.19/tests/__init__.py +0 -0
  33. u_toolkit-0.1.19/tests/fastapi/__init__.py +0 -0
  34. u_toolkit-0.1.19/tests/fastapi/test_cbv.py +0 -116
  35. u_toolkit-0.1.19/uv.lock +0 -565
  36. {u_toolkit-0.1.19 → u_toolkit-0.1.20}/.github/workflows/publish.yml +0 -0
  37. {u_toolkit-0.1.19 → u_toolkit-0.1.20}/.gitignore +0 -0
  38. {u_toolkit-0.1.19 → u_toolkit-0.1.20}/README.md +0 -0
  39. {u_toolkit-0.1.19/src/u_toolkit/fastapi → u_toolkit-0.1.20/src/u_toolkit}/__init__.py +0 -0
  40. {u_toolkit-0.1.19 → u_toolkit-0.1.20}/src/u_toolkit/datetime.py +0 -0
  41. {u_toolkit-0.1.19 → u_toolkit-0.1.20}/src/u_toolkit/decorators.py +0 -0
  42. {u_toolkit-0.1.19 → u_toolkit-0.1.20}/src/u_toolkit/function.py +0 -0
  43. {u_toolkit-0.1.19 → u_toolkit-0.1.20}/src/u_toolkit/helpers.py +0 -0
  44. {u_toolkit-0.1.19 → u_toolkit-0.1.20}/src/u_toolkit/path.py +0 -0
  45. {u_toolkit-0.1.19/src/u_toolkit/pydantic → u_toolkit-0.1.20/tests}/__init__.py +0 -0
  46. {u_toolkit-0.1.19 → u_toolkit-0.1.20}/tests/test_enum.py +0 -0
  47. {u_toolkit-0.1.19 → u_toolkit-0.1.20}/tests/test_function.py +0 -0
  48. {u_toolkit-0.1.19 → u_toolkit-0.1.20}/tests/test_helpers.py +0 -0
@@ -0,0 +1,5 @@
1
+ Metadata-Version: 2.4
2
+ Name: u-toolkit
3
+ Version: 0.1.20
4
+ Summary: Add your description here
5
+ Requires-Python: >=3.11
@@ -1,25 +1,15 @@
1
1
  [project]
2
2
  name = "u-toolkit"
3
- version = "0.1.19"
3
+ version = "0.1.20"
4
4
  description = "Add your description here"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
7
7
  dependencies = [
8
- "pydantic>=2.11.3",
9
8
  ]
10
9
 
11
10
  [project.scripts]
12
11
  u-toolkit = "u_toolkit:main"
13
12
 
14
- [project.optional-dependencies]
15
- sqlalchemy = [
16
- "sqlalchemy>=2.0.40",
17
- ]
18
- fastapi = [
19
- "fastapi>=0.115.12",
20
- "pydantic-settings>=2.9.1",
21
- ]
22
-
23
13
  [build-system]
24
14
  requires = ["hatchling"]
25
15
  build-backend = "hatchling.build"
@@ -27,12 +17,9 @@ build-backend = "hatchling.build"
27
17
  [dependency-groups]
28
18
  dev = [
29
19
  "devtools>=0.12.2",
30
- "httpx>=0.28.1",
31
20
  "pytest>=8.3.5",
32
- "python-multipart>=0.0.20",
33
21
  "rich>=14.0.0",
34
22
  "ruff>=0.11.6",
35
- "uvicorn>=0.34.2",
36
23
  ]
37
24
 
38
25
 
@@ -1,6 +1,6 @@
1
1
  from enum import StrEnum, auto
2
2
 
3
- from .alias_generators import to_camel, to_pascal, to_snake
3
+ from .naming import to_camel, to_pascal, to_snake
4
4
 
5
5
 
6
6
  __all__ = [
@@ -0,0 +1,89 @@
1
+ from collections.abc import Iterable, Mapping
2
+ from typing import overload
3
+
4
+
5
+ def _merge_dict(
6
+ target: dict,
7
+ source: Mapping,
8
+ ):
9
+ """深层合并两个字典
10
+
11
+ :param target: 存放合并内容的字典
12
+ :param source: 来源, 因为不会修改, 所以只读映射就可以
13
+ :param exclude_keys: 需要排除的 keys
14
+ """
15
+
16
+ for ok, ov in source.items():
17
+ v = target.get(ok)
18
+ # 如果两边都是映射类型, 就可以合并
19
+ if isinstance(v, dict) and isinstance(ov, Mapping):
20
+ _merge_dict(v, ov)
21
+ elif isinstance(v, list) and isinstance(ov, Iterable):
22
+ _merge_list(v, ov)
23
+ # 如果当前值允许进行相加的操作
24
+ # 并且不是字符串和数字
25
+ # 并且旧字典与当前值类型相同
26
+ elif (
27
+ hasattr(v, "__add__")
28
+ and not isinstance(v, str | int)
29
+ and type(v) is type(ov)
30
+ ):
31
+ target[ok] = v + ov
32
+ # 否则使用有效的值
33
+ else:
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
@@ -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)
@@ -0,0 +1,110 @@
1
+ import inspect
2
+ from collections.abc import Callable, Sequence
3
+ from functools import partial, update_wrapper
4
+ from typing import Annotated, Any, NamedTuple, overload
5
+
6
+
7
+ class _Undefined: ...
8
+
9
+
10
+ def list_parameters(fn: Callable, /) -> list[inspect.Parameter]:
11
+ signature = inspect.signature(fn)
12
+ return list(signature.parameters.values())
13
+
14
+
15
+ class WithParameterResult(NamedTuple):
16
+ parameters: list[inspect.Parameter]
17
+ parameter: inspect.Parameter
18
+ parameter_index: int
19
+
20
+
21
+ @overload
22
+ def with_parameter(
23
+ fn: Callable, *, name: str, annotation: type | Annotated
24
+ ) -> WithParameterResult: ...
25
+ @overload
26
+ def with_parameter(
27
+ fn: Callable, *, name: str, default: Any
28
+ ) -> WithParameterResult: ...
29
+ @overload
30
+ def with_parameter(
31
+ fn: Callable, *, name: str, annotation: type | Annotated, default: Any
32
+ ) -> WithParameterResult: ...
33
+
34
+
35
+ def with_parameter(
36
+ fn: Callable,
37
+ *,
38
+ name: str,
39
+ annotation: type | Annotated | _Undefined = _Undefined,
40
+ default: Any = _Undefined,
41
+ ) -> WithParameterResult:
42
+ kwargs = {}
43
+ if annotation is not _Undefined:
44
+ kwargs["annotation"] = annotation
45
+ if default is not _Undefined:
46
+ kwargs["default"] = default
47
+
48
+ parameters = list_parameters(fn)
49
+ parameter = inspect.Parameter(
50
+ name=name, kind=inspect.Parameter.KEYWORD_ONLY, **kwargs
51
+ )
52
+ index = -1
53
+ if parameters and parameters[index].kind == inspect.Parameter.VAR_KEYWORD:
54
+ parameters.insert(index, parameter)
55
+ index = -2
56
+ else:
57
+ parameters.append(parameter)
58
+
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
80
+
81
+
82
+ def update_signature(
83
+ fn: Callable,
84
+ *,
85
+ parameters: Sequence[inspect.Parameter] | None = _Undefined, # type: ignore
86
+ return_annotation: type | None = _Undefined,
87
+ ):
88
+ signature = inspect.signature(fn)
89
+ if parameters is not _Undefined:
90
+ signature = signature.replace(parameters=parameters)
91
+ if return_annotation is not _Undefined:
92
+ signature = signature.replace(return_annotation=return_annotation)
93
+
94
+ setattr(fn, "__signature__", signature)
95
+
96
+
97
+ def update_parameters(
98
+ fn: Callable,
99
+ *,
100
+ parameters: Sequence[inspect.Parameter] | None = _Undefined, # type: ignore
101
+ ):
102
+ update_signature(fn, parameters=parameters)
103
+
104
+
105
+ def update_return_annotation(
106
+ fn: Callable,
107
+ *,
108
+ return_annotation: type | None = _Undefined,
109
+ ):
110
+ update_signature(fn, return_annotation=return_annotation)
@@ -0,0 +1,189 @@
1
+ version = 1
2
+ revision = 2
3
+ requires-python = ">=3.11"
4
+
5
+ [[package]]
6
+ name = "asttokens"
7
+ version = "2.4.1"
8
+ source = { registry = "https://pypi.org/simple" }
9
+ dependencies = [
10
+ { name = "six" },
11
+ ]
12
+ sdist = { url = "https://files.pythonhosted.org/packages/45/1d/f03bcb60c4a3212e15f99a56085d93093a497718adf828d050b9d675da81/asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0", size = 62284, upload-time = "2023-10-26T10:03:05.06Z" }
13
+ wheels = [
14
+ { url = "https://files.pythonhosted.org/packages/45/86/4736ac618d82a20d87d2f92ae19441ebc7ac9e7a581d7e58bbe79233b24a/asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24", size = 27764, upload-time = "2023-10-26T10:03:01.789Z" },
15
+ ]
16
+
17
+ [[package]]
18
+ name = "colorama"
19
+ version = "0.4.6"
20
+ source = { registry = "https://pypi.org/simple" }
21
+ sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
22
+ wheels = [
23
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
24
+ ]
25
+
26
+ [[package]]
27
+ name = "devtools"
28
+ version = "0.12.2"
29
+ source = { registry = "https://pypi.org/simple" }
30
+ dependencies = [
31
+ { name = "asttokens" },
32
+ { name = "executing" },
33
+ { name = "pygments" },
34
+ ]
35
+ sdist = { url = "https://files.pythonhosted.org/packages/84/75/b78198620640d394bc435c17bb49db18419afdd6cfa3ed8bcfe14034ec80/devtools-0.12.2.tar.gz", hash = "sha256:efceab184cb35e3a11fa8e602cc4fadacaa2e859e920fc6f87bf130b69885507", size = 75005, upload-time = "2023-09-03T16:57:00.679Z" }
36
+ wheels = [
37
+ { url = "https://files.pythonhosted.org/packages/d1/ae/afb1487556e2dc827a17097aac8158a25b433a345386f0e249f6d2694ccb/devtools-0.12.2-py3-none-any.whl", hash = "sha256:c366e3de1df4cdd635f1ad8cbcd3af01a384d7abda71900e68d43b04eb6aaca7", size = 19411, upload-time = "2023-09-03T16:56:59.049Z" },
38
+ ]
39
+
40
+ [[package]]
41
+ name = "executing"
42
+ version = "2.2.0"
43
+ source = { registry = "https://pypi.org/simple" }
44
+ sdist = { url = "https://files.pythonhosted.org/packages/91/50/a9d80c47ff289c611ff12e63f7c5d13942c65d68125160cefd768c73e6e4/executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755", size = 978693, upload-time = "2025-01-22T15:41:29.403Z" }
45
+ wheels = [
46
+ { url = "https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", size = 26702, upload-time = "2025-01-22T15:41:25.929Z" },
47
+ ]
48
+
49
+ [[package]]
50
+ name = "iniconfig"
51
+ version = "2.1.0"
52
+ source = { registry = "https://pypi.org/simple" }
53
+ sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" }
54
+ wheels = [
55
+ { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" },
56
+ ]
57
+
58
+ [[package]]
59
+ name = "markdown-it-py"
60
+ version = "3.0.0"
61
+ source = { registry = "https://pypi.org/simple" }
62
+ dependencies = [
63
+ { name = "mdurl" },
64
+ ]
65
+ sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" }
66
+ wheels = [
67
+ { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" },
68
+ ]
69
+
70
+ [[package]]
71
+ name = "mdurl"
72
+ version = "0.1.2"
73
+ source = { registry = "https://pypi.org/simple" }
74
+ sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
75
+ wheels = [
76
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
77
+ ]
78
+
79
+ [[package]]
80
+ name = "packaging"
81
+ version = "25.0"
82
+ source = { registry = "https://pypi.org/simple" }
83
+ sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" }
84
+ wheels = [
85
+ { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
86
+ ]
87
+
88
+ [[package]]
89
+ name = "pluggy"
90
+ version = "1.6.0"
91
+ source = { registry = "https://pypi.org/simple" }
92
+ sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
93
+ wheels = [
94
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
95
+ ]
96
+
97
+ [[package]]
98
+ name = "pygments"
99
+ version = "2.19.1"
100
+ source = { registry = "https://pypi.org/simple" }
101
+ sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581, upload-time = "2025-01-06T17:26:30.443Z" }
102
+ wheels = [
103
+ { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" },
104
+ ]
105
+
106
+ [[package]]
107
+ name = "pytest"
108
+ version = "8.3.5"
109
+ source = { registry = "https://pypi.org/simple" }
110
+ dependencies = [
111
+ { name = "colorama", marker = "sys_platform == 'win32'" },
112
+ { name = "iniconfig" },
113
+ { name = "packaging" },
114
+ { name = "pluggy" },
115
+ ]
116
+ sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload-time = "2025-03-02T12:54:54.503Z" }
117
+ wheels = [
118
+ { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" },
119
+ ]
120
+
121
+ [[package]]
122
+ name = "rich"
123
+ version = "14.0.0"
124
+ source = { registry = "https://pypi.org/simple" }
125
+ dependencies = [
126
+ { name = "markdown-it-py" },
127
+ { name = "pygments" },
128
+ ]
129
+ sdist = { url = "https://files.pythonhosted.org/packages/a1/53/830aa4c3066a8ab0ae9a9955976fb770fe9c6102117c8ec4ab3ea62d89e8/rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725", size = 224078, upload-time = "2025-03-30T14:15:14.23Z" }
130
+ wheels = [
131
+ { url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229, upload-time = "2025-03-30T14:15:12.283Z" },
132
+ ]
133
+
134
+ [[package]]
135
+ name = "ruff"
136
+ version = "0.11.11"
137
+ source = { registry = "https://pypi.org/simple" }
138
+ sdist = { url = "https://files.pythonhosted.org/packages/b2/53/ae4857030d59286924a8bdb30d213d6ff22d8f0957e738d0289990091dd8/ruff-0.11.11.tar.gz", hash = "sha256:7774173cc7c1980e6bf67569ebb7085989a78a103922fb83ef3dfe230cd0687d", size = 4186707, upload-time = "2025-05-22T19:19:34.363Z" }
139
+ wheels = [
140
+ { url = "https://files.pythonhosted.org/packages/b1/14/f2326676197bab099e2a24473158c21656fbf6a207c65f596ae15acb32b9/ruff-0.11.11-py3-none-linux_armv6l.whl", hash = "sha256:9924e5ae54125ed8958a4f7de320dab7380f6e9fa3195e3dc3b137c6842a0092", size = 10229049, upload-time = "2025-05-22T19:18:45.516Z" },
141
+ { url = "https://files.pythonhosted.org/packages/9a/f3/bff7c92dd66c959e711688b2e0768e486bbca46b2f35ac319bb6cce04447/ruff-0.11.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:c8a93276393d91e952f790148eb226658dd275cddfde96c6ca304873f11d2ae4", size = 11053601, upload-time = "2025-05-22T19:18:49.269Z" },
142
+ { url = "https://files.pythonhosted.org/packages/e2/38/8e1a3efd0ef9d8259346f986b77de0f62c7a5ff4a76563b6b39b68f793b9/ruff-0.11.11-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d6e333dbe2e6ae84cdedefa943dfd6434753ad321764fd937eef9d6b62022bcd", size = 10367421, upload-time = "2025-05-22T19:18:51.754Z" },
143
+ { url = "https://files.pythonhosted.org/packages/b4/50/557ad9dd4fb9d0bf524ec83a090a3932d284d1a8b48b5906b13b72800e5f/ruff-0.11.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7885d9a5e4c77b24e8c88aba8c80be9255fa22ab326019dac2356cff42089fc6", size = 10581980, upload-time = "2025-05-22T19:18:54.011Z" },
144
+ { url = "https://files.pythonhosted.org/packages/c4/b2/e2ed82d6e2739ece94f1bdbbd1d81b712d3cdaf69f0a1d1f1a116b33f9ad/ruff-0.11.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1b5ab797fcc09121ed82e9b12b6f27e34859e4227080a42d090881be888755d4", size = 10089241, upload-time = "2025-05-22T19:18:56.041Z" },
145
+ { url = "https://files.pythonhosted.org/packages/3d/9f/b4539f037a5302c450d7c695c82f80e98e48d0d667ecc250e6bdeb49b5c3/ruff-0.11.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e231ff3132c1119ece836487a02785f099a43992b95c2f62847d29bace3c75ac", size = 11699398, upload-time = "2025-05-22T19:18:58.248Z" },
146
+ { url = "https://files.pythonhosted.org/packages/61/fb/32e029d2c0b17df65e6eaa5ce7aea5fbeaed22dddd9fcfbbf5fe37c6e44e/ruff-0.11.11-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:a97c9babe1d4081037a90289986925726b802d180cca784ac8da2bbbc335f709", size = 12427955, upload-time = "2025-05-22T19:19:00.981Z" },
147
+ { url = "https://files.pythonhosted.org/packages/6e/e3/160488dbb11f18c8121cfd588e38095ba779ae208292765972f7732bfd95/ruff-0.11.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d8c4ddcbe8a19f59f57fd814b8b117d4fcea9bee7c0492e6cf5fdc22cfa563c8", size = 12069803, upload-time = "2025-05-22T19:19:03.258Z" },
148
+ { url = "https://files.pythonhosted.org/packages/ff/16/3b006a875f84b3d0bff24bef26b8b3591454903f6f754b3f0a318589dcc3/ruff-0.11.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6224076c344a7694c6fbbb70d4f2a7b730f6d47d2a9dc1e7f9d9bb583faf390b", size = 11242630, upload-time = "2025-05-22T19:19:05.871Z" },
149
+ { url = "https://files.pythonhosted.org/packages/65/0d/0338bb8ac0b97175c2d533e9c8cdc127166de7eb16d028a43c5ab9e75abd/ruff-0.11.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:882821fcdf7ae8db7a951df1903d9cb032bbe838852e5fc3c2b6c3ab54e39875", size = 11507310, upload-time = "2025-05-22T19:19:08.584Z" },
150
+ { url = "https://files.pythonhosted.org/packages/6f/bf/d7130eb26174ce9b02348b9f86d5874eafbf9f68e5152e15e8e0a392e4a3/ruff-0.11.11-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:dcec2d50756463d9df075a26a85a6affbc1b0148873da3997286caf1ce03cae1", size = 10441144, upload-time = "2025-05-22T19:19:13.621Z" },
151
+ { url = "https://files.pythonhosted.org/packages/b3/f3/4be2453b258c092ff7b1761987cf0749e70ca1340cd1bfb4def08a70e8d8/ruff-0.11.11-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:99c28505ecbaeb6594701a74e395b187ee083ee26478c1a795d35084d53ebd81", size = 10081987, upload-time = "2025-05-22T19:19:15.821Z" },
152
+ { url = "https://files.pythonhosted.org/packages/6c/6e/dfa4d2030c5b5c13db158219f2ec67bf333e8a7748dccf34cfa2a6ab9ebc/ruff-0.11.11-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9263f9e5aa4ff1dec765e99810f1cc53f0c868c5329b69f13845f699fe74f639", size = 11073922, upload-time = "2025-05-22T19:19:18.104Z" },
153
+ { url = "https://files.pythonhosted.org/packages/ff/f4/f7b0b0c3d32b593a20ed8010fa2c1a01f2ce91e79dda6119fcc51d26c67b/ruff-0.11.11-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:64ac6f885e3ecb2fdbb71de2701d4e34526651f1e8503af8fb30d4915a3fe345", size = 11568537, upload-time = "2025-05-22T19:19:20.889Z" },
154
+ { url = "https://files.pythonhosted.org/packages/d2/46/0e892064d0adc18bcc81deed9aaa9942a27fd2cd9b1b7791111ce468c25f/ruff-0.11.11-py3-none-win32.whl", hash = "sha256:1adcb9a18802268aaa891ffb67b1c94cd70578f126637118e8099b8e4adcf112", size = 10536492, upload-time = "2025-05-22T19:19:23.642Z" },
155
+ { url = "https://files.pythonhosted.org/packages/1b/d9/232e79459850b9f327e9f1dc9c047a2a38a6f9689e1ec30024841fc4416c/ruff-0.11.11-py3-none-win_amd64.whl", hash = "sha256:748b4bb245f11e91a04a4ff0f96e386711df0a30412b9fe0c74d5bdc0e4a531f", size = 11612562, upload-time = "2025-05-22T19:19:27.013Z" },
156
+ { url = "https://files.pythonhosted.org/packages/ce/eb/09c132cff3cc30b2e7244191dcce69437352d6d6709c0adf374f3e6f476e/ruff-0.11.11-py3-none-win_arm64.whl", hash = "sha256:6c51f136c0364ab1b774767aa8b86331bd8e9d414e2d107db7a2189f35ea1f7b", size = 10735951, upload-time = "2025-05-22T19:19:30.043Z" },
157
+ ]
158
+
159
+ [[package]]
160
+ name = "six"
161
+ version = "1.17.0"
162
+ source = { registry = "https://pypi.org/simple" }
163
+ sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" }
164
+ wheels = [
165
+ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
166
+ ]
167
+
168
+ [[package]]
169
+ name = "u-toolkit"
170
+ version = "0.1.19"
171
+ source = { editable = "." }
172
+
173
+ [package.dev-dependencies]
174
+ dev = [
175
+ { name = "devtools" },
176
+ { name = "pytest" },
177
+ { name = "rich" },
178
+ { name = "ruff" },
179
+ ]
180
+
181
+ [package.metadata]
182
+
183
+ [package.metadata.requires-dev]
184
+ dev = [
185
+ { name = "devtools", specifier = ">=0.12.2" },
186
+ { name = "pytest", specifier = ">=8.3.5" },
187
+ { name = "rich", specifier = ">=14.0.0" },
188
+ { name = "ruff", specifier = ">=0.11.6" },
189
+ ]
u_toolkit-0.1.19/PKG-INFO DELETED
@@ -1,11 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: u-toolkit
3
- Version: 0.1.19
4
- Summary: Add your description here
5
- Requires-Python: >=3.11
6
- Requires-Dist: pydantic>=2.11.3
7
- Provides-Extra: fastapi
8
- Requires-Dist: fastapi>=0.115.12; extra == 'fastapi'
9
- Requires-Dist: pydantic-settings>=2.9.1; extra == 'fastapi'
10
- Provides-Extra: sqlalchemy
11
- Requires-Dist: sqlalchemy>=2.0.40; extra == 'sqlalchemy'
@@ -1,9 +0,0 @@
1
- def get(obj: dict, key: str, fallback=None):
2
- items = key.split(".", 1)
3
- if len(items) > 1:
4
- for i in items:
5
- return get(obj, i, fallback)
6
- elif items:
7
- return obj.get(key, fallback)
8
-
9
- return fallback
@@ -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)