u-toolkit 0.1.19__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 +1 -1
- 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/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.19.dist-info/METADATA +0 -11
- u_toolkit-0.1.19.dist-info/RECORD +0 -35
- {u_toolkit-0.1.19.dist-info → u_toolkit-0.1.20.dist-info}/WHEEL +0 -0
- {u_toolkit-0.1.19.dist-info → u_toolkit-0.1.20.dist-info}/entry_points.txt +0 -0
u_toolkit/fastapi/pagination.py
DELETED
@@ -1,79 +0,0 @@
|
|
1
|
-
from collections.abc import Sequence
|
2
|
-
from math import ceil
|
3
|
-
from typing import Annotated, Generic, overload
|
4
|
-
|
5
|
-
from fastapi import Depends, Query
|
6
|
-
from pydantic import BaseModel, Field, NonNegativeInt, PositiveInt
|
7
|
-
from sqlalchemy import MappingResult, ScalarResult
|
8
|
-
|
9
|
-
from u_toolkit.pydantic.type_vars import BaseModelT
|
10
|
-
from u_toolkit.sqlalchemy.type_vars import DeclarativeBaseT
|
11
|
-
|
12
|
-
|
13
|
-
class Page(BaseModel, Generic[BaseModelT]):
|
14
|
-
page_size: PositiveInt = Field(description="page size")
|
15
|
-
page_no: PositiveInt = Field(description="page number")
|
16
|
-
|
17
|
-
page_count: NonNegativeInt = Field(description="page count")
|
18
|
-
count: NonNegativeInt = Field(description="result count")
|
19
|
-
|
20
|
-
results: list[BaseModelT] = Field(description="results")
|
21
|
-
|
22
|
-
|
23
|
-
class PageParamsModel(BaseModel):
|
24
|
-
page_size: int = Query(
|
25
|
-
50,
|
26
|
-
ge=1,
|
27
|
-
le=100,
|
28
|
-
description="page size",
|
29
|
-
)
|
30
|
-
page_no: PositiveInt = Query(
|
31
|
-
1,
|
32
|
-
description="page number",
|
33
|
-
)
|
34
|
-
|
35
|
-
|
36
|
-
PageParams = Annotated[PageParamsModel, Depends()]
|
37
|
-
|
38
|
-
|
39
|
-
@overload
|
40
|
-
def page(
|
41
|
-
model_class: type[BaseModelT],
|
42
|
-
pagination: PageParamsModel,
|
43
|
-
count: int,
|
44
|
-
results: ScalarResult[DeclarativeBaseT],
|
45
|
-
) -> Page[BaseModelT]: ...
|
46
|
-
|
47
|
-
|
48
|
-
@overload
|
49
|
-
def page(
|
50
|
-
model_class: type[BaseModelT],
|
51
|
-
pagination: PageParamsModel,
|
52
|
-
count: int,
|
53
|
-
results: MappingResult,
|
54
|
-
) -> Page[BaseModelT]: ...
|
55
|
-
|
56
|
-
|
57
|
-
@overload
|
58
|
-
def page(
|
59
|
-
model_class: type[BaseModelT],
|
60
|
-
pagination: PageParamsModel,
|
61
|
-
count: int,
|
62
|
-
results: Sequence[DeclarativeBaseT],
|
63
|
-
) -> Page[BaseModelT]: ...
|
64
|
-
|
65
|
-
|
66
|
-
def page(
|
67
|
-
model_class: type[BaseModelT],
|
68
|
-
pagination: PageParamsModel,
|
69
|
-
count: int,
|
70
|
-
results,
|
71
|
-
) -> Page[BaseModelT]:
|
72
|
-
results_ = [model_class.model_validate(i) for i in results]
|
73
|
-
return Page(
|
74
|
-
page_size=pagination.page_size,
|
75
|
-
page_no=pagination.page_no,
|
76
|
-
page_count=ceil(count / pagination.page_size),
|
77
|
-
count=count,
|
78
|
-
results=results_, # type: ignore
|
79
|
-
)
|
u_toolkit/fastapi/responses.py
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
from pydantic import BaseModel
|
2
|
-
|
3
|
-
from u_toolkit.merge import deep_merge_dict
|
4
|
-
|
5
|
-
from .exception import HTTPErrorInterface
|
6
|
-
|
7
|
-
|
8
|
-
def _merge_responses(
|
9
|
-
target: dict,
|
10
|
-
source: dict,
|
11
|
-
):
|
12
|
-
for status, response in target.items():
|
13
|
-
model_class = response.get("model")
|
14
|
-
if status in source:
|
15
|
-
source_model_class = source[status].get("model")
|
16
|
-
if source_model_class and model_class:
|
17
|
-
target[status]["model"] = model_class | source_model_class
|
18
|
-
|
19
|
-
for status, response in source.items():
|
20
|
-
if status not in target:
|
21
|
-
target[status] = response
|
22
|
-
|
23
|
-
|
24
|
-
def error_responses(*errors: type[HTTPErrorInterface]):
|
25
|
-
source = {}
|
26
|
-
|
27
|
-
for e in errors:
|
28
|
-
model_class = e.response_class()
|
29
|
-
if e.status in source:
|
30
|
-
current: type[BaseModel] = source[e.status]["model"]
|
31
|
-
|
32
|
-
source[e.status] = {"model": current | model_class}
|
33
|
-
else:
|
34
|
-
deep_merge_dict(source, {e.status: {"model": model_class}})
|
35
|
-
return source
|
36
|
-
|
37
|
-
|
38
|
-
Response = (
|
39
|
-
tuple[int, type[BaseModel]]
|
40
|
-
| dict[int, type[BaseModel]]
|
41
|
-
| int
|
42
|
-
| type[HTTPErrorInterface]
|
43
|
-
)
|
44
|
-
|
45
|
-
|
46
|
-
def build_responses(*responses: Response):
|
47
|
-
result = {}
|
48
|
-
errors: list[type[HTTPErrorInterface]] = []
|
49
|
-
|
50
|
-
for arg in responses:
|
51
|
-
status = None
|
52
|
-
response = {}
|
53
|
-
if isinstance(arg, tuple):
|
54
|
-
status, response = arg
|
55
|
-
elif isinstance(arg, dict):
|
56
|
-
for status_, response_ in arg.items():
|
57
|
-
result[status_] = {"model": response_}
|
58
|
-
elif isinstance(arg, int):
|
59
|
-
status = arg
|
60
|
-
else:
|
61
|
-
errors.append(arg)
|
62
|
-
continue
|
63
|
-
|
64
|
-
result[status] = {"model": response}
|
65
|
-
|
66
|
-
_merge_responses(result, error_responses(*errors))
|
67
|
-
return result
|
u_toolkit/logger.py
DELETED
u_toolkit/pydantic/__init__.py
DELETED
File without changes
|
u_toolkit/pydantic/fields.py
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
from datetime import datetime
|
2
|
-
from typing import Annotated
|
3
|
-
|
4
|
-
from pydantic import Field, PlainSerializer
|
5
|
-
|
6
|
-
from u_toolkit.datetime import to_naive, to_utc, to_utc_naive
|
7
|
-
|
8
|
-
|
9
|
-
DBSmallInt = Annotated[int, Field(ge=-32768, le=32767)]
|
10
|
-
DBInt = Annotated[int, Field(ge=-2147483648, le=2147483647)]
|
11
|
-
DBBigInt = Annotated[
|
12
|
-
int, Field(ge=-9223372036854775808, le=9223372036854775807)
|
13
|
-
]
|
14
|
-
DBSmallSerial = Annotated[int, Field(ge=1, le=32767)]
|
15
|
-
DBIntSerial = Annotated[int, Field(ge=1, le=2147483647)]
|
16
|
-
DBBigintSerial = Annotated[int, Field(ge=1, le=9223372036854775807)]
|
17
|
-
|
18
|
-
|
19
|
-
# 去除时区信息
|
20
|
-
NaiveDatetime = Annotated[datetime, PlainSerializer(to_naive)]
|
21
|
-
# 将时区转成 UTC
|
22
|
-
UTCDateTime = Annotated[datetime, PlainSerializer(to_utc)]
|
23
|
-
# 将时间转成 UTC, 并且去除时区信息
|
24
|
-
UTCNaiveDateTime = Annotated[datetime, PlainSerializer(to_utc_naive)]
|
u_toolkit/pydantic/models.py
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
from datetime import datetime
|
2
|
-
from typing import Annotated, Any
|
3
|
-
|
4
|
-
from pydantic import BaseModel, ConfigDict, WrapSerializer
|
5
|
-
|
6
|
-
from u_toolkit.alias_generators import to_camel
|
7
|
-
from u_toolkit.datetime import to_utc
|
8
|
-
|
9
|
-
from .type_vars import BaseModelT
|
10
|
-
|
11
|
-
|
12
|
-
class Model(BaseModel):
|
13
|
-
model_config = ConfigDict(
|
14
|
-
populate_by_name=True,
|
15
|
-
from_attributes=True,
|
16
|
-
)
|
17
|
-
|
18
|
-
|
19
|
-
class CamelModel(Model):
|
20
|
-
model_config = ConfigDict(
|
21
|
-
alias_generator=to_camel,
|
22
|
-
populate_by_name=True,
|
23
|
-
from_attributes=True,
|
24
|
-
field_title_generator=to_camel,
|
25
|
-
)
|
26
|
-
|
27
|
-
|
28
|
-
def convert_to_utc(value: Any, handler, info) -> dict[str, datetime]:
|
29
|
-
# Note that `helper` can actually help serialize the `value` for
|
30
|
-
# further custom serialization in case it's a subclass.
|
31
|
-
partial_result = handler(value, info)
|
32
|
-
if info.mode == "json":
|
33
|
-
return {
|
34
|
-
k: to_utc(datetime.fromisoformat(v))
|
35
|
-
for k, v in partial_result.items()
|
36
|
-
}
|
37
|
-
|
38
|
-
return {k: to_utc(v) for k, v in partial_result.items()}
|
39
|
-
|
40
|
-
|
41
|
-
ConvertToUTCModel = Annotated[BaseModelT, WrapSerializer(convert_to_utc)]
|
u_toolkit/pydantic/type_vars.py
DELETED
u_toolkit/sqlalchemy/__init__.py
DELETED
File without changes
|
u_toolkit/sqlalchemy/fields.py
DELETED
File without changes
|
u_toolkit/sqlalchemy/function.py
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
import sqlalchemy as sa
|
2
|
-
from sqlalchemy.orm import DeclarativeBase, QueryableAttribute
|
3
|
-
|
4
|
-
|
5
|
-
def json_object_build(
|
6
|
-
label: str,
|
7
|
-
table: type[DeclarativeBase],
|
8
|
-
*attrs: QueryableAttribute | sa.Column,
|
9
|
-
):
|
10
|
-
return sa.func.json_build_object(
|
11
|
-
*[sa.text(f"'{i.key}', {table.__tablename__}.{i.key}") for i in attrs]
|
12
|
-
).label(label)
|
File without changes
|
@@ -1,20 +0,0 @@
|
|
1
|
-
from functools import partial
|
2
|
-
from typing import Annotated
|
3
|
-
from uuid import UUID, uuid4
|
4
|
-
|
5
|
-
from sqlalchemy import BIGINT
|
6
|
-
from sqlalchemy.orm import mapped_column
|
7
|
-
|
8
|
-
|
9
|
-
primary_key_column = partial(mapped_column, primary_key=True, sort_order=-9999)
|
10
|
-
|
11
|
-
IntPrimaryKey = Annotated[int, primary_key_column()]
|
12
|
-
BigIntPrimaryKey = Annotated[int, primary_key_column(BIGINT)]
|
13
|
-
|
14
|
-
_auto_pk = partial(primary_key_column, autoincrement=True)
|
15
|
-
|
16
|
-
AutoIntPrimaryKey = Annotated[int, _auto_pk()]
|
17
|
-
AutoBigIntPrimaryKey = Annotated[int, _auto_pk(BIGINT)]
|
18
|
-
|
19
|
-
|
20
|
-
UUID4PrimaryKey = Annotated[UUID, primary_key_column(default=uuid4)]
|
@@ -1,23 +0,0 @@
|
|
1
|
-
from datetime import datetime
|
2
|
-
|
3
|
-
from pydantic.alias_generators import to_snake
|
4
|
-
from sqlalchemy import func
|
5
|
-
from sqlalchemy.orm import Mapped, declared_attr, mapped_column
|
6
|
-
|
7
|
-
|
8
|
-
class TablenameMixin:
|
9
|
-
# 当继承该类时, 会自动将表名转为 snake 名称形式
|
10
|
-
@declared_attr.directive
|
11
|
-
@classmethod
|
12
|
-
def __tablename__(cls) -> str:
|
13
|
-
return f"{to_snake(cls.__name__)}_tb"
|
14
|
-
|
15
|
-
|
16
|
-
class TimeStampMixin:
|
17
|
-
# 当继承该类时, 会给表添加创建时间和更新时间字段
|
18
|
-
created_at: Mapped[datetime] = mapped_column(
|
19
|
-
server_default=func.now(), sort_order=9998
|
20
|
-
)
|
21
|
-
updated_at: Mapped[datetime | None] = mapped_column(
|
22
|
-
onupdate=func.now(), sort_order=9999
|
23
|
-
)
|
@@ -1,17 +0,0 @@
|
|
1
|
-
import sqlalchemy as sa
|
2
|
-
from pydantic import TypeAdapter
|
3
|
-
|
4
|
-
from .type_vars import DeclarativeBaseT
|
5
|
-
|
6
|
-
|
7
|
-
class TableInfo:
|
8
|
-
def __init__(self, table: type[DeclarativeBaseT]) -> None:
|
9
|
-
self.table = table
|
10
|
-
self.columns = sa.inspect(table).c
|
11
|
-
self.adapters = {
|
12
|
-
i.name: (
|
13
|
-
TypeAdapter(i.type.python_type),
|
14
|
-
i.type.python_type,
|
15
|
-
)
|
16
|
-
for i in self.columns
|
17
|
-
}
|
@@ -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,35 +0,0 @@
|
|
1
|
-
u_toolkit/__init__.py,sha256=7f_bFg1UERA4gyh3HjCAjOZo2cBUgElpwgX5x-Xk2WA,238
|
2
|
-
u_toolkit/alias_generators.py,sha256=KmPL1ViGJjptONffZUAX4ENvkldrwDylm_Ly5RYE8b4,963
|
3
|
-
u_toolkit/datetime.py,sha256=GOG0xa6yKeqvFXJkImK5Pt7wsPXnHMlNKju8deniGJ4,644
|
4
|
-
u_toolkit/decorators.py,sha256=rBZfXtWVfja6YMDqF9izjAiabRVyp4pAWOlwnN0HkUw,2396
|
5
|
-
u_toolkit/enum.py,sha256=nEdcrvAkLc32YioEZSZJM6DClLM2G__mlJFQC64AvBo,895
|
6
|
-
u_toolkit/function.py,sha256=HgZcWd4IydNqUdUbS6A5pXVcAponGUZ2A8YKuiwHGjg,259
|
7
|
-
u_toolkit/helpers.py,sha256=QSkDZH90FfuNB0hWI1GA2KHFk1ajZMzNBr7ysuBdFTg,161
|
8
|
-
u_toolkit/logger.py,sha256=NOmdR24QfSuo1EMnetyFioa8pA8OYceYTlQ4qiQcBdE,209
|
9
|
-
u_toolkit/merge.py,sha256=kHrloud-nPti5j48zkdvaiy4mIJYqOVguixAjWC46kE,924
|
10
|
-
u_toolkit/path.py,sha256=IkyIHcU9hKBCOZfF30FrKf4CfL-MH91fjeYF9EY7eos,128
|
11
|
-
u_toolkit/signature.py,sha256=-Q6n28PYBYYdd2OXBKESeVkL2rYpV6EaY3IVwQmzezQ,2161
|
12
|
-
u_toolkit/fastapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
-
u_toolkit/fastapi/cbv.py,sha256=vRYGeopzduO7Gmf5O5oz76zGOYqFtD8aGAe1oCcK8R4,12910
|
14
|
-
u_toolkit/fastapi/config.py,sha256=kGpokR9XXr1KxMA1GVKYkCdKwqIQAIwOJ-v6sGbqzAQ,267
|
15
|
-
u_toolkit/fastapi/exception.py,sha256=iZy1kjNkhtkLw6nl5x0_g3uvgpkpwutEsjfB7VvX9M0,4640
|
16
|
-
u_toolkit/fastapi/helpers.py,sha256=BCMMLxa1c6BMA_rKq-hCi0iyEjrR3Z5rPMeTvgaVJB0,447
|
17
|
-
u_toolkit/fastapi/lifespan.py,sha256=W1TwWymW7xtmntx59QBC4LQ6xQr3L7yuMMGj4U8hhTQ,1813
|
18
|
-
u_toolkit/fastapi/pagination.py,sha256=yOgEDUT04m_mZ0cPliuDbUHLFnmxGAmr5PyZlwfjT_s,1940
|
19
|
-
u_toolkit/fastapi/responses.py,sha256=alXUuFK9g1xwkw7V_gpeJFyWuGTHSh-fuuWTuaG8of8,1765
|
20
|
-
u_toolkit/pydantic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
|
-
u_toolkit/pydantic/fields.py,sha256=9I8Jwek_oNn_niI98ZWaSPEUYIl5mw24YgbnpcEtgZk,839
|
22
|
-
u_toolkit/pydantic/models.py,sha256=Dqp3HnPlUU7ZpfBbYbERfcrLUb2CBJKHySRvM1Rv3HE,1101
|
23
|
-
u_toolkit/pydantic/type_vars.py,sha256=XBB3r2SipHOIeyCIuhaBwUDuIfm-M8aI3Gg8rx2uT_A,113
|
24
|
-
u_toolkit/sqlalchemy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
|
-
u_toolkit/sqlalchemy/fields.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
26
|
-
u_toolkit/sqlalchemy/function.py,sha256=DRkszvqDfl-BKBW9IcYeN665pgDYlwWiC3DOCjBnxGY,345
|
27
|
-
u_toolkit/sqlalchemy/table_info.py,sha256=EjY2Vxbw2c6TUGBf3NeJl1BB2Tnn9NfaFikUx9I3BBk,441
|
28
|
-
u_toolkit/sqlalchemy/type_vars.py,sha256=m2VeV41CBIK_1QX3w2kgz-n556sILAGZ-Kaz3TDDDIY,143
|
29
|
-
u_toolkit/sqlalchemy/orm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
30
|
-
u_toolkit/sqlalchemy/orm/fields.py,sha256=3zoYil23I6YLtc_59aHDt9w5l1NBTkePT9AfXI3DMiY,593
|
31
|
-
u_toolkit/sqlalchemy/orm/models.py,sha256=V8vf4ps3phAmwxyaFYK7pw8Igz7h097o4QBjKB0gwC8,705
|
32
|
-
u_toolkit-0.1.19.dist-info/METADATA,sha256=cjvH0qajiIc2SdR5lpo49DBtGS1yyaePHdgPBphwb60,366
|
33
|
-
u_toolkit-0.1.19.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
34
|
-
u_toolkit-0.1.19.dist-info/entry_points.txt,sha256=hTfAYCd5vvRiqgnJk2eBsoRIiIVB9pK8WZm3Q3jjKFU,45
|
35
|
-
u_toolkit-0.1.19.dist-info/RECORD,,
|
File without changes
|
File without changes
|