archipy-sqlite 5.10.0__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.
- archipy/adapters/sqlite/__init__.py +1 -0
- archipy/adapters/sqlite/sqlalchemy/__init__.py +1 -0
- archipy/adapters/sqlite/sqlalchemy/adapters.py +78 -0
- archipy/adapters/sqlite/sqlalchemy/session_manager_registry.py +103 -0
- archipy/adapters/sqlite/sqlalchemy/session_managers.py +199 -0
- archipy_sqlite-5.10.0.dist-info/METADATA +18 -0
- archipy_sqlite-5.10.0.dist-info/RECORD +8 -0
- archipy_sqlite-5.10.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""SQLite adapter package."""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""SQLite SQLAlchemy adapters for ArchiPy."""
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""SQLite SQLAlchemy adapter implementations."""
|
|
2
|
+
|
|
3
|
+
from typing import override
|
|
4
|
+
|
|
5
|
+
from archipy.adapters.base.sqlalchemy.adapters import (
|
|
6
|
+
AsyncBaseSQLAlchemyAdapter,
|
|
7
|
+
BaseSQLAlchemyAdapter,
|
|
8
|
+
)
|
|
9
|
+
from archipy.adapters.sqlite.sqlalchemy.session_managers import (
|
|
10
|
+
AsyncSQLiteSQLAlchemySessionManager,
|
|
11
|
+
SQLiteSQLAlchemySessionManager,
|
|
12
|
+
)
|
|
13
|
+
from archipy.configs.base_config import BaseConfig
|
|
14
|
+
from archipy.configs.config_template import SQLiteSQLAlchemyConfig
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class SQLiteSQLAlchemyAdapter(BaseSQLAlchemyAdapter[SQLiteSQLAlchemyConfig]):
|
|
18
|
+
"""Synchronous SQLAlchemy adapter for SQLite.
|
|
19
|
+
|
|
20
|
+
Inherits from BaseSQLAlchemyAdapter to provide SQLite-specific session management
|
|
21
|
+
and database operations, typically used for in-memory testing.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
orm_config: SQLite-specific configuration. If None, uses global config.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, orm_config: SQLiteSQLAlchemyConfig | None = None) -> None:
|
|
28
|
+
"""Initialize the SQLite adapter with a session manager.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
orm_config: SQLite-specific configuration. If None, uses global config.
|
|
32
|
+
"""
|
|
33
|
+
configs = BaseConfig.global_config().SQLITE_SQLALCHEMY if orm_config is None else orm_config
|
|
34
|
+
super().__init__(configs)
|
|
35
|
+
|
|
36
|
+
@override
|
|
37
|
+
def _create_session_manager(self, configs: SQLiteSQLAlchemyConfig) -> SQLiteSQLAlchemySessionManager:
|
|
38
|
+
"""Create a SQLite-specific session manager.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
configs: SQLite configuration.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
A SQLite session manager instance.
|
|
45
|
+
"""
|
|
46
|
+
return SQLiteSQLAlchemySessionManager(configs)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class AsyncSQLiteSQLAlchemyAdapter(AsyncBaseSQLAlchemyAdapter[SQLiteSQLAlchemyConfig]):
|
|
50
|
+
"""Asynchronous SQLAlchemy adapter for SQLite.
|
|
51
|
+
|
|
52
|
+
Inherits from AsyncBaseSQLAlchemyAdapter to provide async SQLite-specific session
|
|
53
|
+
management and database operations, typically used for in-memory testing.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
orm_config: SQLite-specific configuration. If None, uses global config.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
def __init__(self, orm_config: SQLiteSQLAlchemyConfig | None = None) -> None:
|
|
60
|
+
"""Initialize the async SQLite adapter with a session manager.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
orm_config: SQLite-specific configuration. If None, uses global config.
|
|
64
|
+
"""
|
|
65
|
+
configs = BaseConfig.global_config().SQLITE_SQLALCHEMY if orm_config is None else orm_config
|
|
66
|
+
super().__init__(configs)
|
|
67
|
+
|
|
68
|
+
@override
|
|
69
|
+
def _create_async_session_manager(self, configs: SQLiteSQLAlchemyConfig) -> AsyncSQLiteSQLAlchemySessionManager:
|
|
70
|
+
"""Create an async SQLite-specific session manager.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
configs: SQLite configuration.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
An async SQLite session manager instance.
|
|
77
|
+
"""
|
|
78
|
+
return AsyncSQLiteSQLAlchemySessionManager(configs)
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""Registry for SQLite SQLAlchemy session managers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from archipy.adapters.base.sqlalchemy.session_manager_registry import (
|
|
8
|
+
SessionManagerRegistry,
|
|
9
|
+
)
|
|
10
|
+
from archipy.adapters.sqlite.sqlalchemy.session_managers import (
|
|
11
|
+
AsyncSQLiteSQLAlchemySessionManager,
|
|
12
|
+
SQLiteSQLAlchemySessionManager,
|
|
13
|
+
)
|
|
14
|
+
from archipy.helpers.metaclasses.singleton import Singleton
|
|
15
|
+
from archipy.models.errors import DatabaseConnectionError
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from archipy.adapters.base.sqlalchemy.session_manager_ports import (
|
|
19
|
+
AsyncSessionManagerPort,
|
|
20
|
+
SessionManagerPort,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class SQLiteSessionManagerRegistry(SessionManagerRegistry, metaclass=Singleton):
|
|
25
|
+
"""Registry for SQLite SQLAlchemy session managers.
|
|
26
|
+
|
|
27
|
+
This registry provides a centralized access point for both synchronous and
|
|
28
|
+
asynchronous SQLite session managers, implementing the Service Locator pattern.
|
|
29
|
+
It lazily initializes the appropriate session manager when first requested.
|
|
30
|
+
|
|
31
|
+
The registry maintains singleton instances of:
|
|
32
|
+
- A synchronous session manager (SQLiteSQLAlchemySessionManager)
|
|
33
|
+
- An asynchronous session manager (AsyncSQLiteSQLAlchemySessionManager)
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
@classmethod
|
|
37
|
+
def get_sync_manager(cls) -> SessionManagerPort:
|
|
38
|
+
"""Get the synchronous SQLite session manager instance.
|
|
39
|
+
|
|
40
|
+
Lazily initializes a default SQLiteSQLAlchemySessionManager if none has been set.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
SessionManagerPort: The registered synchronous session manager
|
|
44
|
+
|
|
45
|
+
Raises:
|
|
46
|
+
DatabaseConnectionError: If there's an error initializing the session manager
|
|
47
|
+
"""
|
|
48
|
+
if cls._sync_instance is None:
|
|
49
|
+
try:
|
|
50
|
+
cls._sync_instance = SQLiteSQLAlchemySessionManager()
|
|
51
|
+
except Exception as e:
|
|
52
|
+
raise DatabaseConnectionError(
|
|
53
|
+
database="sqlite",
|
|
54
|
+
) from e
|
|
55
|
+
return cls._sync_instance
|
|
56
|
+
|
|
57
|
+
@classmethod
|
|
58
|
+
def set_sync_manager(cls, manager: SessionManagerPort) -> None:
|
|
59
|
+
"""Register a synchronous session manager.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
manager: The session manager to register
|
|
63
|
+
"""
|
|
64
|
+
cls._sync_instance = manager
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def get_async_manager(cls) -> AsyncSessionManagerPort:
|
|
68
|
+
"""Get the asynchronous SQLite session manager instance.
|
|
69
|
+
|
|
70
|
+
Lazily initializes a default AsyncSQLiteSQLAlchemySessionManager if none has been set.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
AsyncSessionManagerPort: The registered asynchronous session manager
|
|
74
|
+
|
|
75
|
+
Raises:
|
|
76
|
+
DatabaseConnectionError: If there's an error initializing the session manager
|
|
77
|
+
"""
|
|
78
|
+
if cls._async_instance is None:
|
|
79
|
+
try:
|
|
80
|
+
cls._async_instance = AsyncSQLiteSQLAlchemySessionManager()
|
|
81
|
+
except Exception as e:
|
|
82
|
+
raise DatabaseConnectionError(
|
|
83
|
+
database="sqlite",
|
|
84
|
+
) from e
|
|
85
|
+
return cls._async_instance
|
|
86
|
+
|
|
87
|
+
@classmethod
|
|
88
|
+
def set_async_manager(cls, manager: AsyncSessionManagerPort) -> None:
|
|
89
|
+
"""Register an asynchronous session manager.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
manager: The async session manager to register
|
|
93
|
+
"""
|
|
94
|
+
cls._async_instance = manager
|
|
95
|
+
|
|
96
|
+
@classmethod
|
|
97
|
+
def reset(cls) -> None:
|
|
98
|
+
"""Reset the registry to its initial state.
|
|
99
|
+
|
|
100
|
+
This method clears both registered managers, useful for testing.
|
|
101
|
+
"""
|
|
102
|
+
cls._sync_instance = None
|
|
103
|
+
cls._async_instance = None
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"""SQLite SQLAlchemy session manager implementations."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, override
|
|
4
|
+
|
|
5
|
+
from sqlalchemy import URL
|
|
6
|
+
from sqlalchemy.exc import SQLAlchemyError
|
|
7
|
+
|
|
8
|
+
from archipy.adapters.base.sqlalchemy.session_managers import (
|
|
9
|
+
AsyncBaseSQLAlchemySessionManager,
|
|
10
|
+
BaseSQLAlchemySessionManager,
|
|
11
|
+
)
|
|
12
|
+
from archipy.configs.base_config import BaseConfig
|
|
13
|
+
from archipy.configs.config_template import SQLiteSQLAlchemyConfig
|
|
14
|
+
from archipy.helpers.metaclasses.singleton import Singleton
|
|
15
|
+
from archipy.models.errors import DatabaseConnectionError
|
|
16
|
+
|
|
17
|
+
_SYNC_DRIVER = "sqlite"
|
|
18
|
+
_ASYNC_DRIVER = "sqlite+aiosqlite"
|
|
19
|
+
_SYNC_DRIVERS = frozenset({"sqlite", "sqlite+pysqlite"})
|
|
20
|
+
# Queue-pool-only arguments; SQLite in-memory engines use SingletonThreadPool/StaticPool, which reject them.
|
|
21
|
+
_QUEUE_POOL_ONLY_KWARGS = frozenset({"pool_size", "max_overflow", "pool_timeout", "pool_use_lifo"})
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _is_in_memory(database: str | None) -> bool:
|
|
25
|
+
"""Return whether the SQLite database path refers to an in-memory database.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
database: The configured SQLite database path.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
bool: True for ``:memory:``, an empty path, or a ``mode=memory`` URI.
|
|
32
|
+
"""
|
|
33
|
+
return not database or database == ":memory:" or "mode=memory" in database
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _sqlite_pool_kwargs(configs: SQLiteSQLAlchemyConfig, pool_kwargs: dict[str, Any]) -> dict[str, Any]:
|
|
37
|
+
"""Drop queue-pool arguments that SQLite in-memory pools do not accept.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
configs: SQLite configuration.
|
|
41
|
+
pool_kwargs: Pool arguments built by the base session manager.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
dict[str, Any]: Pool arguments valid for the pool class SQLAlchemy selects.
|
|
45
|
+
"""
|
|
46
|
+
if not _is_in_memory(configs.DATABASE):
|
|
47
|
+
return pool_kwargs
|
|
48
|
+
return {key: value for key, value in pool_kwargs.items() if key not in _QUEUE_POOL_ONLY_KWARGS}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class SQLiteSQLAlchemySessionManager(BaseSQLAlchemySessionManager[SQLiteSQLAlchemyConfig], metaclass=Singleton):
|
|
52
|
+
"""Synchronous SQLAlchemy session manager for SQLite.
|
|
53
|
+
|
|
54
|
+
Inherits from BaseSQLAlchemySessionManager to provide SQLite-specific session
|
|
55
|
+
management, including connection URL creation and engine configuration.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
orm_config: SQLite-specific configuration. If None, uses global config.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
def __init__(self, orm_config: SQLiteSQLAlchemyConfig | None = None) -> None:
|
|
62
|
+
"""Initialize the SQLite session manager.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
orm_config: SQLite-specific configuration. If None, uses global config.
|
|
66
|
+
"""
|
|
67
|
+
configs = BaseConfig.global_config().SQLITE_SQLALCHEMY if orm_config is None else orm_config
|
|
68
|
+
super().__init__(configs)
|
|
69
|
+
|
|
70
|
+
@override
|
|
71
|
+
def _expected_config_type(self) -> type[SQLiteSQLAlchemyConfig]:
|
|
72
|
+
"""Return the expected configuration type for SQLite.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
The SQLiteSQLAlchemyConfig class.
|
|
76
|
+
"""
|
|
77
|
+
return SQLiteSQLAlchemyConfig
|
|
78
|
+
|
|
79
|
+
@override
|
|
80
|
+
def _get_database_name(self) -> str:
|
|
81
|
+
"""Return the name of the database being used.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
str: The name of the database ('sqlite').
|
|
85
|
+
"""
|
|
86
|
+
return "sqlite"
|
|
87
|
+
|
|
88
|
+
@override
|
|
89
|
+
def _get_pool_kwargs(self, configs: SQLiteSQLAlchemyConfig) -> dict[str, Any]:
|
|
90
|
+
"""Return pool arguments valid for the SQLite pool class.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
configs: SQLite configuration.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
dict[str, Any]: Pool arguments without queue-pool options for in-memory databases.
|
|
97
|
+
"""
|
|
98
|
+
return _sqlite_pool_kwargs(configs, super()._get_pool_kwargs(configs))
|
|
99
|
+
|
|
100
|
+
@override
|
|
101
|
+
def _create_url(self, configs: SQLiteSQLAlchemyConfig) -> URL:
|
|
102
|
+
"""Create a SQLite connection URL.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
configs: SQLite configuration.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
A SQLAlchemy URL object for SQLite. An async driver such as ``sqlite+aiosqlite``
|
|
109
|
+
is swapped for the sync ``sqlite`` driver.
|
|
110
|
+
|
|
111
|
+
Raises:
|
|
112
|
+
DatabaseConnectionError: If there's an error creating the URL.
|
|
113
|
+
"""
|
|
114
|
+
try:
|
|
115
|
+
return URL.create(
|
|
116
|
+
drivername=(_SYNC_DRIVER if configs.DRIVER_NAME == _ASYNC_DRIVER else configs.DRIVER_NAME),
|
|
117
|
+
database=configs.DATABASE,
|
|
118
|
+
)
|
|
119
|
+
except SQLAlchemyError as e:
|
|
120
|
+
raise DatabaseConnectionError(
|
|
121
|
+
database=self._get_database_name(),
|
|
122
|
+
) from e
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class AsyncSQLiteSQLAlchemySessionManager(
|
|
126
|
+
AsyncBaseSQLAlchemySessionManager[SQLiteSQLAlchemyConfig],
|
|
127
|
+
metaclass=Singleton,
|
|
128
|
+
):
|
|
129
|
+
"""Asynchronous SQLAlchemy session manager for SQLite.
|
|
130
|
+
|
|
131
|
+
Inherits from AsyncBaseSQLAlchemySessionManager to provide async SQLite-specific
|
|
132
|
+
session management, including connection URL creation and async engine configuration.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
orm_config: SQLite-specific configuration. If None, uses global config.
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
def __init__(self, orm_config: SQLiteSQLAlchemyConfig | None = None) -> None:
|
|
139
|
+
"""Initialize the async SQLite session manager.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
orm_config: SQLite-specific configuration. If None, uses global config.
|
|
143
|
+
"""
|
|
144
|
+
configs = BaseConfig.global_config().SQLITE_SQLALCHEMY if orm_config is None else orm_config
|
|
145
|
+
super().__init__(configs)
|
|
146
|
+
|
|
147
|
+
@override
|
|
148
|
+
def _expected_config_type(self) -> type[SQLiteSQLAlchemyConfig]:
|
|
149
|
+
"""Return the expected configuration type for SQLite.
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
The SQLiteSQLAlchemyConfig class.
|
|
153
|
+
"""
|
|
154
|
+
return SQLiteSQLAlchemyConfig
|
|
155
|
+
|
|
156
|
+
@override
|
|
157
|
+
def _get_database_name(self) -> str:
|
|
158
|
+
"""Return the name of the database being used.
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
str: The name of the database ('sqlite').
|
|
162
|
+
"""
|
|
163
|
+
return "sqlite"
|
|
164
|
+
|
|
165
|
+
@override
|
|
166
|
+
def _get_pool_kwargs(self, configs: SQLiteSQLAlchemyConfig) -> dict[str, Any]:
|
|
167
|
+
"""Return pool arguments valid for the SQLite pool class.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
configs: SQLite configuration.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
dict[str, Any]: Pool arguments without queue-pool options for in-memory databases.
|
|
174
|
+
"""
|
|
175
|
+
return _sqlite_pool_kwargs(configs, super()._get_pool_kwargs(configs))
|
|
176
|
+
|
|
177
|
+
@override
|
|
178
|
+
def _create_url(self, configs: SQLiteSQLAlchemyConfig) -> URL:
|
|
179
|
+
"""Create an async SQLite connection URL.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
configs: SQLite configuration.
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
A SQLAlchemy URL object for SQLite. A sync driver such as ``sqlite`` is swapped
|
|
186
|
+
for the async ``sqlite+aiosqlite`` driver.
|
|
187
|
+
|
|
188
|
+
Raises:
|
|
189
|
+
DatabaseConnectionError: If there's an error creating the URL.
|
|
190
|
+
"""
|
|
191
|
+
try:
|
|
192
|
+
return URL.create(
|
|
193
|
+
drivername=(_ASYNC_DRIVER if configs.DRIVER_NAME in _SYNC_DRIVERS else configs.DRIVER_NAME),
|
|
194
|
+
database=configs.DATABASE,
|
|
195
|
+
)
|
|
196
|
+
except SQLAlchemyError as e:
|
|
197
|
+
raise DatabaseConnectionError(
|
|
198
|
+
database=self._get_database_name(),
|
|
199
|
+
) from e
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: archipy-sqlite
|
|
3
|
+
Version: 5.10.0
|
|
4
|
+
Summary: ArchiPy sqlite adapter.
|
|
5
|
+
Author-email: Hossein Nejati <hosseinnejati14@gmail.com>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Requires-Python: <4,>=3.14
|
|
8
|
+
Requires-Dist: aiosqlite>=0.22.1
|
|
9
|
+
Requires-Dist: archipy==5.10.0
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# archipy-sqlite
|
|
13
|
+
|
|
14
|
+
sqlite adapter for [ArchiPy](https://syntaxarc.github.io/ArchiPy/). Install via the core extra:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
uv add "archipy[aiosqlite]"
|
|
18
|
+
```
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
archipy/adapters/sqlite/__init__.py,sha256=RXUomvj3mZS57RgVb4z0tWSttRoy4hEBIUNNLYkZxZE,30
|
|
2
|
+
archipy/adapters/sqlite/sqlalchemy/__init__.py,sha256=8QkLGx0_gZT1dqnPm4YdKzwx4VM4ITm-uPyA4FKXak8,46
|
|
3
|
+
archipy/adapters/sqlite/sqlalchemy/adapters.py,sha256=p4glrd1ITKK3SM5iCxmUXe6jA_LNZ9f0r6lAbZ_JWjA,2799
|
|
4
|
+
archipy/adapters/sqlite/sqlalchemy/session_manager_registry.py,sha256=tFAGvLYczElr7NTilDSQxFCeDz15KY53ONYCZLtyFAE,3528
|
|
5
|
+
archipy/adapters/sqlite/sqlalchemy/session_managers.py,sha256=kgFolt2ZZ7HQ3SLxbDYiO7FIn-HVmJ1EdIDoSSgaaOA,6933
|
|
6
|
+
archipy_sqlite-5.10.0.dist-info/METADATA,sha256=GZ77PnYWPatmHA4ZW_Io-lPjSRVIFSCOhvwK7-M95jg,467
|
|
7
|
+
archipy_sqlite-5.10.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
8
|
+
archipy_sqlite-5.10.0.dist-info/RECORD,,
|