lush-sqlalchemyx 0.2.0__tar.gz → 0.2.1__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 (25) hide show
  1. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/PKG-INFO +2 -2
  2. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/pyproject.toml +9 -2
  3. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/_compat.py +1 -4
  4. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/base/dal/__init__.py +32 -33
  5. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/base/dal/_async.py +2 -5
  6. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/base/dal/_common.py +3 -7
  7. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/base/dal/_sync.py +3 -5
  8. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/integrations/flask/ext.py +6 -12
  9. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/README.md +0 -0
  10. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/__init__.py +0 -0
  11. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/base/__init__.py +0 -0
  12. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/integrations/__init__.py +0 -0
  13. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/integrations/fastapi/__init__.py +0 -0
  14. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/integrations/fastapi/depends/__init__.py +0 -0
  15. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/integrations/flask/__init__.py +0 -0
  16. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/mgrs/__init__.py +0 -0
  17. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/mgrs/mysql/__init__.py +0 -0
  18. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/mgrs/mysql/manager.py +0 -0
  19. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/mgrs/mysql/mapper.py +0 -0
  20. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/mgrs/mysql/sync_manager.py +0 -0
  21. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/mgrs/mysql/sync_mapper.py +0 -0
  22. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/py.typed +0 -0
  23. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/same_impl_just_warn_wrapper.py +0 -0
  24. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/shortcuts/__init__.py +0 -0
  25. {lush_sqlalchemyx-0.2.0 → lush_sqlalchemyx-0.2.1}/src/lush_sqlalchemyx/shortcuts/meta.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: lush-sqlalchemyx
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: SQLAlchemy helpers (DAL) and async MySQL managers, with some web frameworks integrations
5
5
  Author: straydragon
6
6
  Author-email: straydragon <straydragonl@foxmail.com>
@@ -8,7 +8,7 @@ License: Apache-2.0
8
8
  Classifier: Programming Language :: Python :: 3 :: Only
9
9
  Classifier: Programming Language :: Python :: 3.10
10
10
  Requires-Dist: sqlalchemy>=2.0.21
11
- Requires-Dist: pydantic>=2.11.0,<3.0.0
11
+ Requires-Dist: pydantic>=2.3.0,<3.0.0
12
12
  Requires-Dist: typing-extensions>=4.12.2
13
13
  Requires-Dist: lush-pydanticx>=0.1.0
14
14
  Requires-Dist: lush-stdx>=0.1.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "lush-sqlalchemyx"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  description = "SQLAlchemy helpers (DAL) and async MySQL managers, with some web frameworks integrations"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -12,7 +12,7 @@ classifiers = [
12
12
  ]
13
13
  dependencies = [
14
14
  "sqlalchemy>=2.0.21",
15
- "pydantic>=2.11.0,<3.0.0",
15
+ "pydantic>=2.3.0,<3.0.0",
16
16
  "typing-extensions>=4.12.2",
17
17
  "lush-pydanticx>=0.1.0",
18
18
  "lush-stdx>=0.1.0",
@@ -138,6 +138,12 @@ ignore = [
138
138
  # === 其他 ===
139
139
  "D", # 文档字符串相关规则
140
140
  "EM", # 错误消息相关规则
141
+
142
+ # === 新增 (ruff v0.15+) ===
143
+ "PLC0105", # TypeVar 命名约定 (重命名会破坏 API)
144
+ "PLW0127", # 自赋值重导出 (intentional re-export)
145
+ "RUF022", # __all__ 排序 (intentional grouping)
146
+ "RUF002", # 中文 docstring 中使用全角标点
141
147
  ]
142
148
 
143
149
  [tool.ruff.lint.per-file-ignores]
@@ -155,6 +161,7 @@ ignore = [
155
161
  "N802", # 函数名不规范
156
162
  "PERF401", # 性能相关
157
163
  "PT", # assert 相关
164
+ "E402", # 模块级导入不在顶部
158
165
 
159
166
  # === 测试安全相关 ===
160
167
  "S101", # assert语句(测试中使用)
@@ -18,7 +18,4 @@ def require_async() -> None:
18
18
  以便用户看到清晰的错误信息而非深层调用栈中的 ``AttributeError``.
19
19
  """
20
20
  if not _HAS_ASYNC:
21
- raise ImportError(
22
- "Async support requires 'sqlalchemy[asyncio]' (greenlet). "
23
- "Install with: pip install 'lush-sqlalchemyx[asyncio]'"
24
- )
21
+ raise ImportError("Async support requires 'sqlalchemy[asyncio]' (greenlet). Install with: pip install 'lush-sqlalchemyx[asyncio]'")
@@ -4,6 +4,34 @@
4
4
  """
5
5
 
6
6
  # --- shared (sync/async agnostic) ---
7
+ # --- lush-dal-protocol protocols (ORM 无关的抽象层) ---
8
+ from lush_dal_protocol import (
9
+ AsyncBaseDALProtocol,
10
+ AsyncReadDALProtocol,
11
+ AsyncWriteDALProtocol,
12
+ SyncBaseDALProtocol,
13
+ SyncReadDALProtocol,
14
+ SyncWriteDALProtocol,
15
+ )
16
+
17
+ # --- async (requires sqlalchemy[asyncio]) ---
18
+ from ._async import (
19
+ AsyncBaseDAL,
20
+ AsyncRawDAL,
21
+ AsyncRawReadDAL,
22
+ AsyncReadDAL,
23
+ AsyncSqlATableBase,
24
+ AsyncSQLATableT,
25
+ AsyncWriteDAL,
26
+ AsyncXDALOp,
27
+ BasicAsyncBaseTable,
28
+ ReadOnlyAsyncBaseDAL,
29
+ ReadOnlyBasicAsyncBaseTable,
30
+ StdAsyncBaseTable,
31
+ StdReadOnlyBasicAsyncBaseTable,
32
+ async_temp_set_lock_wait_timeout,
33
+ async_with_retry,
34
+ )
7
35
  from ._common import (
8
36
  DEFAULT_RETRY_CONFIG,
9
37
  OPTIMISTIC_LOCK_ERROR_MSG_TRAIT,
@@ -18,8 +46,8 @@ from ._common import (
18
46
  FieldMixin,
19
47
  ReadOnlyMixin,
20
48
  RetryConfig,
21
- SQLATableT,
22
49
  SoftDeleteTableMixin,
50
+ SQLATableT,
23
51
  StdBaseCU,
24
52
  StdBaseDTO,
25
53
  T,
@@ -30,37 +58,8 @@ from ._common import (
30
58
  )
31
59
 
32
60
  # Event listener references — accessed by tests via getattr(module, name).
33
- from ._common import __prevent_readonly_write as __prevent_readonly_write # noqa: F401, PLC2701
34
- from ._common import __receive_before_flush as __receive_before_flush # noqa: F401, PLC2701
35
-
36
- # --- async (requires sqlalchemy[asyncio]) ---
37
- from ._async import (
38
- AsyncBaseDAL,
39
- AsyncRawDAL,
40
- AsyncRawReadDAL,
41
- AsyncReadDAL,
42
- AsyncSQLATableT,
43
- AsyncSqlATableBase,
44
- AsyncWriteDAL,
45
- AsyncXDALOp,
46
- BasicAsyncBaseTable,
47
- ReadOnlyAsyncBaseDAL,
48
- ReadOnlyBasicAsyncBaseTable,
49
- StdAsyncBaseTable,
50
- StdReadOnlyBasicAsyncBaseTable,
51
- async_temp_set_lock_wait_timeout,
52
- async_with_retry,
53
- )
54
-
55
- # --- lush-dal-protocol protocols (ORM 无关的抽象层) ---
56
- from lush_dal_protocol import (
57
- AsyncBaseDALProtocol,
58
- AsyncReadDALProtocol,
59
- AsyncWriteDALProtocol,
60
- SyncBaseDALProtocol,
61
- SyncReadDALProtocol,
62
- SyncWriteDALProtocol,
63
- )
61
+ from ._common import __prevent_readonly_write as __prevent_readonly_write
62
+ from ._common import __receive_before_flush as __receive_before_flush
64
63
 
65
64
  # --- sync ---
66
65
  from ._sync import (
@@ -73,8 +72,8 @@ from ._sync import (
73
72
  SyncRawDAL,
74
73
  SyncRawReadDAL,
75
74
  SyncReadDAL,
76
- SyncSQLATableT,
77
75
  SyncSqlATableBase,
76
+ SyncSQLATableT,
78
77
  SyncWriteDAL,
79
78
  SyncXDALOp,
80
79
  sync_temp_set_lock_wait_timeout,
@@ -25,13 +25,10 @@ from ._common import (
25
25
  OPTIMISTIC_LOCK_ERROR_MSG_TRAIT,
26
26
  PESSIMISTIC_LOCK_ERROR_MSG_TRAIT,
27
27
  READONLY_SESSION_FLAG,
28
- BaseCU,
29
- BaseDTO,
30
28
  BaseModelT,
31
29
  CUModelT,
32
30
  DBRetryableError,
33
31
  DTOModelT,
34
- FieldMixin,
35
32
  ReadOnlyMixin,
36
33
  RetryConfig,
37
34
  SoftDeleteTableMixin,
@@ -231,7 +228,7 @@ class AsyncRawReadDAL:
231
228
  cls,
232
229
  session: AsyncSession,
233
230
  sql: str | sa.TextClause,
234
- params: "_CoreAnyExecuteParams | None" = None,
231
+ params: _CoreAnyExecuteParams | None = None,
235
232
  ) -> sa.Result[Any]:
236
233
  if params is None:
237
234
  params = {}
@@ -500,7 +497,7 @@ class AsyncRawDAL:
500
497
  cls,
501
498
  session: AsyncSession,
502
499
  sql: str | sa.TextClause,
503
- params: "_CoreAnyExecuteParams | None" = None,
500
+ params: _CoreAnyExecuteParams | None = None,
504
501
  ) -> sa.Result[Any]:
505
502
  if params is None:
506
503
  params = {}
@@ -10,19 +10,15 @@ import logging
10
10
  import random
11
11
  from collections.abc import Callable, Iterable
12
12
  from dataclasses import dataclass
13
- from typing import TYPE_CHECKING, Any, ClassVar, Final, Generic, TypeVar, cast
13
+ from typing import Any, ClassVar, Final, Generic, TypeVar, cast
14
14
 
15
15
  import sqlalchemy as sa
16
16
  from pydantic import BaseModel, ConfigDict, Field
17
- from sqlalchemy import ColumnExpressionArgument
18
17
  from sqlalchemy import event as sa_event
19
18
  from sqlalchemy.exc import OperationalError as SQLAlchemyOperationalError
20
- from sqlalchemy.orm import DeclarativeBase, InstrumentedAttribute, Mapped, ORMExecuteState, mapped_column, with_loader_criteria
19
+ from sqlalchemy.orm import DeclarativeBase, Mapped, ORMExecuteState, mapped_column, with_loader_criteria
21
20
  from sqlalchemy.orm import Session as SyncSession
22
21
 
23
- if TYPE_CHECKING:
24
- from sqlalchemy.engine.interfaces import _CoreAnyExecuteParams # pragma: no cover # pyright: ignore[reportPrivateUsage]
25
-
26
22
  READONLY_SESSION_FLAG: Final[str] = "__lush_sqlalchemyx__readonly_session__"
27
23
 
28
24
  _LOGGER = logging.getLogger(__name__)
@@ -317,6 +313,7 @@ __all__ = (
317
313
  "OPTIMISTIC_LOCK_ERROR_MSG_TRAIT",
318
314
  "PESSIMISTIC_LOCK_ERROR_MSG_TRAIT",
319
315
  "READONLY_SESSION_FLAG",
316
+ "_LOGGER",
320
317
  "BaseCU",
321
318
  "BaseDTO",
322
319
  "BaseModelT",
@@ -333,7 +330,6 @@ __all__ = (
333
330
  "StdBaseDTO",
334
331
  "T",
335
332
  "V",
336
- "_LOGGER",
337
333
  "_ensure_strict_fields",
338
334
  "escape_like",
339
335
  "filtered_in_sql_values",
@@ -22,12 +22,10 @@ from ._common import (
22
22
  OPTIMISTIC_LOCK_ERROR_MSG_TRAIT,
23
23
  PESSIMISTIC_LOCK_ERROR_MSG_TRAIT,
24
24
  READONLY_SESSION_FLAG,
25
- BaseCU,
26
25
  BaseModelT,
27
26
  CUModelT,
28
27
  DBRetryableError,
29
28
  DTOModelT,
30
- FieldMixin,
31
29
  ReadOnlyMixin,
32
30
  RetryConfig,
33
31
  SoftDeleteTableMixin,
@@ -116,7 +114,7 @@ def sync_temp_set_lock_wait_timeout(
116
114
  # Sync Table bases
117
115
  # ---------------------------------------------------------------------------
118
116
 
119
- SyncSQLATableT = TypeVar("SyncSQLATableT", bound="SyncSqlATableBase")
117
+ SyncSQLATableT = TypeVar("SyncSQLATableT", bound=DeclarativeBase)
120
118
 
121
119
 
122
120
  class SyncSqlATableBase(DeclarativeBase):
@@ -224,7 +222,7 @@ class SyncRawReadDAL:
224
222
  cls,
225
223
  session: Session,
226
224
  sql: str | sa.TextClause,
227
- params: "_CoreAnyExecuteParams | None" = None,
225
+ params: _CoreAnyExecuteParams | None = None,
228
226
  ) -> sa.Result[Any]:
229
227
  if params is None:
230
228
  params = {}
@@ -490,7 +488,7 @@ class SyncRawDAL:
490
488
  cls,
491
489
  session: Session,
492
490
  sql: str | sa.TextClause,
493
- params: "_CoreAnyExecuteParams | None" = None,
491
+ params: _CoreAnyExecuteParams | None = None,
494
492
  ) -> sa.Result[Any]:
495
493
  if params is None:
496
494
  params = {}
@@ -25,15 +25,11 @@ try:
25
25
  from flask import g
26
26
  from flask_sqlalchemy import SQLAlchemy
27
27
  except ImportError as _exc: # pragma: no cover
28
- raise ImportError(
29
- "Flask integration requires 'flask-sqlalchemy'. "
30
- "Install with: pip install 'lush-sqlalchemyx[flask]'"
31
- ) from _exc
28
+ raise ImportError("Flask integration requires 'flask-sqlalchemy'. Install with: pip install 'lush-sqlalchemyx[flask]'") from _exc
32
29
 
33
- from sqlalchemy.engine import Engine
34
30
  from sqlalchemy.orm import Session
35
31
 
36
- from lush_sqlalchemyx.base.dal._common import BaseCU, BaseDTO, CUModelT, DTOModelT, SQLATableT
32
+ from lush_sqlalchemyx.base.dal._common import CUModelT, DTOModelT, SQLATableT
37
33
  from lush_sqlalchemyx.base.dal._sync import SyncBaseDAL, SyncReadDAL, SyncWriteDAL
38
34
  from lush_sqlalchemyx.mgrs.mysql.sync_manager import SyncMySQLManager
39
35
  from lush_sqlalchemyx.mgrs.mysql.sync_mapper import SyncMySQLManagersMapper
@@ -102,8 +98,7 @@ class MySQLManagerMapperFlaskDepends(Generic[FlaskDBEnumT]):
102
98
  mapper = getattr(g, cls.g_attr_name, None)
103
99
  if mapper is None:
104
100
  raise RuntimeError(
105
- f"SyncMySQLManagersMapper not found on flask.g.{cls.g_attr_name}. "
106
- "Ensure it is set in a before_request hook."
101
+ f"SyncMySQLManagersMapper not found on flask.g.{cls.g_attr_name}. Ensure it is set in a before_request hook."
107
102
  )
108
103
  return mapper
109
104
 
@@ -152,10 +147,12 @@ class FlaskSessionDALAdapter(Generic[SQLATableT, DTOModelT, CUModelT]):
152
147
  _Table = UserTable
153
148
  _DTO = UserDTO
154
149
 
150
+
155
151
  # 2. 创建适配器
156
152
  class UserFlaskDAL(FlaskSessionDALAdapter[UserTable, UserDTO, UserCU]):
157
153
  _dal_class = UserDAL
158
154
 
155
+
159
156
  # 3. 在服务启动时绑定 db
160
157
  FlaskSessionDALAdapter.bind_db(db)
161
158
 
@@ -185,10 +182,7 @@ class FlaskSessionDALAdapter(Generic[SQLATableT, DTOModelT, CUModelT]):
185
182
  def session(self) -> Session:
186
183
  """获取当前 Flask request 作用域的 session."""
187
184
  if self._db is None:
188
- raise RuntimeError(
189
- "FlaskSessionDALAdapter not bound to db. "
190
- "Call FlaskSessionDALAdapter.bind_db(db) during app init."
191
- )
185
+ raise RuntimeError("FlaskSessionDALAdapter not bound to db. Call FlaskSessionDALAdapter.bind_db(db) during app init.")
192
186
  return self._db.session
193
187
 
194
188
  def get_by_id(self, entity_id: int) -> SQLATableT | None: