fixtureqa 0.8.1__tar.gz → 0.8.3__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.
- {fixtureqa-0.8.1/fixtureqa.egg-info → fixtureqa-0.8.3}/PKG-INFO +2 -3
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/routers/sessions.py +11 -1
- {fixtureqa-0.8.1 → fixtureqa-0.8.3/fixtureqa.egg-info}/PKG-INFO +2 -3
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixtureqa.egg-info/requires.txt +1 -2
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/pyproject.toml +4 -7
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_sessions.py +17 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/LICENSE +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/README.md +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/__init__.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/__main__.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/__init__.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/app.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/connection_manager.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/deps.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/routers/__init__.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/routers/admin.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/routers/auth.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/routers/branding.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/routers/custom_tags.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/routers/fix_spec.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/routers/messages.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/routers/perf.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/routers/scenarios.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/routers/setup.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/routers/spec_overlay.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/routers/templates.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/routers/ws.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/api/schemas.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/config/__init__.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/__init__.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/atomic_io.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/auth.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/config_store.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/custom_tag_store.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/db_migrations.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/events.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/fix_application.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/fix_builder.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/fix_parser.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/fix_spec_parser.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/fix_tags.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/fix_time.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/housekeeping.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/inbound.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/json_store.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/latency_csv_writer.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/message_log.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/message_store.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/models.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/perf_charts.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/perf_engine.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/perf_models.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/perf_payload.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/perf_stats.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/perf_store.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/perf_writer.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/scenario_runner.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/scenario_store.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/session.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/session_manager.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/spec_overlay_store.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/template_store.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/user_store.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/value_gen.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/core/venue_responses.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/fix_specs/FIX42.xml +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/fix_specs/FIX44.xml +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/server.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/static/assets/ag-grid-_QKprVdm.js +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/static/assets/index-B-hpSZWZ.css +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/static/assets/index-Cu3H3T9B.js +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/static/assets/index-CyNOPa0n.js +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/static/assets/react-vendor-2eF0YfZT.js +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/static/favicon.svg +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/static/index.html +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixture/ui/__init__.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixtureqa.egg-info/SOURCES.txt +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixtureqa.egg-info/dependency_links.txt +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixtureqa.egg-info/entry_points.txt +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/fixtureqa.egg-info/top_level.txt +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/setup.cfg +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_atomic_io.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_auth.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_config_store.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_connection_manager.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_db_migrations.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_fix_builder.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_health.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_inbound.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_inbound_validation.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_message_store.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_non_stop_session.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_perf_api.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_perf_engine.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_perf_models.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_perf_payload.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_perf_rehydrate.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_scenarios.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_session_auto_response.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_session_lifecycle.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_session_manager_concurrency.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_templates.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_timezone_data.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_value_gen.py +0 -0
- {fixtureqa-0.8.1 → fixtureqa-0.8.3}/tests/test_ws.py +0 -0
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fixtureqa
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.3
|
|
4
4
|
Summary: FIXture — FIX Protocol Testing Tool
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
License-File: LICENSE
|
|
7
|
-
Requires-Dist: fixcore-engine==0.7.
|
|
7
|
+
Requires-Dist: fixcore-engine==0.7.1
|
|
8
8
|
Requires-Dist: fastapi>=0.111.0
|
|
9
9
|
Requires-Dist: uvicorn[standard]>=0.29.0
|
|
10
10
|
Requires-Dist: websockets>=12.0
|
|
11
11
|
Requires-Dist: python-jose[cryptography]>=3.3.0
|
|
12
12
|
Requires-Dist: passlib[bcrypt]>=1.7.4
|
|
13
13
|
Requires-Dist: matplotlib>=3.7
|
|
14
|
-
Requires-Dist: tzdata>=2024.1
|
|
15
14
|
Provides-Extra: dev
|
|
16
15
|
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
17
16
|
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
@@ -127,7 +127,17 @@ async def create_session(body: SessionConfigRequest, sm: SM, us: US, user: Curre
|
|
|
127
127
|
try:
|
|
128
128
|
await sm.start_session(session_id)
|
|
129
129
|
except Exception as e:
|
|
130
|
-
|
|
130
|
+
# Creation is atomic: roll back the just-added session so a failed
|
|
131
|
+
# auto-start doesn't leave an orphan persisted. (Pre-0.8.2 a missing
|
|
132
|
+
# tzdata raised a TimeZone error here while the session stayed
|
|
133
|
+
# registered; the UI surfaced a failure, users retried, and the
|
|
134
|
+
# orphans piled up as duplicates.) The config is reported in the
|
|
135
|
+
# error so the user can fix and re-add.
|
|
136
|
+
try:
|
|
137
|
+
await sm.remove_session(session_id)
|
|
138
|
+
except Exception:
|
|
139
|
+
pass # best-effort rollback; surface the original start failure
|
|
140
|
+
raise HTTPException(status_code=500, detail=f"Failed to start session: {e}")
|
|
131
141
|
|
|
132
142
|
return _session_response(sm, session_id, _owner_store(us, user))
|
|
133
143
|
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fixtureqa
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.3
|
|
4
4
|
Summary: FIXture — FIX Protocol Testing Tool
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
License-File: LICENSE
|
|
7
|
-
Requires-Dist: fixcore-engine==0.7.
|
|
7
|
+
Requires-Dist: fixcore-engine==0.7.1
|
|
8
8
|
Requires-Dist: fastapi>=0.111.0
|
|
9
9
|
Requires-Dist: uvicorn[standard]>=0.29.0
|
|
10
10
|
Requires-Dist: websockets>=12.0
|
|
11
11
|
Requires-Dist: python-jose[cryptography]>=3.3.0
|
|
12
12
|
Requires-Dist: passlib[bcrypt]>=1.7.4
|
|
13
13
|
Requires-Dist: matplotlib>=3.7
|
|
14
|
-
Requires-Dist: tzdata>=2024.1
|
|
15
14
|
Provides-Extra: dev
|
|
16
15
|
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
17
16
|
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
@@ -4,22 +4,19 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "fixtureqa"
|
|
7
|
-
version = "0.8.
|
|
7
|
+
version = "0.8.3"
|
|
8
8
|
description = "FIXture — FIX Protocol Testing Tool"
|
|
9
9
|
requires-python = ">=3.10"
|
|
10
10
|
dependencies = [
|
|
11
|
-
|
|
11
|
+
# 0.7.1 owns the tzdata dependency (zoneinfo for the TimeZone schedule key),
|
|
12
|
+
# so it's no longer declared here — fixcore is the only code using ZoneInfo.
|
|
13
|
+
"fixcore-engine==0.7.1",
|
|
12
14
|
"fastapi>=0.111.0",
|
|
13
15
|
"uvicorn[standard]>=0.29.0",
|
|
14
16
|
"websockets>=12.0",
|
|
15
17
|
"python-jose[cryptography]>=3.3.0",
|
|
16
18
|
"passlib[bcrypt]>=1.7.4",
|
|
17
19
|
"matplotlib>=3.7",
|
|
18
|
-
# IANA tz database for stdlib zoneinfo. fixcore 0.7.0 builds a session
|
|
19
|
-
# schedule (and resolves SessionConfig.time_zone via ZoneInfo) for every
|
|
20
|
-
# session, but slim/alpine base images ship no system /usr/share/zoneinfo,
|
|
21
|
-
# so without this any zone lookup — including the default UTC — fails.
|
|
22
|
-
"tzdata>=2024.1",
|
|
23
20
|
]
|
|
24
21
|
|
|
25
22
|
[project.optional-dependencies]
|
|
@@ -53,6 +53,23 @@ def test_create_session(authed):
|
|
|
53
53
|
assert "session_id" in body
|
|
54
54
|
|
|
55
55
|
|
|
56
|
+
def test_failed_autostart_rolls_back(authed):
|
|
57
|
+
"""A failed auto-start must not leave an orphan persisted session.
|
|
58
|
+
|
|
59
|
+
Regression: pre-0.8.2 a missing tzdata raised a TimeZone error while the
|
|
60
|
+
session stayed registered; retries piled up duplicates. An invalid TimeZone
|
|
61
|
+
passes config validation (we don't pre-check the zone) but fails when the
|
|
62
|
+
engine builds the schedule on start — so it exercises the rollback path.
|
|
63
|
+
"""
|
|
64
|
+
client, _ = authed
|
|
65
|
+
cfg = _ini(9876)
|
|
66
|
+
cfg["auto_start"] = True
|
|
67
|
+
cfg["time_zone"] = "Not/AZone" # invalid IANA zone -> schedule build fails on start
|
|
68
|
+
resp = client.post("/api/sessions/", json=cfg)
|
|
69
|
+
assert resp.status_code == 500
|
|
70
|
+
assert client.get("/api/sessions/").json() == [] # rolled back — no orphan
|
|
71
|
+
|
|
72
|
+
|
|
56
73
|
def _wait_persisted(sm, sid: str, n: int, timeout: float = 5.0) -> None:
|
|
57
74
|
from fixture.core.message_store import MessageStore
|
|
58
75
|
store = MessageStore(sid, sm.message_writer)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|