archipy-sqlite 5.24.0__tar.gz → 5.26.0__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.
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: archipy-sqlite
3
- Version: 5.24.0
3
+ Version: 5.26.0
4
4
  Summary: ArchiPy sqlite adapter.
5
5
  Author-email: Hossein Nejati <hosseinnejati14@gmail.com>
6
6
  License-Expression: Apache-2.0
7
7
  Requires-Python: <4,>=3.14
8
8
  Requires-Dist: aiosqlite>=0.22.1
9
- Requires-Dist: archipy==5.24.0
9
+ Requires-Dist: archipy==5.26.0
10
10
  Requires-Dist: sqlalchemy[asyncio]>=2.1.6
11
11
  Description-Content-Type: text/markdown
12
12
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  from typing import Any, override
4
4
 
5
- from sqlalchemy import URL
5
+ from sqlalchemy import URL, Engine, event
6
6
  from sqlalchemy.exc import SQLAlchemyError
7
7
 
8
8
  from archipy.adapters.base.sqlalchemy.session_managers import (
@@ -73,6 +73,37 @@ def _sqlite_pool_kwargs(configs: SQLiteSQLAlchemyConfig, pool_kwargs: dict[str,
73
73
  return {key: value for key, value in pool_kwargs.items() if key not in dropped}
74
74
 
75
75
 
76
+ def _build_connect_args(configs: SQLiteSQLAlchemyConfig, *, sync_driver: bool) -> dict[str, Any]:
77
+ """Build the sqlite3 connection arguments from the configuration.
78
+
79
+ Args:
80
+ configs: SQLite configuration.
81
+ sync_driver: Whether the sync driver is used (``check_same_thread`` has no meaning for aiosqlite,
82
+ which runs its own connection thread).
83
+
84
+ Returns:
85
+ dict[str, Any]: Only the options that are configured (the sqlite3 defaults apply to the rest).
86
+ """
87
+ connect_args: dict[str, Any] = {}
88
+ if configs.TIMEOUT is not None:
89
+ connect_args["timeout"] = configs.TIMEOUT
90
+ if sync_driver and configs.CHECK_SAME_THREAD is not None:
91
+ connect_args["check_same_thread"] = configs.CHECK_SAME_THREAD
92
+ return connect_args
93
+
94
+
95
+ def _enable_foreign_keys(engine: Engine) -> None:
96
+ """Turn on foreign key enforcement for every connection the engine opens (SQLite has it off by default)."""
97
+
98
+ @event.listens_for(engine, "connect")
99
+ def set_foreign_keys_pragma(dbapi_connection: Any, _connection_record: object) -> None: # noqa: ANN401
100
+ cursor = dbapi_connection.cursor()
101
+ try:
102
+ cursor.execute("PRAGMA foreign_keys=ON")
103
+ finally:
104
+ cursor.close()
105
+
106
+
76
107
  class SQLiteSQLAlchemySessionManager(BaseSQLAlchemySessionManager[SQLiteSQLAlchemyConfig], metaclass=Singleton):
77
108
  """Synchronous SQLAlchemy session manager for SQLite.
78
109
 
@@ -96,7 +127,10 @@ class SQLiteSQLAlchemySessionManager(BaseSQLAlchemySessionManager[SQLiteSQLAlche
96
127
  orm_config: SQLite-specific configuration. If None, uses global config.
97
128
  """
98
129
  configs = orm_config or self._default_config()
130
+ self._configs = configs # read by _get_connect_args, which the base initializer calls
99
131
  super().__init__(configs)
132
+ if configs.FOREIGN_KEYS:
133
+ _enable_foreign_keys(self.engine)
100
134
 
101
135
  @override
102
136
  def _expected_config_type(self) -> type[SQLiteSQLAlchemyConfig]:
@@ -116,6 +150,15 @@ class SQLiteSQLAlchemySessionManager(BaseSQLAlchemySessionManager[SQLiteSQLAlche
116
150
  """
117
151
  return "sqlite"
118
152
 
153
+ @override
154
+ def _get_connect_args(self) -> dict[str, Any]:
155
+ """Return the sqlite3 connection arguments.
156
+
157
+ Returns:
158
+ dict[str, Any]: The configured busy timeout and thread check, otherwise empty.
159
+ """
160
+ return _build_connect_args(self._configs, sync_driver=True)
161
+
119
162
  @override
120
163
  def _get_pool_kwargs(self, configs: SQLiteSQLAlchemyConfig) -> dict[str, Any]:
121
164
  """Return pool arguments valid for the SQLite pool class.
@@ -179,7 +222,10 @@ class AsyncSQLiteSQLAlchemySessionManager(
179
222
  orm_config: SQLite-specific configuration. If None, uses global config.
180
223
  """
181
224
  configs = orm_config or self._default_config()
225
+ self._configs = configs # read by _get_connect_args, which the base initializer calls
182
226
  super().__init__(configs)
227
+ if configs.FOREIGN_KEYS:
228
+ _enable_foreign_keys(self.engine.sync_engine)
183
229
 
184
230
  @override
185
231
  def _expected_config_type(self) -> type[SQLiteSQLAlchemyConfig]:
@@ -199,6 +245,15 @@ class AsyncSQLiteSQLAlchemySessionManager(
199
245
  """
200
246
  return "sqlite"
201
247
 
248
+ @override
249
+ def _get_connect_args(self) -> dict[str, Any]:
250
+ """Return the sqlite3 connection arguments.
251
+
252
+ Returns:
253
+ dict[str, Any]: The configured busy timeout, otherwise empty.
254
+ """
255
+ return _build_connect_args(self._configs, sync_driver=False)
256
+
202
257
  @override
203
258
  def _get_pool_kwargs(self, configs: SQLiteSQLAlchemyConfig) -> dict[str, Any]:
204
259
  """Return pool arguments valid for the SQLite pool class.
@@ -5,10 +5,10 @@ authors = [
5
5
  { name = "Hossein Nejati", email = "hosseinnejati14@gmail.com" },
6
6
  ]
7
7
  readme = "README.md"
8
- version = "5.24.0" # This version is set on publish flow!
8
+ version = "5.26.0" # This version is set on publish flow!
9
9
  requires-python = ">=3.14,<4"
10
10
  dependencies = [
11
- "archipy==5.24.0", # Pinned to core version on publish flow!
11
+ "archipy==5.26.0", # Pinned to core version on publish flow!
12
12
  "sqlalchemy[asyncio]>=2.1.6",
13
13
  "aiosqlite>=0.22.1",
14
14
  ]