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.
@@ -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
- )
@@ -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
@@ -1,11 +0,0 @@
1
- from u_toolkit.enum import NameEnum, auto
2
-
3
-
4
- class LogLevel(NameEnum):
5
- TRACE = auto()
6
- DEBUG = auto()
7
- INFO = auto()
8
- SUCCESS = auto()
9
- WARNING = auto()
10
- ERROR = auto()
11
- CRITICAL = auto()
File without changes
@@ -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)]
@@ -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)]
@@ -1,6 +0,0 @@
1
- from typing import TypeVar
2
-
3
- from pydantic import BaseModel
4
-
5
-
6
- BaseModelT = TypeVar("BaseModelT", bound=BaseModel)
File without changes
File without changes
@@ -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,6 +0,0 @@
1
- from typing import TypeVar
2
-
3
- from sqlalchemy.orm import DeclarativeBase
4
-
5
-
6
- DeclarativeBaseT = TypeVar("DeclarativeBaseT", bound=DeclarativeBase)
@@ -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,,