pytest-neon 2.2.1__py3-none-any.whl → 2.2.2__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.
- pytest_neon/__init__.py +1 -1
- pytest_neon/plugin.py +31 -36
- {pytest_neon-2.2.1.dist-info → pytest_neon-2.2.2.dist-info}/METADATA +1 -1
- pytest_neon-2.2.2.dist-info/RECORD +8 -0
- pytest_neon-2.2.1.dist-info/RECORD +0 -8
- {pytest_neon-2.2.1.dist-info → pytest_neon-2.2.2.dist-info}/WHEEL +0 -0
- {pytest_neon-2.2.1.dist-info → pytest_neon-2.2.2.dist-info}/entry_points.txt +0 -0
- {pytest_neon-2.2.1.dist-info → pytest_neon-2.2.2.dist-info}/licenses/LICENSE +0 -0
pytest_neon/__init__.py
CHANGED
pytest_neon/plugin.py
CHANGED
|
@@ -865,9 +865,11 @@ def _neon_migration_branch(
|
|
|
865
865
|
root_tmp_dir = tmp_path_factory.getbasetemp().parent
|
|
866
866
|
cache_file = root_tmp_dir / "neon_migration_branch.json"
|
|
867
867
|
lock_file = root_tmp_dir / "neon_migration_branch.lock"
|
|
868
|
+
migrations_done_file = root_tmp_dir / "neon_migrations_done"
|
|
868
869
|
else:
|
|
869
870
|
cache_file = None
|
|
870
871
|
lock_file = None
|
|
872
|
+
migrations_done_file = None
|
|
871
873
|
|
|
872
874
|
is_creator = False
|
|
873
875
|
branch: NeonBranch
|
|
@@ -876,6 +878,7 @@ def _neon_migration_branch(
|
|
|
876
878
|
|
|
877
879
|
if is_xdist:
|
|
878
880
|
assert cache_file is not None and lock_file is not None
|
|
881
|
+
assert migrations_done_file is not None
|
|
879
882
|
with FileLock(str(lock_file)):
|
|
880
883
|
if cache_file.exists():
|
|
881
884
|
# Another worker already created the branch - reuse it
|
|
@@ -916,6 +919,22 @@ def _neon_migration_branch(
|
|
|
916
919
|
}
|
|
917
920
|
)
|
|
918
921
|
)
|
|
922
|
+
|
|
923
|
+
# Non-creator workers must wait for migrations to complete BEFORE
|
|
924
|
+
# neon_apply_migrations runs, otherwise they'll try to run migrations
|
|
925
|
+
# concurrently on the same branch, causing race conditions.
|
|
926
|
+
if not is_creator:
|
|
927
|
+
waited = 0.0
|
|
928
|
+
poll_interval = 0.5
|
|
929
|
+
while not migrations_done_file.exists():
|
|
930
|
+
if waited >= _MIGRATION_WAIT_TIMEOUT:
|
|
931
|
+
raise RuntimeError(
|
|
932
|
+
f"Timeout waiting for migrations to complete after "
|
|
933
|
+
f"{_MIGRATION_WAIT_TIMEOUT}s. The creator worker may have "
|
|
934
|
+
f"failed or is still running migrations."
|
|
935
|
+
)
|
|
936
|
+
time.sleep(poll_interval)
|
|
937
|
+
waited += poll_interval
|
|
919
938
|
else:
|
|
920
939
|
# Not using xdist - create branch normally
|
|
921
940
|
is_creator = True
|
|
@@ -932,6 +951,8 @@ def _neon_migration_branch(
|
|
|
932
951
|
|
|
933
952
|
# Mark whether this worker is the creator (used by neon_apply_migrations)
|
|
934
953
|
config._neon_is_migration_creator = is_creator # type: ignore[attr-defined]
|
|
954
|
+
# Store migrations_done_file path for signaling after migrations complete
|
|
955
|
+
config._neon_migrations_done_file = migrations_done_file # type: ignore[attr-defined]
|
|
935
956
|
|
|
936
957
|
try:
|
|
937
958
|
yield branch
|
|
@@ -1007,7 +1028,6 @@ def neon_apply_migrations(_neon_migration_branch: NeonBranch) -> Any:
|
|
|
1007
1028
|
@pytest.fixture(scope="session")
|
|
1008
1029
|
def _neon_migrations_synchronized(
|
|
1009
1030
|
request: pytest.FixtureRequest,
|
|
1010
|
-
tmp_path_factory: pytest.TempPathFactory,
|
|
1011
1031
|
_neon_migration_branch: NeonBranch,
|
|
1012
1032
|
neon_apply_migrations: Any,
|
|
1013
1033
|
) -> Any:
|
|
@@ -1015,49 +1035,24 @@ def _neon_migrations_synchronized(
|
|
|
1015
1035
|
Internal fixture that synchronizes migrations across xdist workers.
|
|
1016
1036
|
|
|
1017
1037
|
This fixture ensures that:
|
|
1018
|
-
1. Only the creator worker runs migrations
|
|
1019
|
-
|
|
1038
|
+
1. Only the creator worker runs migrations (non-creators wait in
|
|
1039
|
+
_neon_migration_branch BEFORE neon_apply_migrations runs)
|
|
1040
|
+
2. Creator signals completion after migrations finish
|
|
1020
1041
|
3. The return value from neon_apply_migrations is preserved for detection
|
|
1021
1042
|
|
|
1022
1043
|
Without xdist, this is a simple passthrough.
|
|
1023
1044
|
"""
|
|
1024
1045
|
config = request.config
|
|
1025
|
-
worker_id = _get_xdist_worker_id()
|
|
1026
|
-
is_xdist = worker_id != "main"
|
|
1027
1046
|
is_creator = getattr(config, "_neon_is_migration_creator", True)
|
|
1047
|
+
migrations_done_file = getattr(config, "_neon_migrations_done_file", None)
|
|
1028
1048
|
|
|
1029
|
-
if not
|
|
1030
|
-
# Not using xdist - migrations already ran, just return the value
|
|
1031
|
-
return neon_apply_migrations
|
|
1032
|
-
|
|
1033
|
-
# For xdist, use a signal file to coordinate
|
|
1034
|
-
root_tmp_dir = tmp_path_factory.getbasetemp().parent
|
|
1035
|
-
migrations_done_file = root_tmp_dir / "neon_migrations_done"
|
|
1036
|
-
migrations_lock_file = root_tmp_dir / "neon_migrations.lock"
|
|
1037
|
-
|
|
1038
|
-
if is_creator:
|
|
1049
|
+
if is_creator and migrations_done_file is not None:
|
|
1039
1050
|
# Creator: migrations just ran via neon_apply_migrations dependency
|
|
1040
|
-
# Signal completion to other workers
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
return neon_apply_migrations
|
|
1044
|
-
else:
|
|
1045
|
-
# Non-creator: wait for migrations to complete
|
|
1046
|
-
# The neon_apply_migrations fixture still runs but on already-migrated DB
|
|
1047
|
-
# (most migration tools handle this gracefully as a no-op)
|
|
1048
|
-
waited = 0.0
|
|
1049
|
-
poll_interval = 0.5
|
|
1050
|
-
while not migrations_done_file.exists():
|
|
1051
|
-
if waited >= _MIGRATION_WAIT_TIMEOUT:
|
|
1052
|
-
raise RuntimeError(
|
|
1053
|
-
f"Timeout waiting for migrations to complete after "
|
|
1054
|
-
f"{_MIGRATION_WAIT_TIMEOUT}s. The creator worker may have "
|
|
1055
|
-
f"failed or is still running migrations."
|
|
1056
|
-
)
|
|
1057
|
-
time.sleep(poll_interval)
|
|
1058
|
-
waited += poll_interval
|
|
1051
|
+
# Signal completion to other workers (who are waiting in
|
|
1052
|
+
# _neon_migration_branch)
|
|
1053
|
+
migrations_done_file.write_text("done")
|
|
1059
1054
|
|
|
1060
|
-
|
|
1055
|
+
return neon_apply_migrations
|
|
1061
1056
|
|
|
1062
1057
|
|
|
1063
1058
|
@pytest.fixture(scope="session")
|
|
@@ -1287,7 +1282,7 @@ def neon_branch(
|
|
|
1287
1282
|
def neon_branch_shared(
|
|
1288
1283
|
request: pytest.FixtureRequest,
|
|
1289
1284
|
_neon_migration_branch: NeonBranch,
|
|
1290
|
-
|
|
1285
|
+
_neon_migrations_synchronized: Any, # Ensures migrations complete first
|
|
1291
1286
|
) -> Generator[NeonBranch, None, None]:
|
|
1292
1287
|
"""
|
|
1293
1288
|
Provide a shared Neon database branch for all tests in a module.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pytest-neon
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: Pytest plugin for Neon database branch isolation in tests
|
|
5
5
|
Project-URL: Homepage, https://github.com/ZainRizvi/pytest-neon
|
|
6
6
|
Project-URL: Repository, https://github.com/ZainRizvi/pytest-neon
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
pytest_neon/__init__.py,sha256=NYxWUqqq-U4rhtxH4fhgZ7F4-vaxQ51oYKhuMFGhTes,398
|
|
2
|
+
pytest_neon/plugin.py,sha256=8TciFbqE7mH86URTxSxw4sU8yqth17Mkrt2XOo0DZ-c,56023
|
|
3
|
+
pytest_neon/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
pytest_neon-2.2.2.dist-info/METADATA,sha256=Ga8VA-3kMmdhEj-oAer-qnOXkmZgC7GiBygh5HysiR4,19266
|
|
5
|
+
pytest_neon-2.2.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
6
|
+
pytest_neon-2.2.2.dist-info/entry_points.txt,sha256=5U88Idj_G8-PSDb9VF3OwYFbGLHnGOo_GxgYvi0dtXw,37
|
|
7
|
+
pytest_neon-2.2.2.dist-info/licenses/LICENSE,sha256=aKKp_Ex4WBHTByY4BhXJ181dzB_qYhi2pCUmZ7Spn_0,1067
|
|
8
|
+
pytest_neon-2.2.2.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
pytest_neon/__init__.py,sha256=MShSVrrcshqn0Gk9s9zc4iMopsVfqCbDyKYJhOa5QYE,398
|
|
2
|
-
pytest_neon/plugin.py,sha256=kpfRodNlIY_6a11UbvtF-S0KFjaPHPPo-K3kiaEAGsA,55952
|
|
3
|
-
pytest_neon/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
pytest_neon-2.2.1.dist-info/METADATA,sha256=NZEC6cCKDZ00UyyAjVQdyawyTjZ1MKL8oboOsw5ao0M,19266
|
|
5
|
-
pytest_neon-2.2.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
6
|
-
pytest_neon-2.2.1.dist-info/entry_points.txt,sha256=5U88Idj_G8-PSDb9VF3OwYFbGLHnGOo_GxgYvi0dtXw,37
|
|
7
|
-
pytest_neon-2.2.1.dist-info/licenses/LICENSE,sha256=aKKp_Ex4WBHTByY4BhXJ181dzB_qYhi2pCUmZ7Spn_0,1067
|
|
8
|
-
pytest_neon-2.2.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|