mockstack 0.12.1__tar.gz → 0.14.0__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 (172) hide show
  1. mockstack-0.14.0/.env.example +49 -0
  2. {mockstack-0.12.1 → mockstack-0.14.0}/.github/workflows/ci.yml +23 -3
  3. {mockstack-0.12.1 → mockstack-0.14.0}/.github/workflows/smoke-test-pypi.yml +1 -1
  4. {mockstack-0.12.1 → mockstack-0.14.0}/.gitignore +4 -0
  5. {mockstack-0.12.1 → mockstack-0.14.0}/.pre-commit-config.yaml +14 -8
  6. mockstack-0.14.0/CLAUDE.md +104 -0
  7. {mockstack-0.12.1 → mockstack-0.14.0}/CONTRIBUTING.md +17 -13
  8. {mockstack-0.12.1 → mockstack-0.14.0}/Dockerfile +1 -1
  9. {mockstack-0.12.1/mockstack.egg-info → mockstack-0.14.0}/PKG-INFO +78 -24
  10. mockstack-0.12.1/PKG-INFO → mockstack-0.14.0/README.md +63 -43
  11. mockstack-0.14.0/docs/configuration.md +141 -0
  12. mockstack-0.14.0/docs/guides/proxyrules-cookbook.md +542 -0
  13. {mockstack-0.12.1 → mockstack-0.14.0}/docs/ollama.md +5 -1
  14. {mockstack-0.12.1 → mockstack-0.14.0}/docs/strategies/base.md +1 -0
  15. mockstack-0.14.0/docs/strategies/filefixtures.md +136 -0
  16. mockstack-0.14.0/docs/strategies/proxyrules.md +647 -0
  17. {mockstack-0.12.1 → mockstack-0.14.0}/examples/filefixtures-with-templates/.env.example +1 -1
  18. {mockstack-0.12.1 → mockstack-0.14.0}/examples/filefixtures-with-templates/README.md +2 -2
  19. mockstack-0.14.0/examples/filefixtures-with-templates/templates/servicename-api-v1-items.j2 +20 -0
  20. {mockstack-0.12.1 → mockstack-0.14.0}/examples/llm/mockstack-langchain-example.ipynb +15 -12
  21. mockstack-0.14.0/examples/proxyrules-cookbook/01-tagged-traffic/fixtures/projects/project.json.j2 +1 -0
  22. mockstack-0.14.0/examples/proxyrules-cookbook/01-tagged-traffic/rules.yml +11 -0
  23. mockstack-0.14.0/examples/proxyrules-cookbook/02-scenario-directories/fixtures/archived/projects/project.json.j2 +1 -0
  24. mockstack-0.14.0/examples/proxyrules-cookbook/02-scenario-directories/fixtures/healthy/projects/project.json.j2 +1 -0
  25. mockstack-0.14.0/examples/proxyrules-cookbook/02-scenario-directories/rules.yml +11 -0
  26. mockstack-0.14.0/examples/proxyrules-cookbook/03-sql-gateway/fixtures/analytics/sales_facts.json.j2 +1 -0
  27. mockstack-0.14.0/examples/proxyrules-cookbook/03-sql-gateway/rules.yml +11 -0
  28. mockstack-0.14.0/examples/proxyrules-cookbook/04-json-literals/fixtures/orders/search.json.j2 +1 -0
  29. mockstack-0.14.0/examples/proxyrules-cookbook/04-json-literals/rules.yml +32 -0
  30. mockstack-0.14.0/examples/proxyrules-cookbook/05-query-parameters/fixtures/users/archived.json.j2 +1 -0
  31. mockstack-0.14.0/examples/proxyrules-cookbook/05-query-parameters/fixtures/users/page.json.j2 +1 -0
  32. mockstack-0.14.0/examples/proxyrules-cookbook/05-query-parameters/rules.yml +18 -0
  33. mockstack-0.14.0/examples/proxyrules-cookbook/06-asserting-in-tests/fixture_assertions.py +40 -0
  34. mockstack-0.14.0/examples/proxyrules-cookbook/06-asserting-in-tests/fixtures/orders/echo.json.j2 +1 -0
  35. mockstack-0.14.0/examples/proxyrules-cookbook/06-asserting-in-tests/fixtures/projects/project.json.j2 +1 -0
  36. mockstack-0.14.0/examples/proxyrules-cookbook/06-asserting-in-tests/fixtures/users/user-1.json.j2 +1 -0
  37. mockstack-0.14.0/examples/proxyrules-cookbook/06-asserting-in-tests/rules.yml +44 -0
  38. mockstack-0.14.0/examples/proxyrules-cookbook/07-redirect-mode/fixtures/users/user-1.json.j2 +1 -0
  39. mockstack-0.14.0/examples/proxyrules-cookbook/07-redirect-mode/rules.yml +9 -0
  40. mockstack-0.14.0/examples/proxyrules-cookbook/08-status-and-headers/fixtures/errors/rate-limited.json.j2 +1 -0
  41. mockstack-0.14.0/examples/proxyrules-cookbook/08-status-and-headers/fixtures/errors/unavailable.json.j2 +1 -0
  42. mockstack-0.14.0/examples/proxyrules-cookbook/08-status-and-headers/fixtures/orders/created.json.j2 +1 -0
  43. mockstack-0.14.0/examples/proxyrules-cookbook/08-status-and-headers/rules.yml +36 -0
  44. mockstack-0.14.0/examples/proxyrules-cookbook/09-recording/rules.yml +11 -0
  45. mockstack-0.14.0/examples/proxyrules-cookbook/09-recording/scrubbers.py +14 -0
  46. mockstack-0.14.0/examples/proxyrules-cookbook/README.md +60 -0
  47. mockstack-0.14.0/examples/proxyrules-cookbook/upstream.py +40 -0
  48. mockstack-0.14.0/examples/proxyrules-eval-isolation/.env.example +16 -0
  49. mockstack-0.14.0/examples/proxyrules-eval-isolation/README.md +78 -0
  50. mockstack-0.14.0/examples/proxyrules-eval-isolation/fixtures/healthy/analytics/sales_facts.json.j2 +1 -0
  51. mockstack-0.14.0/examples/proxyrules-eval-isolation/fixtures/healthy/projects/project.json.j2 +1 -0
  52. mockstack-0.14.0/examples/proxyrules-eval-isolation/rules.yml +26 -0
  53. mockstack-0.14.0/examples/proxyrules-eval-isolation/upstream.py +27 -0
  54. {mockstack-0.12.1 → mockstack-0.14.0}/examples/proxyrules-with-rules-file/.env.example +2 -2
  55. mockstack-0.14.0/examples/proxyrules-with-rules-file/README.md +16 -0
  56. {mockstack-0.12.1 → mockstack-0.14.0}/mkdocs.yml +5 -2
  57. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/config.py +45 -22
  58. mockstack-0.14.0/mockstack/constants.py +80 -0
  59. mockstack-0.14.0/mockstack/display.py +52 -0
  60. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/exceptions.py +3 -1
  61. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/identifiers.py +9 -10
  62. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/lifespan.py +3 -3
  63. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/llm/ollama.py +9 -8
  64. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/main.py +10 -10
  65. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/middleware.py +11 -10
  66. mockstack-0.14.0/mockstack/recording.py +77 -0
  67. mockstack-0.14.0/mockstack/routers/catchall.py +23 -0
  68. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/routers/homepage.py +3 -2
  69. mockstack-0.14.0/mockstack/rules.py +408 -0
  70. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/strategies/__init__.py +1 -0
  71. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/strategies/base.py +4 -4
  72. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/strategies/create_mixin.py +12 -19
  73. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/strategies/factory.py +1 -3
  74. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/strategies/filefixtures.py +52 -23
  75. mockstack-0.14.0/mockstack/strategies/proxyrules.py +777 -0
  76. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/telemetry.py +9 -20
  77. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/templating.py +19 -21
  78. mockstack-0.14.0/mockstack/tests/conftest.py +189 -0
  79. mockstack-0.14.0/mockstack/tests/live/conftest.py +261 -0
  80. mockstack-0.14.0/mockstack/tests/live/test_cookbook.py +632 -0
  81. mockstack-0.14.0/mockstack/tests/live/test_example_eval_isolation.py +89 -0
  82. mockstack-0.14.0/mockstack/tests/live/test_fixture_status_live.py +73 -0
  83. mockstack-0.14.0/mockstack/tests/live/test_predicates_live.py +58 -0
  84. mockstack-0.14.0/mockstack/tests/live/test_record_mode_live.py +142 -0
  85. mockstack-0.14.0/mockstack/tests/live/test_reverse_proxy_live.py +116 -0
  86. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/tests/llm/test_ollama.py +32 -36
  87. mockstack-0.14.0/mockstack/tests/routers/test_catchall.py +60 -0
  88. mockstack-0.14.0/mockstack/tests/routers/test_homepage.py +15 -0
  89. mockstack-0.14.0/mockstack/tests/strategies/__init__.py +0 -0
  90. mockstack-0.14.0/mockstack/tests/strategies/conftest.py +74 -0
  91. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/tests/strategies/test_create_mixin.py +19 -75
  92. mockstack-0.14.0/mockstack/tests/strategies/test_filefixtures.py +294 -0
  93. mockstack-0.14.0/mockstack/tests/strategies/test_filefixtures_example.py +41 -0
  94. mockstack-0.14.0/mockstack/tests/strategies/test_proxyrules.py +1427 -0
  95. mockstack-0.14.0/mockstack/tests/strategies/test_proxyrules_record.py +552 -0
  96. mockstack-0.14.0/mockstack/tests/test_config.py +168 -0
  97. mockstack-0.14.0/mockstack/tests/test_display.py +51 -0
  98. mockstack-0.14.0/mockstack/tests/test_docs_settings.py +73 -0
  99. mockstack-0.14.0/mockstack/tests/test_docs_yaml.py +54 -0
  100. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/tests/test_identifiers.py +29 -40
  101. mockstack-0.14.0/mockstack/tests/test_intent.py +76 -0
  102. mockstack-0.14.0/mockstack/tests/test_middleware.py +23 -0
  103. mockstack-0.14.0/mockstack/tests/test_recording.py +176 -0
  104. mockstack-0.14.0/mockstack/tests/test_rules.py +893 -0
  105. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/tests/test_telemetry.py +40 -73
  106. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/tests/test_templating.py +75 -123
  107. mockstack-0.14.0/mockstack.egg-info/PKG-INFO +193 -0
  108. mockstack-0.14.0/mockstack.egg-info/SOURCES.txt +145 -0
  109. mockstack-0.14.0/mockstack.egg-info/requires.txt +15 -0
  110. mockstack-0.14.0/mockstack.egg-info/scm_file_list.json +141 -0
  111. mockstack-0.14.0/mockstack.egg-info/scm_version.json +8 -0
  112. mockstack-0.14.0/pyproject.toml +167 -0
  113. mockstack-0.14.0/uv.lock +1936 -0
  114. mockstack-0.12.1/.env.example +0 -25
  115. mockstack-0.12.1/README.md +0 -106
  116. mockstack-0.12.1/docs/configuration.md +0 -103
  117. mockstack-0.12.1/docs/strategies/filefixtures.md +0 -109
  118. mockstack-0.12.1/docs/strategies/proxyrules.md +0 -123
  119. mockstack-0.12.1/examples/filefixtures-with-templates/templates/servicename-api-v1-items.j2 +0 -19
  120. mockstack-0.12.1/examples/proxyrules-with-rules-file/README.md +0 -15
  121. mockstack-0.12.1/mockstack/constants.py +0 -38
  122. mockstack-0.12.1/mockstack/display.py +0 -30
  123. mockstack-0.12.1/mockstack/routers/catchall.py +0 -16
  124. mockstack-0.12.1/mockstack/rules.py +0 -117
  125. mockstack-0.12.1/mockstack/strategies/proxyrules.py +0 -274
  126. mockstack-0.12.1/mockstack/tests/conftest.py +0 -78
  127. mockstack-0.12.1/mockstack/tests/routers/test_catchall.py +0 -46
  128. mockstack-0.12.1/mockstack/tests/routers/test_homepage.py +0 -27
  129. mockstack-0.12.1/mockstack/tests/strategies/test_filefixtures.py +0 -275
  130. mockstack-0.12.1/mockstack/tests/strategies/test_proxyrules.py +0 -397
  131. mockstack-0.12.1/mockstack/tests/test_display.py +0 -20
  132. mockstack-0.12.1/mockstack/tests/test_intent.py +0 -160
  133. mockstack-0.12.1/mockstack/tests/test_middleware.py +0 -37
  134. mockstack-0.12.1/mockstack/tests/test_rules.py +0 -168
  135. mockstack-0.12.1/mockstack.egg-info/SOURCES.txt +0 -92
  136. mockstack-0.12.1/mockstack.egg-info/requires.txt +0 -15
  137. mockstack-0.12.1/pyproject.toml +0 -69
  138. mockstack-0.12.1/uv.lock +0 -2030
  139. {mockstack-0.12.1 → mockstack-0.14.0}/.dockerignore +0 -0
  140. {mockstack-0.12.1 → mockstack-0.14.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  141. {mockstack-0.12.1 → mockstack-0.14.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  142. {mockstack-0.12.1 → mockstack-0.14.0}/.github/workflows/publish-docs.yml +0 -0
  143. {mockstack-0.12.1 → mockstack-0.14.0}/.github/workflows/publish-to-pypi.yml +0 -0
  144. {mockstack-0.12.1 → mockstack-0.14.0}/CODE_OF_CONDUCT.md +0 -0
  145. {mockstack-0.12.1 → mockstack-0.14.0}/LICENSE +0 -0
  146. {mockstack-0.12.1 → mockstack-0.14.0}/SECURITY.md +0 -0
  147. {mockstack-0.12.1 → mockstack-0.14.0}/docker-entrypoint.sh +0 -0
  148. {mockstack-0.12.1 → mockstack-0.14.0}/docs/assets/favicon.ico +0 -0
  149. {mockstack-0.12.1 → mockstack-0.14.0}/docs/assets/logo.png +0 -0
  150. {mockstack-0.12.1 → mockstack-0.14.0}/docs/assets/mockstack.png +0 -0
  151. {mockstack-0.12.1 → mockstack-0.14.0}/examples/filefixtures-with-templates/templates/servicename2-api-v2-user.533ec889-7c68-45c8-b21e-4a7e455d1234.j2 +0 -0
  152. {mockstack-0.12.1 → mockstack-0.14.0}/examples/llm/README.md +0 -0
  153. {mockstack-0.12.1 → mockstack-0.14.0}/examples/llm/templates/ollama-openai-v1-chat-completions.j2 +0 -0
  154. {mockstack-0.12.1 → mockstack-0.14.0}/examples/llm/templates/openai-v1-chat-completions.j2 +0 -0
  155. {mockstack-0.12.1 → mockstack-0.14.0}/examples/llm/templates/openai-v1-deployments-gpt-4o-chat-completions.j2 +0 -0
  156. {mockstack-0.12.1 → mockstack-0.14.0}/examples/proxyrules-with-rules-file/rules.yml +0 -0
  157. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/__init__.py +0 -0
  158. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/intent.py +0 -0
  159. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/llm/__init__.py +0 -0
  160. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/routers/__init__.py +0 -0
  161. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/tests/__init__.py +0 -0
  162. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/tests/fixtures/__init__.py +0 -0
  163. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/tests/fixtures/proxyrules.yml +0 -0
  164. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/tests/fixtures/templates/__init__.py +0 -0
  165. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack/tests/fixtures/templates/example-template.j2 +0 -0
  166. {mockstack-0.12.1/mockstack/tests/llm → mockstack-0.14.0/mockstack/tests/live}/__init__.py +0 -0
  167. {mockstack-0.12.1/mockstack/tests/routers → mockstack-0.14.0/mockstack/tests/llm}/__init__.py +0 -0
  168. {mockstack-0.12.1/mockstack/tests/strategies → mockstack-0.14.0/mockstack/tests/routers}/__init__.py +0 -0
  169. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack.egg-info/dependency_links.txt +0 -0
  170. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack.egg-info/entry_points.txt +0 -0
  171. {mockstack-0.12.1 → mockstack-0.14.0}/mockstack.egg-info/top_level.txt +0 -0
  172. {mockstack-0.12.1 → mockstack-0.14.0}/setup.cfg +0 -0
@@ -0,0 +1,49 @@
1
+ # Example environment variables for mockstack.
2
+ # Copy this file to `.env` in the directory you run mockstack from and adjust the values.
3
+ # Every setting, with its default, is listed at https://promptromp.github.io/mockstack/configuration/
4
+
5
+ # the strategy to use: filefixtures (the default) or proxyrules
6
+ MOCKSTACK__STRATEGY = filefixtures
7
+
8
+ # strategy-specific settings
9
+
10
+ # base dir for all templates. Required by the 'filefixtures' strategy
11
+ # (and other hybrid strategies utilizing templates); the directory must exist.
12
+ MOCKSTACK__TEMPLATES_DIR = "/some/path/templates/"
13
+
14
+ # When using filefixtures strategy, controls whether POST requests first try a
15
+ # matching template (default: true). With templates off, or when no template
16
+ # matches, a POST is handled as a search, a command or a simulated create.
17
+ MOCKSTACK__FILEFIXTURES_ENABLE_TEMPLATES_FOR_POST = false
18
+
19
+ # When using filefixtures strategy, controls whether a POST with no matching template
20
+ # simulates creating the resource (default: true) or gets the same 404 as a GET.
21
+ MOCKSTACK__FILEFIXTURES_SIMULATE_CREATE_ON_MISSING = true
22
+
23
+ # rules file for the proxyrules strategy. Required by the 'proxyrules' strategy; the
24
+ # file must exist. See examples/proxyrules-with-rules-file/ and
25
+ # mockstack/tests/fixtures/proxyrules.yml for examples.
26
+ MOCKSTACK__PROXYRULES_RULES_FILENAME="/some/path/proxyrules.yml"
27
+
28
+ # reverse_proxy (default), http_307_temporary or http_301_permanent
29
+ MOCKSTACK__PROXYRULES_REDIRECT_VIA = reverse_proxy
30
+ # timeout in seconds for reverse-proxied requests (default: 10.0)
31
+ MOCKSTACK__PROXYRULES_REVERSE_PROXY_TIMEOUT = 10.0
32
+ MOCKSTACK__PROXYRULES_SIMULATE_CREATE_ON_MISSING = true
33
+ MOCKSTACK__PROXYRULES_VERIFY_SSL_CERTIFICATES = true
34
+
35
+ # record mode for the proxyrules strategy: off (default), missing or overwrite.
36
+ # missing records a fixture rule's file from the next matching URL rule when the file
37
+ # does not exist yet; overwrite also re-records files recorded before. Requests really
38
+ # reach the upstream until recorded. Never enable on a shared or exposed instance.
39
+ # See https://promptromp.github.io/mockstack/strategies/proxyrules/#recording-fixtures
40
+ MOCKSTACK__PROXYRULES_RECORD_MODE = off
41
+ # directory every recorded fixture must resolve inside; required when recording.
42
+ # MOCKSTACK__PROXYRULES_RECORD_ROOT = "/some/path/fixtures/"
43
+ # optional module:function called on every body before it is recorded (must be importable).
44
+ # MOCKSTACK__PROXYRULES_RECORD_SCRUBBER = "my_scrubbers:mask_emails"
45
+
46
+ # OpenTelemetry settings
47
+ MOCKSTACK__OPENTELEMETRY__ENABLED = true
48
+ MOCKSTACK__OPENTELEMETRY__ENDPOINT = "http://localhost:4317/"
49
+ MOCKSTACK__OPENTELEMETRY__CAPTURE_RESPONSE_BODY = true
@@ -20,7 +20,7 @@ jobs:
20
20
  strategy:
21
21
  fail-fast: false
22
22
  matrix:
23
- python-version: ["3.11", "3.12", "3.13"]
23
+ python-version: ["3.13", "3.14"]
24
24
 
25
25
  steps:
26
26
  - uses: actions/checkout@v6
@@ -32,16 +32,36 @@ jobs:
32
32
  - name: Install ruff
33
33
  uses: astral-sh/ruff-action@v4.0.0
34
34
  with:
35
- version: "latest"
35
+ # Pinned to the ruff-pre-commit rev: new ruff releases add rules to the selected
36
+ # families, which should arrive through a deliberate bump, not a random CI run.
37
+ version: "0.16.7"
36
38
  - name: Install the project
37
39
  run: uv sync --all-extras --dev
38
40
  - name: Run ruff lint and formatting checks
39
41
  run: |
40
42
  ruff check
41
- ruff format
43
+ ruff format --check
42
44
  - name: Run mypy
43
45
  run: |
44
46
  uv pip install types-pyyaml
45
47
  uv run mypy mockstack
46
48
  - name: Run tests
47
49
  run: uv run pytest
50
+ - name: Run live tests
51
+ run: uv run pytest -m slow mockstack/tests/live -v
52
+
53
+ docs:
54
+
55
+ runs-on: ubuntu-latest
56
+
57
+ steps:
58
+ - uses: actions/checkout@v6
59
+ - name: Install uv and set the python version
60
+ uses: astral-sh/setup-uv@v8.1.0
61
+ with:
62
+ python-version: "3.13"
63
+ version: "latest"
64
+ - name: Build docs strictly
65
+ run: |
66
+ cp README.md docs/
67
+ uvx --with mkdocs-material mkdocs build --strict
@@ -20,7 +20,7 @@ jobs:
20
20
  strategy:
21
21
  fail-fast: false
22
22
  matrix:
23
- python-version: ["3.11", "3.12", "3.13"]
23
+ python-version: ["3.13", "3.14"]
24
24
  steps:
25
25
  - name: Install uv with Python ${{ matrix.python-version }}
26
26
  uses: astral-sh/setup-uv@v8.1.0
@@ -173,3 +173,7 @@ cython_debug/
173
173
 
174
174
  # do not check in any user templates
175
175
  templates/*.j2
176
+
177
+ # rules files rendered from the examples' ${VAR} placeholders
178
+ examples/**/rules.local.yml
179
+ examples/proxyrules-cookbook/09-recording/fixtures/
@@ -1,4 +1,6 @@
1
1
  fail_fast: true
2
+ default_language_version:
3
+ python: python3
2
4
  repos:
3
5
  - repo: local
4
6
  hooks:
@@ -10,7 +12,7 @@ repos:
10
12
  language: pygrep
11
13
  types: [text]
12
14
  - repo: https://github.com/pre-commit/pre-commit-hooks
13
- rev: v5.0.0
15
+ rev: v6.0.0
14
16
  hooks:
15
17
  - id: check-added-large-files
16
18
  - id: fix-byte-order-marker
@@ -24,23 +26,27 @@ repos:
24
26
  - id: end-of-file-fixer
25
27
  - id: trailing-whitespace
26
28
  - repo: https://github.com/astral-sh/ruff-pre-commit
27
- rev: v0.11.9
29
+ rev: v0.16.7
28
30
  hooks:
29
31
  # Run the linter.
30
32
  - id: ruff
31
33
  args: [ --fix ]
32
34
  # Run the formatter.
33
35
  - id: ruff-format
34
- - repo: https://github.com/pre-commit/mirrors-mypy
35
- rev: v1.15.0
36
- hooks:
37
- - id: mypy
38
- additional_dependencies: [types-pyyaml>=6.0.12]
39
36
  - repo: local
40
37
  hooks:
38
+ # mypy runs from the dev dependency group in uv.lock, exactly as CI runs it: the
39
+ # stricter checks need the real third-party packages installed, which an isolated
40
+ # hook environment would have to duplicate in `additional_dependencies`.
41
+ - id: mypy
42
+ name: mypy
43
+ entry: bash -ec "uv run mypy mockstack"
44
+ language: system
45
+ types: [python]
46
+ pass_filenames: false
41
47
  - id: pytest
42
48
  name: pytest [with coverage, without slow]
43
- entry: bash -ec "uv run python -m pytest --cov=mockstack mockstack/tests --cov-fail-under='85' -m 'not slow'"
49
+ entry: bash -ec "uv run python -m pytest --cov=mockstack mockstack/tests --cov-fail-under='90' -m 'not slow'"
44
50
  language: system
45
51
  types: [python]
46
52
  pass_filenames: false
@@ -0,0 +1,104 @@
1
+ # CLAUDE.md
2
+
3
+ Guidance for AI coding agents and contributors working in this repository.
4
+
5
+ ## What mockstack is
6
+
7
+ mockstack is an API-mocking service built on FastAPI. A catch-all route hands every
8
+ request to one *strategy*, selected with the `strategy` setting:
9
+
10
+ - `filefixtures`: renders Jinja templates from `templates_dir`, chosen from the request
11
+ path, and simulates resource creation, searches and commands for POSTs.
12
+ - `proxyrules`: evaluates an ordered YAML rules file. The first matching rule serves a
13
+ `file:///` fixture (with the rule's optional `status` and `response_headers`),
14
+ reverse-proxies to a real service, or redirects. In record mode
15
+ (`proxyrules_record_mode`) a missing fixture is recorded from the next matching URL
16
+ rule. Rules match on path, method and `headers`/`query`/`body`/`json` predicates, and
17
+ every response is stamped with `X-Mockstack-Result` and `X-Mockstack-Rule`.
18
+
19
+ Both share `CreateMixin` for simulated creates. Settings come from pydantic-settings:
20
+ CLI flags, `MOCKSTACK__*` environment variables, or a `.env` file.
21
+
22
+ ## Layout
23
+
24
+ - `mockstack/main.py`: app factory (`create_app`) and the `mockstack` CLI entry point
25
+ - `mockstack/config.py`: `Settings`; `mockstack/constants.py`: enums, header names
26
+ - `mockstack/strategies/`: `base.py`, `filefixtures.py`, `proxyrules.py`,
27
+ `create_mixin.py`, `factory.py`
28
+ - `mockstack/rules.py`: the proxyrules `Rule`: predicates, load-time validation,
29
+ template context
30
+ - `mockstack/recording.py`: record-mode building blocks: fixture encoding that renders
31
+ back to the exact body, the recorded marker, root confinement and atomic writes
32
+ - `mockstack/templating.py`: Jinja environment and path-to-template-name resolution
33
+ - `mockstack/intent.py`, `mockstack/identifiers.py`: POST intent (search, command,
34
+ create) and path-identifier heuristics
35
+ - `mockstack/routers/`: catch-all and homepage routes
36
+ - `mockstack/tests/`: unit tests; `conftest.py` holds fixtures shared by unit and live
37
+ tests (`make_settings`, `make_request`, `write_rules`, `write_template`, `span`), and
38
+ `strategies/conftest.py` adds strategy helpers (`traced_request`,
39
+ `proxyrules_strategy`, `apply_rule`, `upstream_send`, `span_attributes`). Build settings with
40
+ `make_settings`: it ignores
41
+ `MOCKSTACK__*` environment variables and `.env` files
42
+ - `mockstack/tests/live/`: live tests against real uvicorn servers on loopback sockets;
43
+ `conftest.py` provides the session-scoped recording echo `upstream`, the module-scoped
44
+ `mockstack_server`, `proxyrules_settings` and `render_rules`; `test_record_mode_live.py`
45
+ records into temporary directories, never the repository
46
+ - `examples/`: runnable examples; `examples/proxyrules-cookbook/` holds the files
47
+ embedded in the cookbook docs page
48
+ - `docs/`: the MkDocs Material site (`mkdocs.yml`); the home page is `README.md`
49
+
50
+ ## Commands
51
+
52
+ ```bash
53
+ uv sync # install
54
+ uv run pytest -q --cov=mockstack # unit tests; live tests are deselected
55
+ uv run pytest -m slow mockstack/tests/live -v # live socket tests
56
+ uv run mypy mockstack
57
+ uvx ruff check && uvx ruff format --check
58
+ cp README.md docs/ && uvx --with mkdocs-material mkdocs build --strict
59
+ uvx pre-commit run --all-files # ruff, mypy, unit tests with coverage >= 90%
60
+ ```
61
+
62
+ mockstack requires Python 3.13 or later; CI tests 3.13 and 3.14. Ruff (line length 120)
63
+ and mypy are configured in `pyproject.toml`: production code must be fully annotated,
64
+ and a `# noqa` names its rule code with the reason on the line above. CI and pre-commit
65
+ pin ruff (0.16.7); if a newer `uvx ruff` reports findings they do not, run
66
+ `uvx ruff@0.16.7`. Coverage measures production code only, and the pre-commit pytest
67
+ hook fails below 90%.
68
+
69
+ If `VIRTUAL_ENV` points at another checkout, `unset VIRTUAL_ENV` first so `uv` uses
70
+ this project's `.venv`.
71
+
72
+ The docs build copies `README.md` to `docs/README.md` as the site's home page. That
73
+ copy is a build artifact and is gitignored: never commit it. The build is strict and
74
+ `pymdownx.snippets` has `check_paths: true`, so a broken link or a missing embedded
75
+ file fails it. CI runs the unit tests, the live tests, mypy, ruff and the docs build.
76
+
77
+ ## Conventions
78
+
79
+ - **TDD.** Write the failing test first. Unit-test logic; add a live test when the
80
+ behaviour depends on real sockets, HTTP framing or a real upstream.
81
+ - **Live tests are marked `slow`** (`pytestmark = pytest.mark.slow`). `pyproject.toml`
82
+ deselects them by default, so run them explicitly.
83
+ - **Docs examples must be backed by tests.** Cookbook recipes are real files under
84
+ `examples/proxyrules-cookbook/`, embedded in `docs/guides/proxyrules-cookbook.md` with
85
+ `--8<--`. `mockstack/tests/live/test_cookbook.py` runs every `curl` command on that
86
+ page, and checks the page embeds every recipe file and that the README's
87
+ proxyrules example matches recipe 1. Change a recipe's files, page section and test
88
+ together. `mockstack/tests/test_docs_yaml.py` checks that every YAML block in the
89
+ docs parses, and `test_docs_settings.py` that every `MOCKSTACK__*` variable in the
90
+ docs, examples and `.env.example` files names a real setting.
91
+ - **Regexes in YAML** go in plain or single-quoted scalars: a double-quoted `"\1"`
92
+ does not parse.
93
+ - **Fail at load, not per request.** Rules are validated and compiled when the
94
+ strategy is constructed. Every `proxyrules` response, including errors, carries the
95
+ result headers.
96
+ - **Keep names generic** in code, tests, docs and examples: projects service,
97
+ analytics SQL gateway, `sales_facts`, orders, users. Never use company, product or
98
+ internal service names.
99
+ - **Branches.** Pushes to `main` and to any `docs/**` branch deploy the docs site
100
+ (`.github/workflows/publish-docs.yml`), so never push a `docs/...` branch casually.
101
+ Use `feat/`, `fix/` and similar prefixes for working branches.
102
+ - **Commits.** Conventional prefixes (`feat:`, `fix:`, `docs:`, `test:`, `chore:`,
103
+ `ci:`). Stage files by explicit path. Commit trailers are added by the tool, so do
104
+ not type them by hand.
@@ -6,7 +6,8 @@ Thank you for your interest in contributing to mockstack! We welcome contributio
6
6
 
7
7
  ### Prerequisites
8
8
 
9
- - Python 3.11 or higher
9
+ - Python 3.13 or higher (CI tests 3.13 and 3.14)
10
+ - [uv](https://docs.astral.sh/uv/)
10
11
  - Git
11
12
  - A GitHub account
12
13
 
@@ -18,15 +19,16 @@ Thank you for your interest in contributing to mockstack! We welcome contributio
18
19
  git clone https://github.com/YOUR_USERNAME/mockstack.git
19
20
  cd mockstack
20
21
  ```
21
- 3. Create a virtual environment:
22
+ 3. Install the package in development mode, with its development dependencies. `uv sync`
23
+ creates the `.venv` virtual environment itself:
22
24
  ```bash
23
- uv venv
24
- source .venv/bin/activate # On Windows: venv\Scripts\activate
25
+ uv sync
25
26
  ```
26
- 4. Install the package in development mode:
27
+ Run commands in it with `uv run` (e.g. `uv run pytest`), or activate it with
28
+ `source .venv/bin/activate` (on Windows: `.venv\Scripts\activate`).
29
+ 4. Install the pre-commit hooks, which run ruff, mypy and the unit tests on every commit:
27
30
  ```bash
28
- uv sync
29
- pip install -e .
31
+ uvx pre-commit install
30
32
  ```
31
33
 
32
34
  ## How to Contribute
@@ -38,7 +40,7 @@ If you find a bug, please create an issue using our **Bug Report** template. Thi
38
40
  - A clear description of the problem
39
41
  - Steps to reproduce the issue
40
42
  - Expected vs actual behavior
41
- - Your environment details (Python version, pytest version, etc.)
43
+ - Your environment details (mockstack version, Python version, OS, etc.)
42
44
  - Any relevant code snippets or error messages
43
45
 
44
46
  ### Suggesting Features
@@ -70,7 +72,9 @@ We welcome feature suggestions! Please use our **Feature Request** template when
70
72
 
71
73
  4. **Run the test suite**:
72
74
  ```bash
73
- pytest
75
+ uv run pytest # unit tests
76
+ uv run pytest -m slow mockstack/tests/live # live tests against real servers on loopback sockets
77
+ uvx pre-commit run --all-files # ruff, mypy, and the unit tests with a 90% coverage threshold
74
78
  ```
75
79
 
76
80
  5. **Commit your changes**:
@@ -91,11 +95,11 @@ We welcome feature suggestions! Please use our **Feature Request** template when
91
95
 
92
96
  ### Code Style
93
97
 
94
- - Follow PEP 8 Python style guidelines. We use `ruff` for linting and formatting.
98
+ - Follow PEP 8 Python style guidelines. We use `ruff` for linting and formatting, with the rule families configured in `pyproject.toml` (bugbear, bandit, pyupgrade, simplify and more). CI and the pre-commit hooks pin the ruff version.
95
99
  - Use meaningful variable and function names
96
- - Write clear commit messages
97
- - Keep line length reasonable (ideally under 120 characters)
98
- - Use type hints where appropriate
100
+ - Write clear commit messages, with a conventional prefix (`feat:`, `fix:`, `docs:`, `test:`, `chore:`, `ci:`)
101
+ - Keep lines within 120 characters (enforced by `ruff`)
102
+ - Fully annotate production code: mypy runs with `disallow_untyped_defs`. Tests may leave fixture and parametrized arguments unannotated
99
103
 
100
104
  ### Testing
101
105
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Define build argument for version
4
4
  ARG PYTHON_IMAGE_VERSION=3.13-slim
5
- ARG MOCKSTACK_VERSION=0.8.0
5
+ ARG MOCKSTACK_VERSION=0.14.0
6
6
 
7
7
  # ---------------------------- Base Image --------------------------------
8
8
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mockstack
3
- Version: 0.12.1
3
+ Version: 0.14.0
4
4
  Summary: An API mocking workhorse
5
5
  Author-email: Adam Ever-Hadani <mockstack.contact@gmail.com>
6
6
  License-Expression: MIT
@@ -9,26 +9,27 @@ Project-URL: Issues, https://github.com/promptromp/mockstack/issues
9
9
  Keywords: mocking,integration-testing,testing,microservices,api
10
10
  Classifier: Development Status :: 5 - Production/Stable
11
11
  Classifier: Programming Language :: Python
12
- Classifier: Programming Language :: Python :: 3.11
13
- Classifier: Programming Language :: Python :: 3.12
14
12
  Classifier: Programming Language :: Python :: 3.13
15
- Requires-Python: >=3.11
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: Implementation :: CPython
16
+ Requires-Python: >=3.13
16
17
  Description-Content-Type: text/markdown
17
18
  License-File: LICENSE
18
19
  Requires-Dist: colorama>=0.4.6
19
- Requires-Dist: fastapi[standard]>=0.115.12
20
+ Requires-Dist: fastapi[standard]>=0.141.1
20
21
  Requires-Dist: httpx>=0.28.1
21
22
  Requires-Dist: jinja2>=3.1.6
22
- Requires-Dist: opentelemetry-distro[otlp]>=0.53b1
23
- Requires-Dist: opentelemetry-instrumentation-fastapi>=0.53b1
24
- Requires-Dist: pydantic>=2.11.3
25
- Requires-Dist: pydantic-settings>=2.9.1
26
- Requires-Dist: pyyaml>=6.0.2
27
- Requires-Dist: rich>=14.0.0
28
- Requires-Dist: typer>=0.15.2
29
- Requires-Dist: uvicorn>=0.34.2
23
+ Requires-Dist: opentelemetry-distro[otlp]>=0.65b0
24
+ Requires-Dist: opentelemetry-instrumentation-fastapi>=0.65b0
25
+ Requires-Dist: pydantic>=2.13.5
26
+ Requires-Dist: pydantic-settings>=2.15.0
27
+ Requires-Dist: pyyaml>=6.0.3
28
+ Requires-Dist: rich>=15.0.0
29
+ Requires-Dist: typer>=0.27.2
30
+ Requires-Dist: uvicorn>=0.53.0
30
31
  Provides-Extra: llm
31
- Requires-Dist: ollama>=0.4.8; extra == "llm"
32
+ Requires-Dist: ollama>=0.6.2; extra == "llm"
32
33
  Dynamic: license-file
33
34
 
34
35
  ![mockstack logo](https://github.com/promptromp/mockstack/raw/main/docs/assets/mockstack.png)
@@ -59,6 +60,11 @@ Use mockstack for:
59
60
  Highlights include:
60
61
 
61
62
  * Multiple strategies for handling requests such as [Jinja](https://jinja.palletsprojects.com/en/stable/) template files with intelligent URL request-to-template routing, proxy strategy, and mixed strategies. :game_die:
63
+ * Rule predicates for the `proxyrules` strategy: match requests on path, method, headers, query parameters and JSON body fields, then serve a fixture, reverse-proxy to a real service, or redirect. :dart:
64
+ * Dynamic replacements: a rule's replacement can be a Jinja template, so a request header can pick the fixture scenario to serve. :twisted_rightwards_arrows:
65
+ * Result headers: every `proxyrules` response is stamped with `X-Mockstack-Result` and `X-Mockstack-Rule`, so a test can assert it got a fixture and not the real service. :label:
66
+ * Fixture status codes and headers: a `proxyrules` fixture can answer with any status and extra headers, e.g. a 503 with `Retry-After`, to test how a client handles a failing dependency. :vertical_traffic_light:
67
+ * Record mode: `proxyrules` can record real responses into the fixtures its rules serve, with an optional scrubber, then replay them without the real service. :red_circle:
62
68
  * Observability via [OpenTelemetry](https://opentelemetry.io/) integration. Get detailed traces of your sessions instantly reported to backends such as [Grafana](https://grafana.com/), [Jaeger](https://www.jaegertracing.io/), [Zipkin](https://zipkin.io/), etc. :eyes:
63
69
  * Configurability via [pydantic-settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/) supports customizing behaviour via environment variables and a `.env` file. :flags:
64
70
  * Comprehensive unit-tests, linting and formatting coverage as well as vulnerabilities and security scanning with full CI automation to ensure stability and a high-quality codebase for production-grade use. :+1:
@@ -74,12 +80,13 @@ or install into a persistent environment and add it to the PATH with:
74
80
 
75
81
  uv tool install mockstack
76
82
 
83
+ mockstack requires Python 3.13 or later; `uvx` and `uv tool install` pick a compatible interpreter, downloading one if needed.
77
84
 
78
85
  ## Usage
79
86
 
80
87
  See the [examples](https://github.com/promptromp/mockstack/blob/main/examples/) directory for complete examples with documentation.
81
88
 
82
- Available configuration options are [here](https://github.com/promptromp/mockstack/blob/main/mockstack/config.py).
89
+ Available configuration options are described in the [Configuration](https://promptromp.github.io/mockstack/configuration/) reference, and defined [here](https://github.com/promptromp/mockstack/blob/main/mockstack/config.py).
83
90
 
84
91
  Setting individual options can be done either through an `.env` file, individual environment variables, or command-line arguments.
85
92
 
@@ -103,37 +110,84 @@ See also the included [.env.example](https://github.com/promptromp/mockstack/blo
103
110
  Out of the box, you get the following behavior when using the default `filefixtures` strategy:
104
111
 
105
112
  - The HTTP request `GET /someservice/api/v1/user/c27f5b2b-6e81-420d-a4e4-6426e1c32db8` will try to find `<templates_dir>/someservice-api-v1-user.c27f5b2b-6e81-420d-a4e4-6426e1c32db8.j2`,
106
- and will fallback to `<templates_dir>/someservice-api-v1-user.j2` (and finally to `index.j2` if exists). These are j2 files that have access to request body context variables.
107
- - The HTTP request `POST /someservice/api/v2/item` with a JSON body will attempt to intelligently simulate the creation of a resource, returning the appropriate status code and will echo back the provided request resource, after injecting additional metadata fields based on strategy configuration. This is useful for services that expect fields such as `id` and `created_at` on returned created resources.
108
- - HTTP requests for `DELETE` / `PUT` / `PATCH` are a no-op by default, simply returning the appropriate status code.
109
- - The HTTP request `POST /someservice/api/v2/embedding_search` will be handled as a search request rather than a resource creation, returning an appropriate http status code and mock results based on user-configurable formatting.
113
+ and will fallback to `<templates_dir>/someservice-api-v1-user.j2` (and finally to `index.j2` if exists). These are j2 files that have access to request context variables (query parameters, headers, the JSON body and the identifiers in the path).
114
+ - The HTTP request `POST /someservice/api/v2/item` with a JSON body will attempt to intelligently simulate the creation of a resource, returning the appropriate status code and will echo back the provided request resource, after injecting additional metadata fields based on strategy configuration. This is useful for services that expect fields such as `id` and `created_at` on returned created resources. Templates are tried first, so a template matching the path (`index.j2` included) answers the POST instead, unless `filefixtures_enable_templates_for_post=false`. This fallback can be turned off with `filefixtures_simulate_create_on_missing=false`, in which case a create-looking POST with no matching template gets a 404 instead.
115
+ - HTTP requests for `DELETE` / `PUT` / `PATCH` are a no-op by default, simply returning the appropriate status code (204). `HEAD` and `OPTIONS` requests are answered 405.
116
+ - The HTTP request `POST /someservice/api/v2/embedding_search` will be handled as a search request rather than a resource creation: it is answered from its template (`someservice-api-v2-embedding_search.j2`), or with a 404 when there is none.
110
117
 
111
118
  Overall, the design philosophy is that things "just work". The framework attempts to intelligently deduce the intent of the request as much as possible and act accordingly,
112
119
  while leaving room for advanced users to go in and customize behavior using the configuration options.
113
120
 
121
+ ### Mix fixtures and real services
122
+
123
+ With the `proxyrules` strategy, one mockstack instance can serve fixtures to test traffic and pass everything else through to the real service. Rules are tried in order and the first match wins:
124
+
125
+ ```yaml
126
+ rules:
127
+ - name: projects-fixture
128
+ method: GET
129
+ pattern: ^/projects/api/v1/project/(?P<id>[a-z0-9-]+)$
130
+ headers:
131
+ x-test-run: ".+"
132
+ replacement: file://${FIXTURES_DIR}/projects/project.json.j2
133
+
134
+ - name: projects-passthrough
135
+ pattern: ^/projects/(.*)
136
+ replacement: ${UPSTREAM_URL}/\1
137
+ ```
138
+
139
+ Fill in the `${FIXTURES_DIR}` and `${UPSTREAM_URL}` placeholders (for example with `envsubst`), then start mockstack with `MOCKSTACK__STRATEGY=proxyrules` and `MOCKSTACK__PROXYRULES_RULES_FILENAME` pointing at the result. A request tagged with `X-Test-Run` is served from the fixture (`X-Mockstack-Result: template`); the untagged one is reverse-proxied to the real service (`X-Mockstack-Result: proxy`):
140
+
141
+ ```shell
142
+ curl -i -H "X-Test-Run: ci-42" http://127.0.0.1:8000/projects/api/v1/project/proj-123
143
+ curl -i http://127.0.0.1:8000/projects/api/v1/project/proj-123
144
+ ```
145
+
146
+ The [ProxyRules cookbook](https://promptromp.github.io/mockstack/guides/proxyrules-cookbook/) walks through this recipe and more (per-scenario fixtures, matching on request bodies and query parameters, asserting in tests, error responses, recording fixtures), each backed by a live test.
147
+
148
+ ### Record fixtures from a real service
149
+
150
+ Instead of writing fixtures by hand, record them: with record mode on, a fixture rule whose file does not exist yet sends the request on to the next matching URL rule, saves the response into the fixture file, and serves it from there. Later requests are replayed from the file without calling the service. Record mode is off by default:
151
+
152
+ ```shell
153
+ MOCKSTACK__STRATEGY=proxyrules MOCKSTACK__PROXYRULES_RULES_FILENAME=rules.yml \
154
+ MOCKSTACK__PROXYRULES_RECORD_MODE=missing MOCKSTACK__PROXYRULES_RECORD_ROOT=fixtures \
155
+ uv run mockstack
156
+ ```
157
+
158
+ Requests really reach the service until their response is recorded, so record against a safe environment and review the recorded files before committing them. An optional scrubber can mask sensitive data first; see [Recording fixtures](https://promptromp.github.io/mockstack/strategies/proxyrules/#recording-fixtures) and the cookbook's [Record fixtures from a real service](https://promptromp.github.io/mockstack/guides/proxyrules-cookbook/#9-record-fixtures-from-a-real-service).
114
159
 
115
160
  ## Testing
116
161
 
117
162
  Invoke unit-tests with:
118
163
 
119
- uv run python -m pytest
164
+ uv run pytest
120
165
 
121
- Linting, formatting, static type checks etc. are all managed via [pre-commit](https://pre-commit.com/) hooks. These will run automatically on every commit. You can invoke these manually on all files with:
166
+ Live tests start real mockstack and upstream servers on loopback sockets, including one that runs every example on the ProxyRules cookbook page. They are marked `slow` and deselected by default; run them with:
122
167
 
123
- pre-commit run --all-files
168
+ uv run pytest -m slow mockstack/tests/live
169
+
170
+ Linting, formatting, static type checks and the unit tests (with a 90% coverage threshold) are all managed via [pre-commit](https://pre-commit.com/) hooks. Install them once and they will run automatically on every commit:
171
+
172
+ uvx pre-commit install
173
+
174
+ You can invoke these manually on all files with:
175
+
176
+ uvx pre-commit run --all-files
124
177
 
125
178
 
126
179
  ## Contributing
127
180
 
128
- If you are contributing to development, you will want to clone this project, and can then install it locally with:
181
+ If you are contributing to development, you will want to clone this project, and can then install it locally (`uv sync` installs the project in editable mode, together with its development dependencies) with:
129
182
 
130
183
  gh repo clone promptromp/mockstack
131
184
  cd mockstack/
132
185
  uv sync
133
- uv pip install -e .
134
186
 
135
187
  Run in development mode (for live-reload of changes when developing):
136
188
 
137
189
  uv run uvicorn --factory mockstack.main:create_app --reload
138
190
 
139
191
  Note that when you run using the uvicorn CLI, you will need to set any configuration via `.env` file or environment variables.
192
+
193
+ See [CONTRIBUTING.md](https://github.com/promptromp/mockstack/blob/main/CONTRIBUTING.md) for the full development workflow.