fixturify 0.1.9__py3-none-any.whl → 0.1.11__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.
fixturify/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """PyTools - A collection of reusable Python utility modules."""
2
2
 
3
- __version__ = "0.1.8"
3
+ __version__ = "0.1.11"
4
4
 
5
5
  from fixturify.sql_d import sql, Phase, SqlTestConfig
6
6
  from fixturify.read_d import read
@@ -115,18 +115,33 @@ class JsonAssert:
115
115
  """
116
116
  Compare data to JSON file. Raises AssertionError if different.
117
117
 
118
+ If the file doesn't exist, it will be created with the current data.
119
+
118
120
  Args:
119
121
  relative_path: Path to JSON file, relative to caller's location
120
122
 
121
123
  Raises:
122
124
  AssertionError: If data doesn't match file content (with diff details)
123
- FileNotFoundError: If JSON file doesn't exist
124
125
  ValueError: If data can't be converted or file can't be parsed
125
126
  """
126
127
  # Resolve the path relative to the caller's file
127
128
  # Use centralized caller detection from _PathResolver
128
129
  caller_file = _PathResolver._get_caller_file(stack_level=1)
129
- expected_path = _PathResolver.resolve(relative_path, caller_file)
130
+ expected_path = _PathResolver.resolve_without_check(relative_path, caller_file)
131
+
132
+ # If file doesn't exist, create it with current data
133
+ if not expected_path.exists():
134
+ try:
135
+ actual_data = self._normalizer.normalize(self._data)
136
+ except ValueError as e:
137
+ raise ValueError(f"Cannot normalize actual data: {e}")
138
+
139
+ expected_path.parent.mkdir(parents=True, exist_ok=True)
140
+ expected_path.write_text(
141
+ json.dumps(actual_data, indent=2, ensure_ascii=False),
142
+ encoding=ENCODING
143
+ )
144
+ return
130
145
 
131
146
  # Read and parse the expected JSON file
132
147
  try:
@@ -1,7 +1,8 @@
1
1
  """SQL module for executing SQL files before/after tests."""
2
2
 
3
3
  from fixturify.sql_d._config import SqlTestConfig
4
+ from fixturify.sql_d._connection_cache import get_connection_cache
4
5
  from fixturify.sql_d._decorator import sql
5
6
  from fixturify.sql_d._phase import Phase
6
7
 
7
- __all__ = ["sql", "Phase", "SqlTestConfig"]
8
+ __all__ = ["sql", "Phase", "SqlTestConfig", "get_connection_cache"]
@@ -0,0 +1,220 @@
1
+ """Connection cache for sharing database connections across test decorators.
2
+
3
+ This module provides a singleton cache that stores database connections
4
+ keyed by their configuration. This avoids creating a new connection
5
+ for each @sql decorator invocation, significantly improving test performance.
6
+ """
7
+
8
+ import atexit
9
+ import asyncio
10
+ from dataclasses import dataclass
11
+ from typing import Any, Dict, Optional, Tuple, TYPE_CHECKING
12
+
13
+ if TYPE_CHECKING:
14
+ from ._config import SqlTestConfig
15
+
16
+
17
+ @dataclass(frozen=True)
18
+ class CacheKey:
19
+ """Immutable key for connection cache lookup."""
20
+
21
+ driver: str
22
+ host: str
23
+ database: str
24
+ user: str
25
+ port: Optional[int]
26
+
27
+ @classmethod
28
+ def from_config(cls, config: "SqlTestConfig") -> "CacheKey":
29
+ """Create cache key from SqlTestConfig."""
30
+ return cls(
31
+ driver=config.driver,
32
+ host=config.host,
33
+ database=config.database,
34
+ user=config.user,
35
+ port=config.port,
36
+ )
37
+
38
+
39
+ class ConnectionCache:
40
+ """
41
+ Singleton cache for database connections.
42
+
43
+ Maintains separate caches for sync and async connections.
44
+ Connections are created on first access and reused for subsequent calls.
45
+ All connections are closed when the process exits via atexit handler.
46
+ """
47
+
48
+ _instance: Optional["ConnectionCache"] = None
49
+
50
+ def __new__(cls) -> "ConnectionCache":
51
+ if cls._instance is None:
52
+ cls._instance = super().__new__(cls)
53
+ cls._instance._initialized = False
54
+ return cls._instance
55
+
56
+ def __init__(self) -> None:
57
+ if self._initialized:
58
+ return
59
+ self._initialized = True
60
+ self._sync_connections: Dict[CacheKey, Any] = {}
61
+ self._async_connections: Dict[CacheKey, Any] = {}
62
+ self._sync_close_funcs: Dict[CacheKey, Any] = {}
63
+ self._async_close_funcs: Dict[CacheKey, Any] = {}
64
+
65
+ def get_sync(
66
+ self,
67
+ config: "SqlTestConfig",
68
+ connect_func: Any,
69
+ connect_params: Dict[str, Any],
70
+ ) -> Any:
71
+ """
72
+ Get or create a sync connection.
73
+
74
+ Args:
75
+ config: Database configuration
76
+ connect_func: Function to create connection (e.g., driver.connect)
77
+ connect_params: Parameters to pass to connect_func
78
+
79
+ Returns:
80
+ Database connection object
81
+ """
82
+ key = CacheKey.from_config(config)
83
+
84
+ if key not in self._sync_connections:
85
+ connection = connect_func(**connect_params)
86
+ self._sync_connections[key] = connection
87
+
88
+ return self._sync_connections[key]
89
+
90
+ async def get_async(
91
+ self,
92
+ config: "SqlTestConfig",
93
+ connect_coro: Any,
94
+ ) -> Any:
95
+ """
96
+ Get or create an async connection.
97
+
98
+ Args:
99
+ config: Database configuration
100
+ connect_coro: Coroutine that creates connection
101
+
102
+ Returns:
103
+ Database connection object
104
+ """
105
+ key = CacheKey.from_config(config)
106
+
107
+ if key not in self._async_connections:
108
+ connection = await connect_coro
109
+ self._async_connections[key] = connection
110
+
111
+ return self._async_connections[key]
112
+
113
+ def register_sync_closer(
114
+ self,
115
+ config: "SqlTestConfig",
116
+ close_func: Any,
117
+ ) -> None:
118
+ """Register a close function for a sync connection."""
119
+ key = CacheKey.from_config(config)
120
+ if key not in self._sync_close_funcs:
121
+ self._sync_close_funcs[key] = close_func
122
+
123
+ def register_async_closer(
124
+ self,
125
+ config: "SqlTestConfig",
126
+ close_func: Any,
127
+ ) -> None:
128
+ """Register a close function for an async connection."""
129
+ key = CacheKey.from_config(config)
130
+ if key not in self._async_close_funcs:
131
+ self._async_close_funcs[key] = close_func
132
+
133
+ def close_all_sync(self) -> None:
134
+ """Close all cached sync connections."""
135
+ for key, connection in list(self._sync_connections.items()):
136
+ try:
137
+ if key in self._sync_close_funcs:
138
+ self._sync_close_funcs[key](connection)
139
+ elif hasattr(connection, "close"):
140
+ connection.close()
141
+ except Exception:
142
+ pass # Best effort cleanup
143
+ self._sync_connections.clear()
144
+ self._sync_close_funcs.clear()
145
+
146
+ def close_all_async_sync(self) -> None:
147
+ """
148
+ Close all async connections from sync context.
149
+
150
+ This is called by atexit handler which runs in sync context.
151
+ We need to handle async cleanup carefully.
152
+ """
153
+ for key, connection in list(self._async_connections.items()):
154
+ try:
155
+ if hasattr(connection, "close"):
156
+ # Some async connections have sync close()
157
+ result = connection.close()
158
+ # If close() returns a coroutine, we need to run it
159
+ if asyncio.iscoroutine(result):
160
+ try:
161
+ loop = asyncio.get_event_loop()
162
+ if loop.is_running():
163
+ # Can't run from within running loop
164
+ pass
165
+ else:
166
+ loop.run_until_complete(result)
167
+ except RuntimeError:
168
+ # No event loop, create new one
169
+ asyncio.run(result)
170
+ except Exception:
171
+ pass # Best effort cleanup
172
+ self._async_connections.clear()
173
+ self._async_close_funcs.clear()
174
+
175
+ async def close_all_async(self) -> None:
176
+ """Close all cached async connections from async context."""
177
+ for key, connection in list(self._async_connections.items()):
178
+ try:
179
+ if key in self._async_close_funcs:
180
+ await self._async_close_funcs[key](connection)
181
+ elif hasattr(connection, "close"):
182
+ result = connection.close()
183
+ if asyncio.iscoroutine(result):
184
+ await result
185
+ # Handle wait_closed for aiomysql-style connections
186
+ if hasattr(connection, "wait_closed"):
187
+ await connection.wait_closed()
188
+ except Exception:
189
+ pass # Best effort cleanup
190
+ self._async_connections.clear()
191
+ self._async_close_funcs.clear()
192
+
193
+ def clear(self) -> None:
194
+ """Clear all connections (for testing purposes)."""
195
+ self.close_all_sync()
196
+ self.close_all_async_sync()
197
+
198
+
199
+ # Global cache instance
200
+ _cache: Optional[ConnectionCache] = None
201
+
202
+
203
+ def get_connection_cache() -> ConnectionCache:
204
+ """Get the global connection cache instance."""
205
+ global _cache
206
+ if _cache is None:
207
+ _cache = ConnectionCache()
208
+ return _cache
209
+
210
+
211
+ def _cleanup_connections() -> None:
212
+ """Cleanup handler called at process exit."""
213
+ global _cache
214
+ if _cache is not None:
215
+ _cache.close_all_sync()
216
+ _cache.close_all_async_sync()
217
+
218
+
219
+ # Register cleanup handler
220
+ atexit.register(_cleanup_connections)
@@ -26,17 +26,14 @@ class AiomysqlStrategy(AsyncSqlExecutionStrategy):
26
26
  """Execute SQL using aiomysql."""
27
27
  driver = self.get_driver_module()
28
28
  params = self.build_connection_params(config)
29
-
30
- connection = await driver.connect(**params)
31
- try:
32
- async with connection.cursor() as cursor:
33
- # aiomysql doesn't support multi-statement by default
34
- await self._execute_statements(cursor, sql_content)
35
- await connection.commit()
36
- finally:
37
- connection.close()
38
- if hasattr(connection, "wait_closed"):
39
- await connection.wait_closed()
29
+
30
+ connection = await self.get_cached_connection_async(
31
+ config, driver.connect(**params)
32
+ )
33
+ async with connection.cursor() as cursor:
34
+ # aiomysql doesn't support multi-statement by default
35
+ await self._execute_statements(cursor, sql_content)
36
+ await connection.commit()
40
37
 
41
38
  async def _execute_statements(self, cursor: Any, sql_content: str) -> None:
42
39
  """
@@ -22,8 +22,11 @@ class AiosqliteStrategy(AsyncSqlExecutionStrategy):
22
22
  """Execute SQL using aiosqlite."""
23
23
  driver = self.get_driver_module()
24
24
  params = self.build_connection_params(config)
25
-
25
+
26
26
  database_path = params.get("database", ":memory:")
27
- async with driver.connect(database_path) as connection:
28
- await connection.executescript(sql_content)
29
- await connection.commit()
27
+
28
+ connection = await self.get_cached_connection_async(
29
+ config, driver.connect(database_path)
30
+ )
31
+ await connection.executescript(sql_content)
32
+ await connection.commit()
@@ -26,9 +26,8 @@ class AsyncpgStrategy(AsyncSqlExecutionStrategy):
26
26
  """Execute SQL using asyncpg."""
27
27
  driver = self.get_driver_module()
28
28
  params = self.build_connection_params(config)
29
-
30
- connection = await driver.connect(**params)
31
- try:
32
- await connection.execute(sql_content)
33
- finally:
34
- await connection.close()
29
+
30
+ connection = await self.get_cached_connection_async(
31
+ config, driver.connect(**params)
32
+ )
33
+ await connection.execute(sql_content)
@@ -1,7 +1,7 @@
1
1
  """Base classes for SQL execution strategies."""
2
2
 
3
3
  from abc import ABC, abstractmethod
4
- from typing import Any, Dict, TYPE_CHECKING
4
+ from typing import Any, Callable, Dict, TYPE_CHECKING
5
5
 
6
6
  if TYPE_CHECKING:
7
7
  from .._config import SqlTestConfig
@@ -92,6 +92,28 @@ class SqlExecutionStrategy(ABC):
92
92
  f"Install it with: pip install {self.driver_name}"
93
93
  ) from e
94
94
 
95
+ def get_cached_connection(
96
+ self,
97
+ config: "SqlTestConfig",
98
+ connect_func: Callable[..., Any],
99
+ connect_params: Dict[str, Any],
100
+ ) -> Any:
101
+ """
102
+ Get a cached connection or create a new one.
103
+
104
+ Args:
105
+ config: Database configuration
106
+ connect_func: Function to create connection
107
+ connect_params: Parameters for connect_func
108
+
109
+ Returns:
110
+ Database connection (cached or newly created)
111
+ """
112
+ from .._connection_cache import get_connection_cache
113
+
114
+ cache = get_connection_cache()
115
+ return cache.get_sync(config, connect_func, connect_params)
116
+
95
117
 
96
118
  class AsyncSqlExecutionStrategy(SqlExecutionStrategy):
97
119
  """
@@ -116,3 +138,23 @@ class AsyncSqlExecutionStrategy(SqlExecutionStrategy):
116
138
  raise RuntimeError(
117
139
  f"Strategy {self.driver_name} is async. Use execute_async() instead."
118
140
  )
141
+
142
+ async def get_cached_connection_async(
143
+ self,
144
+ config: "SqlTestConfig",
145
+ connect_coro: Any,
146
+ ) -> Any:
147
+ """
148
+ Get a cached async connection or create a new one.
149
+
150
+ Args:
151
+ config: Database configuration
152
+ connect_coro: Coroutine that creates connection
153
+
154
+ Returns:
155
+ Database connection (cached or newly created)
156
+ """
157
+ from .._connection_cache import get_connection_cache
158
+
159
+ cache = get_connection_cache()
160
+ return await cache.get_async(config, connect_coro)
@@ -26,18 +26,15 @@ class MysqlConnectorStrategy(SqlExecutionStrategy):
26
26
  """Execute SQL using mysql.connector."""
27
27
  driver = self.get_driver_module()
28
28
  params = self.build_connection_params(config)
29
-
30
- connection = driver.connect(**params)
29
+
30
+ connection = self.get_cached_connection(config, driver.connect, params)
31
+ cursor = connection.cursor()
31
32
  try:
32
- cursor = connection.cursor()
33
- try:
34
- # MySQL connector doesn't support multi-statement by default
35
- self._execute_statements(cursor, sql_content, driver)
36
- connection.commit()
37
- finally:
38
- cursor.close()
33
+ # MySQL connector doesn't support multi-statement by default
34
+ self._execute_statements(cursor, sql_content, driver)
35
+ connection.commit()
39
36
  finally:
40
- connection.close()
37
+ cursor.close()
41
38
 
42
39
  def _execute_statements(self, cursor: Any, sql_content: str, driver: Any) -> None:
43
40
  """
@@ -27,9 +27,8 @@ class PsycopgStrategy(AsyncSqlExecutionStrategy):
27
27
  driver = self.get_driver_module()
28
28
  params = self.build_connection_params(config)
29
29
 
30
- connection = await driver.AsyncConnection.connect(**params)
31
- try:
32
- await connection.execute(sql_content)
33
- await connection.commit()
34
- finally:
35
- await connection.close()
30
+ connection = await self.get_cached_connection_async(
31
+ config, driver.AsyncConnection.connect(**params)
32
+ )
33
+ await connection.execute(sql_content)
34
+ await connection.commit()
@@ -26,15 +26,12 @@ class Psycopg2Strategy(SqlExecutionStrategy):
26
26
  """Execute SQL using psycopg2."""
27
27
  driver = self.get_driver_module()
28
28
  params = self.build_connection_params(config)
29
-
30
- connection = driver.connect(**params)
29
+
30
+ connection = self.get_cached_connection(config, driver.connect, params)
31
+ cursor = connection.cursor()
31
32
  try:
32
- cursor = connection.cursor()
33
- try:
34
- # psycopg2 supports multi-statement execution
35
- cursor.execute(sql_content)
36
- connection.commit()
37
- finally:
38
- cursor.close()
33
+ # psycopg2 supports multi-statement execution
34
+ cursor.execute(sql_content)
35
+ connection.commit()
39
36
  finally:
40
- connection.close()
37
+ cursor.close()
@@ -1,6 +1,6 @@
1
1
  """Strategy for sqlite3 driver."""
2
2
 
3
- from typing import TYPE_CHECKING
3
+ from typing import Any, TYPE_CHECKING
4
4
 
5
5
  from ._base import SqlExecutionStrategy
6
6
 
@@ -22,12 +22,13 @@ class Sqlite3Strategy(SqlExecutionStrategy):
22
22
  """Execute SQL using sqlite3."""
23
23
  driver = self.get_driver_module()
24
24
  params = self.build_connection_params(config)
25
-
25
+
26
26
  database_path = params.get("database", ":memory:")
27
- connection = driver.connect(database_path)
28
- try:
29
- # SQLite supports executescript for multi-statement execution
30
- connection.executescript(sql_content)
31
- connection.commit()
32
- finally:
33
- connection.close()
27
+
28
+ def connect_sqlite() -> Any:
29
+ return driver.connect(database_path)
30
+
31
+ connection = self.get_cached_connection(config, connect_sqlite, {})
32
+ # SQLite supports executescript for multi-statement execution
33
+ connection.executescript(sql_content)
34
+ connection.commit()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fixturify
3
- Version: 0.1.9
3
+ Version: 0.1.11
4
4
  Summary: A collection of convenient testing utilities for Python
5
5
  Project-URL: Homepage, https://github.com/eleven-sea/pytools
6
6
  Project-URL: Repository, https://github.com/eleven-sea/pytools
@@ -1,4 +1,4 @@
1
- fixturify/__init__.py,sha256=bQfZ0ipbm4yuVNFRwr3sKhHY7_goNcHq9K9PYvOTQGQ,484
1
+ fixturify/__init__.py,sha256=KOtcjgkSXK30bgl49i_edSu2yUNDqWAzVubxosMBqFQ,485
2
2
  fixturify/_utils/__init__.py,sha256=Ago2DIAS0UgTvVRxWGisxPoawDFNAB5mbjnC0hYsmNw,334
3
3
  fixturify/_utils/_constants.py,sha256=CYkqgI-ljyMcntBUP8ZCQmx7JSsLqyNxzIwNfxm2XkA,453
4
4
  fixturify/_utils/_fixture_discovery.py,sha256=u9hfoNdbLz35-X7h6fwdGuQQ8edryGNWfg_ba5i8Nq8,5185
@@ -22,7 +22,7 @@ fixturify/http_d/_stubs/_httpcore.py,sha256=WR_KZGInuVqoBBRML_T6bGe5LEMjbW4ElRem
22
22
  fixturify/http_d/_stubs/_tornado.py,sha256=Vm-hETi01xGIjVVvYmVoIOXhzSWAukae48Tzmy0afFY,3219
23
23
  fixturify/json_assert/__init__.py,sha256=eDwsoGZPMDparbzKAJ2xXorVsEVPMcbHMXMfue3a3YM,375
24
24
  fixturify/json_assert/_actual_saver.py,sha256=_BXTI2CScIUJ7UeeU1-mIKssaDrHGldlFHDtq1o_i80,2355
25
- fixturify/json_assert/_assert.py,sha256=mKX2-13mS0wZomf6OjhPfK_-UEd_Hmz9UB46z-5Krsk,6068
25
+ fixturify/json_assert/_assert.py,sha256=fTpcnADwUthCPHLJX-lJiMu3gxh9yy27zJsESO9_SRs,6641
26
26
  fixturify/json_assert/_comparator.py,sha256=67YMjRmfhaksJco2mOklAvm9yUD6gzkvxV9H9yegRCk,6226
27
27
  fixturify/json_assert/_diff_formatter.py,sha256=Aiop7FFzblkCAF2uixekFbjnRQVApZhY0tVgyWJHpk4,9971
28
28
  fixturify/json_assert/_normalizer.py,sha256=DV048q_W-T7VyOmHHtxOf5aHX7xW6Rhde9ckX6O6Ygs,3081
@@ -49,23 +49,24 @@ fixturify/object_mapper/_serializers/_sqlmodel.py,sha256=66PHxMw32rACjaYgjLHSGu_
49
49
  fixturify/read_d/__init__.py,sha256=t3f3OxBenqMN-DeEifXJ6A2_jZ4XHo4tkby9XtpIoo0,130
50
50
  fixturify/read_d/_decorator.py,sha256=7uKRZ-WkGHxSNf87qlC7u-0PfiNrlZHbnQ-jWXrk5no,7700
51
51
  fixturify/read_d/_fixture_loader.py,sha256=9pXJxLOEcdLylZup41wXuok6n7bHYExPBqvFZP2Fya0,2857
52
- fixturify/sql_d/__init__.py,sha256=nqjA4Bd6h1RCq_kzSVrN2A5kuv8zHqzvYEbgBRyJhEQ,241
52
+ fixturify/sql_d/__init__.py,sha256=Y18FgZFI_z-HUAdQ6uHOppMDZC1W5hYGZhC3ZJZ5pB0,332
53
53
  fixturify/sql_d/_config.py,sha256=W3RL1UW9WrYWNHu2FqcOW22Q_loYLi9htXsqARALH6s,762
54
+ fixturify/sql_d/_connection_cache.py,sha256=5J0RLWl-6Aoyc4Ybx5FthsjeN_SA4flWgDrl6L2bODw,7172
54
55
  fixturify/sql_d/_decorator.py,sha256=9ynQlODhU5m4d29DjMQMpuMG_Fd0jikhzuMKkNDXUmA,12531
55
56
  fixturify/sql_d/_driver_registry.py,sha256=Fwxt86Gv2UbnO7V_FgzaGc1UvCzd8QV5UtHiRdahlNs,3349
56
57
  fixturify/sql_d/_executor.py,sha256=iEizcgSKrShh1CHwiVjkM1Xjs1Iiw7WESnzborAQpqY,2271
57
58
  fixturify/sql_d/_fixture_discovery.py,sha256=17m3RmJvSH8ygdZoDbkm7RIdcewe5wEyIx6X_40MxjY,1635
58
59
  fixturify/sql_d/_phase.py,sha256=zQv2YwRkXSB4Kdeqrcp5BELplWHJVgQd_0wlcjS2eqY,228
59
60
  fixturify/sql_d/_strategies/__init__.py,sha256=36IdX6pFdBgZJ1-Cn3HQfwhKgKp-bB9g4qvN3KwoncQ,323
60
- fixturify/sql_d/_strategies/_aiomysql.py,sha256=IYG1G-yQfugSLTic7bH_iPHfMMF3gaCAF8cZrjmedDk,2179
61
- fixturify/sql_d/_strategies/_aiosqlite.py,sha256=GmZA2mUtV2fJYCIroqc1ttcPC6ZzksWNQmVwC7cAUEw,916
62
- fixturify/sql_d/_strategies/_asyncpg.py,sha256=bRgTPoof4GBMhcp-0-1a2dpt4MwGb2NggewemqeShqs,945
63
- fixturify/sql_d/_strategies/_base.py,sha256=BhtbqN5tQjQzM3au_EZtWawCs1AuSbFUIsyjELrReO8,3459
64
- fixturify/sql_d/_strategies/_mysql.py,sha256=3l7aoP9FSfG-_sUofN8q9EGvSNjuavWoPU8lkPNQIsE,2452
65
- fixturify/sql_d/_strategies/_psycopg.py,sha256=3P75nMDJDwx1-JlRDnnPlCHWPXFOKI9BjEfdJChuHxA,1006
66
- fixturify/sql_d/_strategies/_psycopg2.py,sha256=aeQRpj1k1cTtOWLFnOEaQ7IcTZ-4oV_Z4p6YHsM-iyA,1105
61
+ fixturify/sql_d/_strategies/_aiomysql.py,sha256=uo0y27kfl82c9OqhWSLsx1hHN6ow0gCQLiwi5Bwi5iY,2060
62
+ fixturify/sql_d/_strategies/_aiosqlite.py,sha256=gccGZKYA17JZXG7P4o6NrgHK77BGgErz0XDKWGMAY3A,958
63
+ fixturify/sql_d/_strategies/_asyncpg.py,sha256=3TW0XW6M3jYJGfn8KeZtgLP6XC3jSi2anGVFAn5HCGA,930
64
+ fixturify/sql_d/_strategies/_base.py,sha256=4g-7-W1muTcQ5H4h3pN64m3MiuUou1wMcQeGLohg_4Y,4705
65
+ fixturify/sql_d/_strategies/_mysql.py,sha256=4MG0Pn7GWNYaakqAbFkNT3xOKKJh4DJ9JshHdbJwgts,2389
66
+ fixturify/sql_d/_strategies/_psycopg.py,sha256=8uD-mkeQKuVW9wqnfizw_FJ67MTQ80A1AP8XGvVMMIQ,995
67
+ fixturify/sql_d/_strategies/_psycopg2.py,sha256=2M0fmYtLxFxJXHsgxomaEEzPVS9u0TFs6u4ldIINy08,1042
67
68
  fixturify/sql_d/_strategies/_registry.py,sha256=ddQpp9cU4SHA2OylsPpMBMarLyQKmV-4Ge4X395tg1Q,3346
68
- fixturify/sql_d/_strategies/_sqlite.py,sha256=auW6nV1bfE8UJlk4TW5fZkcqlnr_9q6Eia5bQjE2n3w,965
69
- fixturify-0.1.9.dist-info/METADATA,sha256=XgZDuNy618fafU8vfBzc2ZNBBwE_McPpf9k461OzpiU,2978
70
- fixturify-0.1.9.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
71
- fixturify-0.1.9.dist-info/RECORD,,
69
+ fixturify/sql_d/_strategies/_sqlite.py,sha256=ZXZwdgzcMdbrE2dUMjbBJD4m1gLec5nAM6DThs108_g,1002
70
+ fixturify-0.1.11.dist-info/METADATA,sha256=4B1_WgTgeN43Lrf1RX_Q69j9mQQaN-h6lM0lCTwp2tI,2979
71
+ fixturify-0.1.11.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
72
+ fixturify-0.1.11.dist-info/RECORD,,