stemtrace 0.3.9__tar.gz → 0.3.10__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 (175) hide show
  1. {stemtrace-0.3.9 → stemtrace-0.3.10}/.bumpversion.toml +3 -3
  2. stemtrace-0.3.10/.coderabbit.yaml +92 -0
  3. {stemtrace-0.3.9 → stemtrace-0.3.10}/.dockerignore +1 -0
  4. {stemtrace-0.3.9 → stemtrace-0.3.10}/.github/workflows/ci.yml +10 -0
  5. {stemtrace-0.3.9 → stemtrace-0.3.10}/.github/workflows/release.yml +7 -1
  6. {stemtrace-0.3.9 → stemtrace-0.3.10}/.gitignore +1 -0
  7. {stemtrace-0.3.9 → stemtrace-0.3.10}/.pre-commit-config.yaml +6 -0
  8. {stemtrace-0.3.9 → stemtrace-0.3.10}/CHANGELOG.md +12 -1
  9. {stemtrace-0.3.9 → stemtrace-0.3.10}/CONTRIBUTING.md +36 -3
  10. {stemtrace-0.3.9 → stemtrace-0.3.10}/Dockerfile +3 -1
  11. {stemtrace-0.3.9 → stemtrace-0.3.10}/Makefile +2 -1
  12. {stemtrace-0.3.9 → stemtrace-0.3.10}/PKG-INFO +3 -2
  13. {stemtrace-0.3.9 → stemtrace-0.3.10}/README.md +1 -1
  14. {stemtrace-0.3.9 → stemtrace-0.3.10}/pyproject.toml +78 -1
  15. {stemtrace-0.3.9 → stemtrace-0.3.10}/scripts/wait_for_http.py +0 -1
  16. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/__init__.py +2 -2
  17. stemtrace-0.3.10/src/stemtrace/_version.py +8 -0
  18. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/core/graph.py +278 -264
  19. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/library/output_capture.py +1 -1
  20. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/library/scrubbing.py +3 -4
  21. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/library/signals.py +9 -0
  22. stemtrace-0.3.10/src/stemtrace/library/transports/__init__.py +24 -0
  23. stemtrace-0.3.10/src/stemtrace/library/transports/breaker.py +5 -0
  24. stemtrace-0.3.10/src/stemtrace/library/transports/memory.py +5 -0
  25. stemtrace-0.3.10/src/stemtrace/library/transports/rabbitmq.py +29 -0
  26. stemtrace-0.3.10/src/stemtrace/library/transports/redis.py +23 -0
  27. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/__main__.py +2 -1
  28. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/api/routes.py +215 -125
  29. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/consumer.py +30 -12
  30. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/fastapi/form_auth.py +28 -10
  31. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/fastapi/form_auth_middleware.py +54 -21
  32. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/fastapi/router.py +4 -4
  33. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/package-lock.json +2 -2
  34. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/package.json +1 -1
  35. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/playwright.config.ts +9 -6
  36. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/hooks/WebSocketContext.tsx +12 -2
  37. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/tests/header.spec.ts +50 -1
  38. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/tests/task-detail.spec.ts +101 -97
  39. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/static.py +1 -1
  40. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/websocket.py +1 -1
  41. {stemtrace-0.3.9/src/stemtrace/library → stemtrace-0.3.10/src/stemtrace}/transports/__init__.py +12 -8
  42. {stemtrace-0.3.9/src/stemtrace/library → stemtrace-0.3.10/src/stemtrace}/transports/rabbitmq.py +139 -96
  43. {stemtrace-0.3.9/src/stemtrace/library → stemtrace-0.3.10/src/stemtrace}/transports/redis.py +119 -63
  44. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/e2e/test_api_e2e.py +1 -2
  45. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/integration/test_rabbitmq_publish.py +9 -5
  46. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/integration/test_rabbitmq_transport.py +18 -19
  47. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/integration/test_redis_resilience_docker.py +1 -1
  48. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/integration/test_redis_transport.py +3 -3
  49. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/integration/test_static_ui.py +29 -0
  50. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/integration/test_workers_refresh.py +1 -1
  51. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_consumer.py +95 -1
  52. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_form_auth.py +68 -2
  53. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_form_login.py +18 -1
  54. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_graph.py +398 -0
  55. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_init.py +2 -4
  56. stemtrace-0.3.10/tests/unit/test_library_transports_alias.py +77 -0
  57. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_publish_breaker.py +1 -1
  58. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_rabbitmq_publish.py +158 -146
  59. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_redis_resilience.py +91 -1
  60. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_routes.py +32 -3
  61. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_signals.py +90 -2
  62. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_signals_output.py +1 -1
  63. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_store.py +1 -1
  64. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_transports.py +112 -61
  65. {stemtrace-0.3.9 → stemtrace-0.3.10}/uv.lock +139 -2
  66. {stemtrace-0.3.9 → stemtrace-0.3.10}/.github/dependabot.yml +0 -0
  67. {stemtrace-0.3.9 → stemtrace-0.3.10}/.github/workflows/e2e.yml +0 -0
  68. {stemtrace-0.3.9 → stemtrace-0.3.10}/.python-version +0 -0
  69. {stemtrace-0.3.9 → stemtrace-0.3.10}/Dockerfile.e2e +0 -0
  70. {stemtrace-0.3.9 → stemtrace-0.3.10}/LICENSE +0 -0
  71. {stemtrace-0.3.9 → stemtrace-0.3.10}/build_ui.py +0 -0
  72. {stemtrace-0.3.9 → stemtrace-0.3.10}/docker-compose.e2e.rabbitmq.yml +0 -0
  73. {stemtrace-0.3.9 → stemtrace-0.3.10}/docker-compose.e2e.yml +0 -0
  74. {stemtrace-0.3.9 → stemtrace-0.3.10}/docker-compose.rabbitmq.yml +0 -0
  75. {stemtrace-0.3.9 → stemtrace-0.3.10}/docker-compose.yml +0 -0
  76. {stemtrace-0.3.9 → stemtrace-0.3.10}/docs/brand/stemtrace-mark-light.svg +0 -0
  77. {stemtrace-0.3.9 → stemtrace-0.3.10}/docs/brand/stemtrace-mark.svg +0 -0
  78. {stemtrace-0.3.9 → stemtrace-0.3.10}/docs/screenshots/task_details.png +0 -0
  79. {stemtrace-0.3.9 → stemtrace-0.3.10}/docs/screenshots/unregistered.png +0 -0
  80. {stemtrace-0.3.9 → stemtrace-0.3.10}/docs/screenshots/workflow.png +0 -0
  81. {stemtrace-0.3.9 → stemtrace-0.3.10}/examples/celery_app.py +0 -0
  82. {stemtrace-0.3.9 → stemtrace-0.3.10}/examples/fastapi_integration.py +0 -0
  83. {stemtrace-0.3.9 → stemtrace-0.3.10}/examples/with_auth.py +0 -0
  84. {stemtrace-0.3.9 → stemtrace-0.3.10}/examples/with_login.py +0 -0
  85. {stemtrace-0.3.9 → stemtrace-0.3.10}/progress.md +0 -0
  86. {stemtrace-0.3.9 → stemtrace-0.3.10}/scripts/changelog_section.py +0 -0
  87. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/core/__init__.py +0 -0
  88. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/core/events.py +0 -0
  89. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/core/exceptions.py +0 -0
  90. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/core/ports.py +0 -0
  91. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/library/__init__.py +0 -0
  92. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/library/bootsteps.py +0 -0
  93. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/library/config.py +0 -0
  94. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/py.typed +0 -0
  95. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/__init__.py +0 -0
  96. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/api/__init__.py +0 -0
  97. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/api/schemas.py +0 -0
  98. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/api/websocket.py +0 -0
  99. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/fastapi/__init__.py +0 -0
  100. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/fastapi/auth.py +0 -0
  101. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/fastapi/extension.py +0 -0
  102. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/fastapi/login_routes.py +0 -0
  103. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/store.py +0 -0
  104. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/__init__.py +0 -0
  105. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/biome.json +0 -0
  106. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/index.html +0 -0
  107. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/postcss.config.js +0 -0
  108. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/api/client.ts +0 -0
  109. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/api/queries.ts +0 -0
  110. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/components/DateRangePicker.tsx +0 -0
  111. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/components/Filters.tsx +0 -0
  112. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/components/LogoutButton.tsx +0 -0
  113. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/components/SessionRejectedNotice.tsx +0 -0
  114. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/components/SproutMark.tsx +0 -0
  115. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/components/TaskGraph.tsx +0 -0
  116. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/components/TaskList.tsx +0 -0
  117. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/components/TaskOutput.tsx +0 -0
  118. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/components/TaskStateBadge.tsx +0 -0
  119. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/components/TaskTimeline.tsx +0 -0
  120. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/components/TimelineBar.tsx +0 -0
  121. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/components/Tooltip.tsx +0 -0
  122. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/hooks/useInfiniteScroll.ts +0 -0
  123. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/index.css +0 -0
  124. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/main.tsx +0 -0
  125. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/routes/__root.tsx +0 -0
  126. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/routes/graph.$rootId.tsx +0 -0
  127. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/routes/graphs.tsx +0 -0
  128. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/routes/index.tsx +0 -0
  129. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/routes/registry.tsx +0 -0
  130. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/routes/tasks.$taskId.tsx +0 -0
  131. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/routes/workers.tsx +0 -0
  132. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/utils/format.ts +0 -0
  133. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/src/vite-env.d.ts +0 -0
  134. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/tests/auth.spec.ts +0 -0
  135. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/tests/fixtures/mock-api.ts +0 -0
  136. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/tests/fixtures/mock-data.ts +0 -0
  137. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/tests/graphs.spec.ts +0 -0
  138. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/tests/registry.spec.ts +0 -0
  139. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/tests/tasks.spec.ts +0 -0
  140. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/tests/workers.spec.ts +0 -0
  141. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/tsconfig.json +0 -0
  142. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/tsconfig.tsbuildinfo +0 -0
  143. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/frontend/vite.config.ts +0 -0
  144. {stemtrace-0.3.9 → stemtrace-0.3.10}/src/stemtrace/server/ui/templates/login.html +0 -0
  145. {stemtrace-0.3.9/src/stemtrace/library → stemtrace-0.3.10/src/stemtrace}/transports/breaker.py +0 -0
  146. {stemtrace-0.3.9/src/stemtrace/library → stemtrace-0.3.10/src/stemtrace}/transports/memory.py +0 -0
  147. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/__init__.py +0 -0
  148. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/conftest.py +0 -0
  149. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/e2e/__init__.py +0 -0
  150. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/e2e/conftest.py +0 -0
  151. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/e2e/tasks.py +0 -0
  152. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/e2e/test_workers_e2e.py +0 -0
  153. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/integration/__init__.py +0 -0
  154. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/integration/output_worker_app.py +0 -0
  155. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/integration/test_embedded_static.py +0 -0
  156. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/integration/test_fastapi_integration.py +0 -0
  157. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/integration/test_output_capture_worker.py +0 -0
  158. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/integration/test_wait_for_http_redirects.py +0 -0
  159. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/__init__.py +0 -0
  160. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_auth.py +0 -0
  161. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_bootsteps.py +0 -0
  162. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_build_ui_hook.py +0 -0
  163. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_changelog_section_script.py +0 -0
  164. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_cli.py +0 -0
  165. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_cli_form_login.py +0 -0
  166. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_config.py +0 -0
  167. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_events.py +0 -0
  168. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_examples.py +0 -0
  169. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_exceptions.py +0 -0
  170. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_favicon.py +0 -0
  171. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_output_capture.py +0 -0
  172. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_scrubbing.py +0 -0
  173. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_ui_static_prefix.py +0 -0
  174. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_wait_for_http_script.py +0 -0
  175. {stemtrace-0.3.9 → stemtrace-0.3.10}/tests/unit/test_websocket.py +0 -0
@@ -1,5 +1,5 @@
1
1
  [tool.bumpversion]
2
- current_version = "0.3.9"
2
+ current_version = "0.3.10"
3
3
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
4
4
  serialize = ["{major}.{minor}.{patch}"]
5
5
  commit = true
@@ -12,9 +12,9 @@ filename = "pyproject.toml"
12
12
  search = 'version = "{current_version}"'
13
13
  replace = 'version = "{new_version}"'
14
14
 
15
- # Python __version__ in package __init__.py
15
+ # Python __version__ (leaf module, re-exported by the package __init__.py)
16
16
  [[tool.bumpversion.files]]
17
- filename = "src/stemtrace/__init__.py"
17
+ filename = "src/stemtrace/_version.py"
18
18
  search = '__version__ = "{current_version}"'
19
19
  replace = '__version__ = "{new_version}"'
20
20
 
@@ -0,0 +1,92 @@
1
+ # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
2
+ # CodeRabbit review settings. The rules behind these instructions are summarized
3
+ # in CONTRIBUTING.md; ruff, mypy and import-linter already run in CI, so reviews
4
+ # should focus on what tools can't check.
5
+ language: en-US
6
+ tone_instructions: >-
7
+ Be concise and specific. Skip praise and style nits that ruff or Biome already
8
+ enforce. Lead with correctness, boundaries and test gaps.
9
+
10
+ reviews:
11
+ profile: chill
12
+ high_level_summary: true
13
+ poem: false
14
+ in_progress_fortune: false
15
+ sequence_diagrams: false
16
+ collapse_walkthrough: true
17
+ path_filters:
18
+ - "!uv.lock"
19
+ - "!**/package-lock.json"
20
+ - "!src/stemtrace/server/ui/frontend/src/routeTree.gen.ts"
21
+ - "!src/stemtrace/server/ui/frontend/dist/**"
22
+ # Most specific paths first, the general Python entry last. The server and
23
+ # general globs match only *.py, so frontend files get just the frontend entry.
24
+ path_instructions:
25
+ - path: "src/stemtrace/core/**"
26
+ instructions: |
27
+ Domain layer: pure Python plus Pydantic only. Flag any I/O (network, files,
28
+ environment, clocks used for side effects) and any import of
29
+ stemtrace.library, stemtrace.server, Celery, Redis, kombu or FastAPI.
30
+ Events are immutable (frozen=True). Synthetic GROUP/CHORD nodes have
31
+ empty `events`; new graph code must handle that.
32
+ - path: "src/stemtrace/library/**"
33
+ instructions: |
34
+ Runs inside Celery workers. Imports core only, never stemtrace.server.
35
+ Publishing is fire-and-forget: it must never raise into or block a task,
36
+ and a failing broker must stay cheap on repeated events (circuit breaker
37
+ or backoff, never retry per event). Log volume must stay bounded during
38
+ an outage. Check shared state under prefork, threads and gevent/eventlet,
39
+ and fork safety of module-level locks. Per-task state belongs in a
40
+ ContextVar.
41
+ - path: "src/stemtrace/server/ui/frontend/**"
42
+ instructions: |
43
+ React 19 + TypeScript strict + TanStack Router/Query + @xyflow/react.
44
+ No `any`, explicit return types on exported functions, props interfaces
45
+ for components. routeTree.gen.ts is generated and must not be edited by
46
+ hand. Graph or UI behavior changes need Playwright coverage in tests/.
47
+ - path: "src/stemtrace/server/**/*.py"
48
+ instructions: |
49
+ Web server and consumer. Imports core only, never stemtrace.library. The
50
+ server is read-only toward the broker and the user's Celery app. Check
51
+ that API response schema changes are reflected in the frontend types and
52
+ tests, that auth dependencies apply to new routes, and that background
53
+ loops stop within a bounded time.
54
+ - path: "pyproject.toml"
55
+ instructions: |
56
+ Flag any new per-file-ignores entry for the design rules (C90, PLR09xx,
57
+ BLE, ERA, RET, PT) and any added import-linter ignore_imports entry:
58
+ the baseline only shrinks. New dependencies need a stated reason.
59
+ - path: "tests/**"
60
+ instructions: |
61
+ - A new test should fail on the old code with an assertion error that is
62
+ the bug, not an ImportError.
63
+ - Assert exact values, sequences and log counts, not `is not None`.
64
+ - Prefer fakes that model the real library semantics over
65
+ unittest.mock; a fake that always succeeds proves nothing.
66
+ - No real sleeps in unit tests: inject the clock and sleep function, and
67
+ bound loops so a regression fails instead of hanging.
68
+ - New `# noqa` comments need a reason after the codes; bare ones are
69
+ the pre-existing baseline and only shrink.
70
+ - Imports at the top of the file. Names follow
71
+ test_<action>_<condition>_<result>. Tests needing Redis or RabbitMQ
72
+ are marked integration; Docker-based ones e2e.
73
+ - path: "src/stemtrace/**/*.py"
74
+ instructions: |
75
+ - Does each new class or function hide a decision or remove work from its
76
+ callers? Flag pass-through wrappers and options with no current caller.
77
+ - Constants, timeouts and limits are defined once and imported, not copied.
78
+ - Every blocking call (connect, read, close, join, wait, lock) needs an
79
+ explicit timeout smaller than its caller's.
80
+ - Broad `except Exception` only at fire-and-forget boundaries, with a
81
+ `# noqa: BLE001 <reason>` comment and logging with context.
82
+ - Comments explain why or state an invariant. Comments about third-party
83
+ behavior should name the library version and function.
84
+ - Behavior claims in docstrings, README and CHANGELOG must be backed by a
85
+ test. Changes to user-visible behavior should be opt-in.
86
+ - Bare `# noqa: <codes>` comments are the baseline of code that predates
87
+ the lint rules; it only shrinks. Flag a newly added bare noqa: a new
88
+ suppression must give a reason after the codes, and a refactor
89
+ should delete the noqa it makes unnecessary.
90
+
91
+ chat:
92
+ art: false
@@ -39,6 +39,7 @@ ENV/
39
39
  .pytest_cache/
40
40
  .mypy_cache/
41
41
  .ruff_cache/
42
+ .import_linter_cache/
42
43
  .coverage
43
44
  htmlcov/
44
45
  .tox/
@@ -15,6 +15,7 @@ jobs:
15
15
  lint:
16
16
  if: github.event_name == 'pull_request'
17
17
  runs-on: ubuntu-latest
18
+ timeout-minutes: 10
18
19
  env:
19
20
  UV_PYTHON: "3.12"
20
21
  STEMTRACE_SKIP_UI_BUILD: "1"
@@ -40,9 +41,13 @@ jobs:
40
41
  - name: Check formatting
41
42
  run: uv run --locked --no-build ruff format --check src/ tests/
42
43
 
44
+ - name: Check import contracts
45
+ run: uv run --locked --no-build lint-imports
46
+
43
47
  type-check:
44
48
  if: github.event_name == 'pull_request'
45
49
  runs-on: ubuntu-latest
50
+ timeout-minutes: 10
46
51
  env:
47
52
  UV_PYTHON: "3.12"
48
53
  STEMTRACE_SKIP_UI_BUILD: "1"
@@ -68,6 +73,7 @@ jobs:
68
73
  test:
69
74
  if: github.event_name == 'pull_request'
70
75
  runs-on: ubuntu-latest
76
+ timeout-minutes: 15
71
77
  env:
72
78
  UV_PYTHON: ${{ matrix.python-version }}
73
79
  STEMTRACE_SKIP_UI_BUILD: "1"
@@ -104,6 +110,7 @@ jobs:
104
110
  audit:
105
111
  name: Audit runtime dependencies
106
112
  runs-on: ubuntu-latest
113
+ timeout-minutes: 10
107
114
  env:
108
115
  UV_PYTHON: "3.12"
109
116
  steps:
@@ -128,6 +135,7 @@ jobs:
128
135
  frontend:
129
136
  if: github.event_name == 'pull_request'
130
137
  runs-on: ubuntu-latest
138
+ timeout-minutes: 10
131
139
  defaults:
132
140
  run:
133
141
  working-directory: src/stemtrace/server/ui/frontend
@@ -153,6 +161,7 @@ jobs:
153
161
  build:
154
162
  if: github.event_name == 'pull_request'
155
163
  runs-on: ubuntu-latest
164
+ timeout-minutes: 15
156
165
  env:
157
166
  UV_PYTHON: "3.12"
158
167
  needs: [lint, type-check, test, frontend]
@@ -200,6 +209,7 @@ jobs:
200
209
  # actual default-branch commit after merges (or direct pushes / releases).
201
210
  if: github.ref == 'refs/heads/main' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
202
211
  runs-on: ubuntu-latest
212
+ timeout-minutes: 15
203
213
  env:
204
214
  UV_PYTHON: "3.12"
205
215
  STEMTRACE_SKIP_UI_BUILD: "1"
@@ -8,6 +8,7 @@ on:
8
8
  jobs:
9
9
  build:
10
10
  runs-on: ubuntu-latest
11
+ timeout-minutes: 15
11
12
  env:
12
13
  UV_PYTHON: "3.12"
13
14
  outputs:
@@ -87,8 +88,11 @@ jobs:
87
88
  path: dist/
88
89
 
89
90
  pypi:
90
- needs: build
91
+ # After the image: a failed or hung docker build then publishes nothing,
92
+ # instead of leaving PyPI ahead of GHCR and the GitHub Release.
93
+ needs: [build, docker]
91
94
  runs-on: ubuntu-latest
95
+ timeout-minutes: 10
92
96
  environment: pypi
93
97
  permissions:
94
98
  id-token: write
@@ -105,6 +109,7 @@ jobs:
105
109
  docker:
106
110
  needs: build
107
111
  runs-on: ubuntu-latest
112
+ timeout-minutes: 25
108
113
  permissions:
109
114
  contents: read
110
115
  packages: write
@@ -147,6 +152,7 @@ jobs:
147
152
  github-release:
148
153
  needs: [build, pypi, docker]
149
154
  runs-on: ubuntu-latest
155
+ timeout-minutes: 10
150
156
  permissions:
151
157
  contents: write
152
158
  steps:
@@ -14,6 +14,7 @@ htmlcov/
14
14
  # Type checking / linting
15
15
  .mypy_cache/
16
16
  .ruff_cache/
17
+ .import_linter_cache/
17
18
 
18
19
  # Virtual environments
19
20
  .venv/
@@ -30,3 +30,9 @@ repos:
30
30
  language: system
31
31
  types: [python]
32
32
  pass_filenames: false
33
+ - id: lint-imports
34
+ name: import contracts
35
+ entry: uv run lint-imports
36
+ language: system
37
+ types: [python]
38
+ pass_filenames: false
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.10] - 2026-10-11
11
+
12
+ ### Changed
13
+ - Docker image: the UI is built once on the build machine's native platform instead of under emulation for each architecture, which also makes release builds faster. Building the image from source now needs BuildKit (the default since Docker 23 and in `docker compose`).
14
+ - Development: ruff now also enforces complexity, function-size, blind-`except` and dead-code rules, and [import-linter](https://import-linter.readthedocs.io/) checks the `core`/`library`/`server` import boundaries in `make lint` and CI (see CONTRIBUTING.md). No runtime change.
15
+ - The broker transports moved from `stemtrace.library.transports` to `stemtrace.transports`, so the Celery integration and the server share them without importing each other. The old module paths (`stemtrace.library.transports` and its `redis`, `rabbitmq`, `memory` and `breaker` submodules) still import the same public classes and functions but emit a `DeprecationWarning`, and will be removed in 1.0; patching module internals through the old paths (e.g. `mock.patch("stemtrace.library.transports.redis.time.sleep")`) no longer reaches the real code, so update such patches to `stemtrace.transports`. The transports' loggers are renamed to match (e.g. `stemtrace.transports.rabbitmq`); logging configured for the `stemtrace` logger is unaffected.
16
+
17
+ ### Fixed
18
+ - Redis: a stream entry whose payload is valid JSON but not an object (e.g. `42`) is now skipped with a warning; it used to end the consumer's read loop and trigger a restart.
19
+
10
20
  ## [0.3.9] - 2026-10-10
11
21
 
12
22
  ### Added
@@ -186,7 +196,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
186
196
  - **E2E test suite**: Docker API tests + Playwright browser tests
187
197
  - **Comprehensive test suite**: 350+ Python tests, 90%+ coverage
188
198
 
189
- [unreleased]: https://github.com/iansokolskyi/stemtrace/compare/v0.3.9...HEAD
199
+ [unreleased]: https://github.com/iansokolskyi/stemtrace/compare/v0.3.10...HEAD
200
+ [0.3.10]: https://github.com/iansokolskyi/stemtrace/compare/v0.3.9...v0.3.10
190
201
  [0.3.9]: https://github.com/iansokolskyi/stemtrace/compare/v0.3.8...v0.3.9
191
202
  [0.3.8]: https://github.com/iansokolskyi/stemtrace/compare/v0.3.7...v0.3.8
192
203
  [0.3.7]: https://github.com/iansokolskyi/stemtrace/compare/v0.3.6...v0.3.7
@@ -37,7 +37,7 @@ make check
37
37
  make check
38
38
 
39
39
  # Individual checks
40
- make lint # ruff check + format
40
+ make lint # ruff check + format + import contracts
41
41
  make types # mypy --strict
42
42
  make test # pytest with coverage
43
43
  ```
@@ -54,6 +54,38 @@ uv run ruff check --fix src/ tests/
54
54
  uv run ruff format src/ tests/
55
55
  ```
56
56
 
57
+ ### Lint Rules and Import Contracts
58
+
59
+ Besides style, ruff enforces design limits: McCabe complexity 10 (`C90`), at most
60
+ 12 branches, 6 returns, 50 statements and 5 positional arguments per function
61
+ (`PLR09xx`; make extra parameters keyword-only), no blind `except Exception`
62
+ (`BLE`), no commented-out code (`ERA`), plus `RET` and `PT` style rules. A broad
63
+ except is accepted only at a fire-and-forget boundary, with
64
+ `# noqa: BLE001 <reason>` on that line.
65
+
66
+ [import-linter](https://import-linter.readthedocs.io/) checks the architecture
67
+ boundaries (`uv run lint-imports`, part of `make lint` and CI):
68
+
69
+ - `stemtrace.core` imports nothing from `stemtrace.library`, `stemtrace.server` or
70
+ `stemtrace.transports`, and no broker, Celery or web library (`celery`, `kombu`,
71
+ `amqp`, `redis`, `fastapi`, `starlette`, `uvicorn`, `typer`, `httpx`)
72
+ - `stemtrace.transports` imports nothing from `stemtrace.library` or
73
+ `stemtrace.server` (both of them use it)
74
+ - `stemtrace.library` does not import `stemtrace.server`
75
+ - `stemtrace.server` does not import `stemtrace.library`
76
+
77
+ **Baseline policy.** Code that predates these rules carries a per-line
78
+ `# noqa: <codes>` comment with no reason (added with `ruff check --add-noqa`).
79
+ Known import violations, if any, are listed under `ignore_imports` in
80
+ `pyproject.toml` (there are none at the moment). The baseline only shrinks:
81
+
82
+ - New code follows the rules. If a suppression is really needed, it names the
83
+ code and gives a reason: `# noqa: BLE001 fire-and-forget: <why>`. Never add a
84
+ bare `# noqa`.
85
+ - When you fix a baselined line, delete its `# noqa`. Ruff's `RUF100` fails on a
86
+ `# noqa` that no longer suppresses anything, and import-linter fails on an
87
+ `ignore_imports` entry that no longer matches, so stale entries can't linger.
88
+
57
89
  ### Type Checking
58
90
 
59
91
  All code must pass `mypy --strict`:
@@ -125,8 +157,9 @@ uv lock --upgrade
125
157
  ### Key Principles
126
158
 
127
159
  - **core/** - Pure Python, no external dependencies
128
- - **library/** - Celery integration, imports only from core/
129
- - **server/** - Web server, imports only from core/
160
+ - **transports/** - Broker adapters (Redis, RabbitMQ, memory), imports only from core/
161
+ - **library/** - Celery integration, imports only from core/ and transports/
162
+ - **server/** - Web server, imports only from core/ and transports/
130
163
  - Never import sideways (library ↔ server)
131
164
 
132
165
  ### Code Quality
@@ -2,7 +2,9 @@
2
2
  # Multi-stage build for smaller production image
3
3
 
4
4
  # Stage 1: Build frontend
5
- FROM node:22.23.3-alpine3.24@sha256:0a7108bf6c7bf5de370ffb1a3ed6be93d405b43ff159f681a8d18c0e2bc2e402 AS frontend-builder
5
+ # The UI build output is static files, identical for every platform, so build it
6
+ # once on the native build platform instead of under QEMU (npm ci hung there).
7
+ FROM --platform=$BUILDPLATFORM node:22.23.3-alpine3.24@sha256:0a7108bf6c7bf5de370ffb1a3ed6be93d405b43ff159f681a8d18c0e2bc2e402 AS frontend-builder
6
8
 
7
9
  WORKDIR /app/frontend
8
10
  COPY src/stemtrace/server/ui/frontend/package*.json ./
@@ -30,6 +30,7 @@ exit(1) if missing else print('✓ All public APIs have docstrings') \
30
30
  lint:
31
31
  uv run ruff check src/ tests/
32
32
  uv run ruff format --check src/ tests/
33
+ uv run lint-imports
33
34
 
34
35
  format:
35
36
  uv run ruff format src/ tests/
@@ -57,7 +58,7 @@ coverage:
57
58
 
58
59
  # Clean build artifacts
59
60
  clean:
60
- rm -rf .pytest_cache .mypy_cache .ruff_cache htmlcov .coverage dist/
61
+ rm -rf .pytest_cache .mypy_cache .ruff_cache .import_linter_cache htmlcov .coverage dist/
61
62
  find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
62
63
 
63
64
  # =============================================================================
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stemtrace
3
- Version: 0.3.9
3
+ Version: 0.3.10
4
4
  Summary: A lightweight Celery task flow visualizer
5
5
  Project-URL: Homepage, https://github.com/iansokolskyi/stemtrace
6
6
  Project-URL: Documentation, https://github.com/iansokolskyi/stemtrace#readme
@@ -42,6 +42,7 @@ Provides-Extra: dev
42
42
  Requires-Dist: build>=1.0.0; extra == 'dev'
43
43
  Requires-Dist: bump-my-version>=0.28.0; extra == 'dev'
44
44
  Requires-Dist: hatchling>=1.20.0; extra == 'dev'
45
+ Requires-Dist: import-linter>=2.0; extra == 'dev'
45
46
  Requires-Dist: mypy>=1.0.0; extra == 'dev'
46
47
  Requires-Dist: pre-commit>=3.0.0; extra == 'dev'
47
48
  Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
@@ -59,7 +60,7 @@ Description-Content-Type: text/markdown
59
60
 
60
61
  **Zero-infrastructure Celery task flow visualizer**
61
62
 
62
- [![PyPI version](https://img.shields.io/badge/pypi-v0.3.9-darklime)](https://pypi.org/project/stemtrace)
63
+ [![PyPI version](https://img.shields.io/badge/pypi-v0.3.10-darklime)](https://pypi.org/project/stemtrace)
63
64
  [![Python](https://img.shields.io/pypi/pyversions/stemtrace.svg)](https://pypi.org/project/stemtrace/)
64
65
  [![CI](https://github.com/iansokolskyi/stemtrace/actions/workflows/ci.yml/badge.svg)](https://github.com/iansokolskyi/stemtrace/actions/workflows/ci.yml)
65
66
  [![codecov](https://codecov.io/gh/iansokolskyi/stemtrace/graph/badge.svg)](https://codecov.io/gh/iansokolskyi/stemtrace)
@@ -4,7 +4,7 @@
4
4
 
5
5
  **Zero-infrastructure Celery task flow visualizer**
6
6
 
7
- [![PyPI version](https://img.shields.io/badge/pypi-v0.3.9-darklime)](https://pypi.org/project/stemtrace)
7
+ [![PyPI version](https://img.shields.io/badge/pypi-v0.3.10-darklime)](https://pypi.org/project/stemtrace)
8
8
  [![Python](https://img.shields.io/pypi/pyversions/stemtrace.svg)](https://pypi.org/project/stemtrace/)
9
9
  [![CI](https://github.com/iansokolskyi/stemtrace/actions/workflows/ci.yml/badge.svg)](https://github.com/iansokolskyi/stemtrace/actions/workflows/ci.yml)
10
10
  [![codecov](https://codecov.io/gh/iansokolskyi/stemtrace/graph/badge.svg)](https://codecov.io/gh/iansokolskyi/stemtrace)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "stemtrace"
3
- version = "0.3.9"
3
+ version = "0.3.10"
4
4
  description = "A lightweight Celery task flow visualizer"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -57,6 +57,7 @@ dev = [
57
57
  "websockets>=12.0", # For WebSocket E2E tests
58
58
  "build>=1.0.0", # For local package builds
59
59
  "twine>=5.0.0", # For package verification
60
+ "import-linter>=2.0", # Enforces the core/library/server import boundaries (make lint, CI)
60
61
  ]
61
62
 
62
63
  [project.urls]
@@ -137,8 +138,27 @@ select = [
137
138
  "TCH", # flake8-type-checking
138
139
  "PTH", # flake8-use-pathlib
139
140
  "RUF", # Ruff-specific
141
+ "PGH004", # blanket noqa (always name the rule)
140
142
  "D", # pydocstyle
143
+ "C90", # mccabe complexity
144
+ "PLR0911", # too many return statements
145
+ "PLR0912", # too many branches
146
+ "PLR0915", # too many statements
147
+ "PLR0917", # too many positional arguments (make extra params keyword-only)
148
+ "BLE", # blind except (allowed only with `# noqa: BLE001 <reason>`)
149
+ "ERA", # commented-out code
150
+ "RET", # flake8-return
151
+ "PT", # flake8-pytest-style
152
+ "PLR0402", # manual from-import
153
+ "PLR1711", # useless return
154
+ "PLR1714", # repeated equality comparison
155
+ "PLR5501", # collapsible else-if
141
156
  ]
157
+ # Baseline: code that predates the rules above carries a per-line
158
+ # `# noqa: <codes>` (added with `ruff check --add-noqa`), to be removed by
159
+ # refactors. Don't add bare noqa comments: a new one needs a reason after the
160
+ # codes, e.g. `# noqa: BLE001 fire-and-forget: ...`. RUF100 (via "RUF") flags
161
+ # any noqa that no longer suppresses anything, so the baseline only shrinks.
142
162
  ignore = [
143
163
  "E501", # Line too long (handled by formatter)
144
164
  "D100", # Missing docstring in public module
@@ -146,6 +166,16 @@ ignore = [
146
166
  "D107", # Missing docstring in __init__
147
167
  ]
148
168
 
169
+ [tool.ruff.lint.mccabe]
170
+ max-complexity = 10
171
+
172
+ [tool.ruff.lint.pylint]
173
+ # pylint defaults, written down so the limits are visible
174
+ max-branches = 12
175
+ max-returns = 6
176
+ max-statements = 50
177
+ max-positional-args = 5
178
+
149
179
  [tool.ruff.lint.pydocstyle]
150
180
  convention = "google"
151
181
 
@@ -156,6 +186,53 @@ known-first-party = ["stemtrace"]
156
186
  "tests/**/*.py" = ["D", "ARG"] # No docstrings required in tests
157
187
  "examples/**/*.py" = ["ARG001", "D417"] # bind=True tasks have unused self
158
188
 
189
+ # =============================================================================
190
+ # import-linter (architecture boundaries, see CONTRIBUTING.md)
191
+ # =============================================================================
192
+ [tool.importlinter]
193
+ root_package = "stemtrace"
194
+ include_external_packages = true
195
+
196
+ [[tool.importlinter.contracts]]
197
+ name = "core is independent of library, server and transports"
198
+ type = "forbidden"
199
+ source_modules = ["stemtrace.core"]
200
+ forbidden_modules = ["stemtrace.library", "stemtrace.server", "stemtrace.transports"]
201
+
202
+ [[tool.importlinter.contracts]]
203
+ name = "core uses no broker, Celery or web libraries"
204
+ type = "forbidden"
205
+ source_modules = ["stemtrace.core"]
206
+ forbidden_modules = [
207
+ "amqp",
208
+ "celery",
209
+ "fastapi",
210
+ "httpx",
211
+ "kombu",
212
+ "redis",
213
+ "starlette",
214
+ "typer",
215
+ "uvicorn",
216
+ ]
217
+
218
+ [[tool.importlinter.contracts]]
219
+ name = "library does not import server"
220
+ type = "forbidden"
221
+ source_modules = ["stemtrace.library"]
222
+ forbidden_modules = ["stemtrace.server"]
223
+
224
+ [[tool.importlinter.contracts]]
225
+ name = "server does not import library"
226
+ type = "forbidden"
227
+ source_modules = ["stemtrace.server"]
228
+ forbidden_modules = ["stemtrace.library"]
229
+
230
+ [[tool.importlinter.contracts]]
231
+ name = "transports import only core (library and server both use them)"
232
+ type = "forbidden"
233
+ source_modules = ["stemtrace.transports"]
234
+ forbidden_modules = ["stemtrace.library", "stemtrace.server"]
235
+
159
236
  # =============================================================================
160
237
  # pytest
161
238
  # =============================================================================
@@ -26,7 +26,6 @@ class _NoRedirectHandler(urllib.request.HTTPRedirectHandler):
26
26
 
27
27
  def redirect_request(self, *_args: object, **_kwargs: object) -> None:
28
28
  """Return None so urllib raises HTTPError instead of following."""
29
- return None
30
29
 
31
30
 
32
31
  _OPENER = urllib.request.build_opener(_NoRedirectHandler())
@@ -20,6 +20,7 @@ import os
20
20
  import warnings
21
21
  from typing import TYPE_CHECKING, Any
22
22
 
23
+ from stemtrace._version import __version__
23
24
  from stemtrace.core.events import TaskEvent, TaskState
24
25
  from stemtrace.core.exceptions import ConfigurationError
25
26
  from stemtrace.core.graph import TaskGraph, TaskNode
@@ -28,7 +29,6 @@ from stemtrace.library.bootsteps import register_bootsteps
28
29
  from stemtrace.library.config import StemtraceConfig, _reset_config, set_config
29
30
  from stemtrace.library.config import get_config as _get_config
30
31
  from stemtrace.library.signals import connect_signals
31
- from stemtrace.library.transports import get_transport as _get_transport
32
32
  from stemtrace.server.fastapi import (
33
33
  StemtraceExtension,
34
34
  create_router,
@@ -38,12 +38,12 @@ from stemtrace.server.fastapi import (
38
38
  from stemtrace.server.fastapi.form_auth import FormAuthConfig, resolve_session_secret
39
39
  from stemtrace.server.fastapi.form_auth_middleware import create_form_auth_middleware
40
40
  from stemtrace.server.fastapi.login_routes import create_login_router
41
+ from stemtrace.transports import get_transport as _get_transport
41
42
 
42
43
  if TYPE_CHECKING:
43
44
  from celery import Celery
44
45
  from fastapi import FastAPI
45
46
 
46
- __version__ = "0.3.9"
47
47
  __all__ = [
48
48
  "ConfigurationError",
49
49
  "StemtraceConfig",
@@ -0,0 +1,8 @@
1
+ """Package version, kept in a leaf module.
2
+
3
+ It imports nothing, so ``stemtrace.server`` can read the version without
4
+ importing the package root (which pulls in ``stemtrace.library``).
5
+ bump-my-version updates the string; see ``.bumpversion.toml``.
6
+ """
7
+
8
+ __version__ = "0.3.10"