esuls 0.1.17__tar.gz → 0.1.18__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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: esuls
3
- Version: 0.1.17
3
+ Version: 0.1.18
4
4
  Summary: Utility library for async database operations, HTTP requests, and parallel execution
5
5
  Author-email: IperGiove <ipergiove@gmail.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "esuls"
7
- version = "0.1.17"
7
+ version = "0.1.18"
8
8
  description = "Utility library for async database operations, HTTP requests, and parallel execution"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.14"
@@ -46,6 +46,8 @@ class AsyncDB(Generic[SchemaType]):
46
46
  _schema_init_lock: asyncio.Lock = None
47
47
  # Threading lock to guard class-level dict mutations
48
48
  _db_locks_guard = threading.Lock()
49
+ # Track all instances for cleanup
50
+ _instances: list['AsyncDB'] = []
49
51
 
50
52
  def __init__(self, db_path: Union[str, Path], table_name: str, schema_class: Type[SchemaType]):
51
53
  """Initialize AsyncDB with a path and schema dataclass."""
@@ -76,6 +78,9 @@ class AsyncDB(Generic[SchemaType]):
76
78
  # Persistent connection (lazy init)
77
79
  self._connection: Optional[aiosqlite.Connection] = None
78
80
 
81
+ # Track instance for cleanup
82
+ AsyncDB._instances.append(self)
83
+
79
84
  # Use a class-level set to track initialized schemas
80
85
  if not hasattr(AsyncDB, '_initialized_schemas'):
81
86
  AsyncDB._initialized_schemas = set()
@@ -138,6 +143,13 @@ class AsyncDB(Generic[SchemaType]):
138
143
  pass
139
144
  self._connection = None
140
145
 
146
+ @classmethod
147
+ async def close_all(cls) -> None:
148
+ """Close all AsyncDB instances."""
149
+ for instance in cls._instances:
150
+ await instance.close()
151
+ cls._instances.clear()
152
+
141
153
  async def _init_schema(self, db: aiosqlite.Connection) -> None:
142
154
  """Generate schema from dataclass structure with support for field additions."""
143
155
  logger.debug(f"Initializing schema for {self.schema_class.__name__} in table {self.table_name}")
@@ -3,6 +3,7 @@ from functools import lru_cache
3
3
  from typing import TypeAlias, Union, Optional, Dict, Any, AsyncContextManager, Literal
4
4
  from urllib.parse import urlparse
5
5
  import asyncio
6
+ import atexit
6
7
  import json
7
8
  import random
8
9
  import ssl
@@ -257,12 +258,32 @@ async def close_shared_client() -> None:
257
258
 
258
259
 
259
260
  async def cleanup_all() -> None:
260
- """Close all global HTTP resources (domain clients + cffi session)."""
261
+ """Close all global HTTP resources (domain clients + cffi session) and DB connections."""
261
262
  await close_shared_client()
262
263
  if _get_session_cffi.cache_info().currsize > 0:
263
264
  cffi_session = _get_session_cffi()
264
265
  await cffi_session.close()
265
266
  _get_session_cffi.cache_clear()
267
+ # Close all AsyncDB instances
268
+ from esuls.db_cli import AsyncDB
269
+ await AsyncDB.close_all()
270
+
271
+
272
+ def _atexit_cleanup() -> None:
273
+ """Run async cleanup at process exit."""
274
+ try:
275
+ loop = asyncio.get_event_loop()
276
+ if loop.is_running():
277
+ loop.create_task(cleanup_all())
278
+ else:
279
+ loop.run_until_complete(cleanup_all())
280
+ except RuntimeError:
281
+ loop = asyncio.new_event_loop()
282
+ loop.run_until_complete(cleanup_all())
283
+ loop.close()
284
+
285
+
286
+ atexit.register(_atexit_cleanup)
266
287
 
267
288
 
268
289
  async def close_domain_client(url: str, http2: Optional[bool] = None) -> None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: esuls
3
- Version: 0.1.17
3
+ Version: 0.1.18
4
4
  Summary: Utility library for async database operations, HTTP requests, and parallel execution
5
5
  Author-email: IperGiove <ipergiove@gmail.com>
6
6
  License: MIT
File without changes
File without changes
File without changes
File without changes
File without changes