fixtureqa 0.4.13__tar.gz → 0.4.15__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.
Files changed (99) hide show
  1. {fixtureqa-0.4.13/fixtureqa.egg-info → fixtureqa-0.4.15}/PKG-INFO +2 -2
  2. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/session.py +19 -8
  3. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/session_manager.py +19 -1
  4. fixtureqa-0.4.13/fixture/static/assets/index-DHd_iEnT.js → fixtureqa-0.4.15/fixture/static/assets/index-BVKx6Ai2.js +14 -14
  5. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/static/index.html +1 -1
  6. {fixtureqa-0.4.13 → fixtureqa-0.4.15/fixtureqa.egg-info}/PKG-INFO +2 -2
  7. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixtureqa.egg-info/SOURCES.txt +1 -1
  8. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixtureqa.egg-info/requires.txt +1 -1
  9. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/pyproject.toml +2 -2
  10. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_sessions.py +40 -0
  11. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/LICENSE +0 -0
  12. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/README.md +0 -0
  13. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/__init__.py +0 -0
  14. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/__main__.py +0 -0
  15. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/__init__.py +0 -0
  16. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/app.py +0 -0
  17. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/connection_manager.py +0 -0
  18. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/deps.py +0 -0
  19. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/routers/__init__.py +0 -0
  20. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/routers/admin.py +0 -0
  21. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/routers/auth.py +0 -0
  22. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/routers/branding.py +0 -0
  23. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/routers/custom_tags.py +0 -0
  24. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/routers/fix_spec.py +0 -0
  25. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/routers/messages.py +0 -0
  26. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/routers/perf.py +0 -0
  27. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/routers/scenarios.py +0 -0
  28. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/routers/sessions.py +0 -0
  29. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/routers/setup.py +0 -0
  30. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/routers/spec_overlay.py +0 -0
  31. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/routers/templates.py +0 -0
  32. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/routers/ws.py +0 -0
  33. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/api/schemas.py +0 -0
  34. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/config/__init__.py +0 -0
  35. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/__init__.py +0 -0
  36. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/atomic_io.py +0 -0
  37. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/auth.py +0 -0
  38. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/config_store.py +0 -0
  39. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/custom_tag_store.py +0 -0
  40. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/db_migrations.py +0 -0
  41. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/events.py +0 -0
  42. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/exec_csv_writer.py +0 -0
  43. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/fix_application.py +0 -0
  44. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/fix_builder.py +0 -0
  45. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/fix_parser.py +0 -0
  46. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/fix_spec_parser.py +0 -0
  47. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/fix_tags.py +0 -0
  48. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/fix_time.py +0 -0
  49. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/housekeeping.py +0 -0
  50. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/inbound.py +0 -0
  51. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/json_store.py +0 -0
  52. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/message_log.py +0 -0
  53. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/message_store.py +0 -0
  54. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/models.py +0 -0
  55. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/perf_engine.py +0 -0
  56. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/perf_models.py +0 -0
  57. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/perf_payload.py +0 -0
  58. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/perf_stats.py +0 -0
  59. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/perf_store.py +0 -0
  60. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/perf_writer.py +0 -0
  61. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/scenario_runner.py +0 -0
  62. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/scenario_store.py +0 -0
  63. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/spec_overlay_store.py +0 -0
  64. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/template_store.py +0 -0
  65. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/user_store.py +0 -0
  66. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/core/venue_responses.py +0 -0
  67. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/fix_specs/FIX42.xml +0 -0
  68. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/fix_specs/FIX44.xml +0 -0
  69. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/server.py +0 -0
  70. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/static/assets/ag-grid-_QKprVdm.js +0 -0
  71. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/static/assets/index-BwQf-cei.css +0 -0
  72. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/static/assets/index-CyNOPa0n.js +0 -0
  73. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/static/assets/react-vendor-2eF0YfZT.js +0 -0
  74. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/static/favicon.svg +0 -0
  75. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixture/ui/__init__.py +0 -0
  76. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixtureqa.egg-info/dependency_links.txt +0 -0
  77. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixtureqa.egg-info/entry_points.txt +0 -0
  78. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/fixtureqa.egg-info/top_level.txt +0 -0
  79. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/setup.cfg +0 -0
  80. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_atomic_io.py +0 -0
  81. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_auth.py +0 -0
  82. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_config_store.py +0 -0
  83. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_connection_manager.py +0 -0
  84. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_db_migrations.py +0 -0
  85. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_fix_builder.py +0 -0
  86. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_health.py +0 -0
  87. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_inbound.py +0 -0
  88. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_inbound_validation.py +0 -0
  89. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_message_store.py +0 -0
  90. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_perf_api.py +0 -0
  91. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_perf_engine.py +0 -0
  92. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_perf_models.py +0 -0
  93. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_perf_payload.py +0 -0
  94. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_perf_rehydrate.py +0 -0
  95. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_scenarios.py +0 -0
  96. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_session_lifecycle.py +0 -0
  97. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_session_manager_concurrency.py +0 -0
  98. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_templates.py +0 -0
  99. {fixtureqa-0.4.13 → fixtureqa-0.4.15}/tests/test_ws.py +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fixtureqa
3
- Version: 0.4.13
3
+ Version: 0.4.15
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.6.0
7
+ Requires-Dist: fixcore-engine==0.6.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
@@ -51,14 +51,8 @@ class Session:
51
51
  def __init__(self, config: SessionConfig, event_handler: EventHandler,
52
52
  msg_writer: Optional["MessageWriter"] = None):
53
53
  self.config = config
54
- if msg_writer is not None and config.log_messages:
55
- from .message_store import MessageStore
56
- self._message_log = MessageStore(config.session_id, msg_writer)
57
- else:
58
- # No persistent writer, or logging disabled for this session
59
- # (high-rate/perf): in-memory log only, no per-message SQLite churn.
60
- from .message_log import MessageLog
61
- self._message_log = MessageLog()
54
+ self._msg_writer = msg_writer
55
+ self._message_log = self._pick_message_log()
62
56
  self.state = SessionState(config=config, message_log=self._message_log)
63
57
  self._event_handler = event_handler
64
58
  self._transport: Optional[SocketInitiator | SocketAcceptor] = None
@@ -69,6 +63,23 @@ class Session:
69
63
  # and the ack/fill silently never sent.
70
64
  self._venue_tasks: set[asyncio.Task] = set()
71
65
 
66
+ def _pick_message_log(self):
67
+ if self._msg_writer is not None and self.config.log_messages:
68
+ from .message_store import MessageStore
69
+ return MessageStore(self.config.session_id, self._msg_writer)
70
+ # No persistent writer, or logging disabled for this session
71
+ # (high-rate/perf): in-memory log only, no per-message SQLite churn.
72
+ from .message_log import MessageLog
73
+ return MessageLog()
74
+
75
+ def rebind_message_log(self) -> None:
76
+ """Re-run the log-backend choice after config.log_messages changed
77
+ (standard <-> perf conversion on a stopped session). Switching to the
78
+ persistent store re-exposes the session's messages.db history; the
79
+ in-memory ring from perf mode is not carried over."""
80
+ self._message_log = self._pick_message_log()
81
+ self.state.message_log = self._message_log
82
+
72
83
  # ------------------------------------------------------------------
73
84
  # Public API
74
85
  # ------------------------------------------------------------------
@@ -1,5 +1,7 @@
1
1
  import copy
2
2
  import logging
3
+ import os
4
+ import shutil
3
5
  import threading
4
6
  from typing import Dict, List, Optional, Set
5
7
  from .models import SessionConfig, SessionState, SessionStatus
@@ -73,7 +75,15 @@ class SessionManager:
73
75
  await self._get(session_id).stop(force=force)
74
76
 
75
77
  def update_session(self, session_id: str, req) -> SessionConfig:
76
- """Update config fields on a stopped session."""
78
+ """Update config fields on a stopped session.
79
+
80
+ Standard <-> perf conversion happens here too: `durable_seqnums` and
81
+ the engine-side logging are start-time decisions and need nothing,
82
+ but flipping `log_messages` rebinds the message-log backend
83
+ (SQLite-backed store vs in-memory ring), and flipping
84
+ `durable_seqnums` clears the session's file store so the next start
85
+ gets clean seqnums instead of resuming from a stale file.
86
+ """
77
87
  from .models import ConnectionType, SessionRole
78
88
  session = self._get(session_id)
79
89
  with self._lock:
@@ -92,9 +102,17 @@ class SessionManager:
92
102
  for key, value in updates.items():
93
103
  setattr(candidate, key, value)
94
104
  self._validate_config(candidate, exclude_id=session_id)
105
+ old_log_messages = cfg.log_messages
106
+ old_durable = cfg.durable_seqnums
95
107
  for key, value in updates.items():
96
108
  setattr(cfg, key, value)
109
+ if cfg.log_messages != old_log_messages:
110
+ session.rebind_message_log()
97
111
  self._persist() # disk I/O — outside the lock
112
+ if cfg.durable_seqnums != old_durable:
113
+ store_path = os.path.abspath(
114
+ os.path.join(cfg.file_store_path, session_id))
115
+ shutil.rmtree(store_path, ignore_errors=True)
98
116
  return cfg
99
117
 
100
118
  async def remove_session(self, session_id: str) -> None: