modelrack 0.5.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 (104) hide show
  1. modelrack-0.5.0/.editorconfig +23 -0
  2. modelrack-0.5.0/.github/workflows/ci.yml +139 -0
  3. modelrack-0.5.0/.github/workflows/nightly.yml +50 -0
  4. modelrack-0.5.0/.github/workflows/release.yml +57 -0
  5. modelrack-0.5.0/.gitignore +100 -0
  6. modelrack-0.5.0/.importlinter +27 -0
  7. modelrack-0.5.0/.pre-commit-config.yaml +22 -0
  8. modelrack-0.5.0/CHANGELOG.md +530 -0
  9. modelrack-0.5.0/CONTRIBUTING.md +50 -0
  10. modelrack-0.5.0/LICENSE +201 -0
  11. modelrack-0.5.0/PKG-INFO +321 -0
  12. modelrack-0.5.0/README.md +291 -0
  13. modelrack-0.5.0/SECURITY.md +39 -0
  14. modelrack-0.5.0/docs/README.md +10 -0
  15. modelrack-0.5.0/docs/packages/modelrack/development-plan.md +248 -0
  16. modelrack-0.5.0/docs/packages/modelrack/spec.md +286 -0
  17. modelrack-0.5.0/docs/providers.md +48 -0
  18. modelrack-0.5.0/docs/quickstart.md +217 -0
  19. modelrack-0.5.0/pyproject.toml +101 -0
  20. modelrack-0.5.0/requirements/README.md +55 -0
  21. modelrack-0.5.0/requirements/ci.lock +536 -0
  22. modelrack-0.5.0/requirements/release.in +6 -0
  23. modelrack-0.5.0/requirements/release.lock +493 -0
  24. modelrack-0.5.0/scripts/generate_provider_matrix.py +143 -0
  25. modelrack-0.5.0/src/modelrack/__about__.py +3 -0
  26. modelrack-0.5.0/src/modelrack/__init__.py +169 -0
  27. modelrack-0.5.0/src/modelrack/cache.py +309 -0
  28. modelrack-0.5.0/src/modelrack/errors.py +213 -0
  29. modelrack-0.5.0/src/modelrack/events.py +299 -0
  30. modelrack-0.5.0/src/modelrack/provider.py +468 -0
  31. modelrack-0.5.0/src/modelrack/providers/__init__.py +13 -0
  32. modelrack-0.5.0/src/modelrack/providers/_fake_errors.py +173 -0
  33. modelrack-0.5.0/src/modelrack/providers/_fake_generation.py +423 -0
  34. modelrack-0.5.0/src/modelrack/providers/_fake_script.py +764 -0
  35. modelrack-0.5.0/src/modelrack/providers/_http.py +341 -0
  36. modelrack-0.5.0/src/modelrack/providers/_ollama_wire.py +471 -0
  37. modelrack-0.5.0/src/modelrack/providers/fake.py +1180 -0
  38. modelrack-0.5.0/src/modelrack/providers/ollama.py +1417 -0
  39. modelrack-0.5.0/src/modelrack/providers/openai_compatible.py +1351 -0
  40. modelrack-0.5.0/src/modelrack/py.typed +0 -0
  41. modelrack-0.5.0/src/modelrack/residency.py +215 -0
  42. modelrack-0.5.0/src/modelrack/streaming.py +264 -0
  43. modelrack-0.5.0/src/modelrack/testing.py +57 -0
  44. modelrack-0.5.0/src/modelrack/types.py +636 -0
  45. modelrack-0.5.0/tests/conftest.py +148 -0
  46. modelrack-0.5.0/tests/contract/test_conformance.py +700 -0
  47. modelrack-0.5.0/tests/fixtures/providers/ollama/chat_complete.json +16 -0
  48. modelrack-0.5.0/tests/fixtures/providers/ollama/chat_stream.ndjson +5 -0
  49. modelrack-0.5.0/tests/fixtures/providers/ollama/error_bad_option.json +1 -0
  50. modelrack-0.5.0/tests/fixtures/providers/ollama/error_context_overflow.json +1 -0
  51. modelrack-0.5.0/tests/fixtures/providers/ollama/error_model_not_found.json +1 -0
  52. modelrack-0.5.0/tests/fixtures/providers/ollama/error_runner_stopped.json +1 -0
  53. modelrack-0.5.0/tests/fixtures/providers/ollama/generate_load.json +9 -0
  54. modelrack-0.5.0/tests/fixtures/providers/ollama/generate_unload.json +7 -0
  55. modelrack-0.5.0/tests/fixtures/providers/ollama/manifest.json +6 -0
  56. modelrack-0.5.0/tests/fixtures/providers/ollama/ps_empty.json +1 -0
  57. modelrack-0.5.0/tests/fixtures/providers/ollama/ps_resident.json +22 -0
  58. modelrack-0.5.0/tests/fixtures/providers/ollama/show_llama.json +27 -0
  59. modelrack-0.5.0/tests/fixtures/providers/ollama/show_minimal.json +18 -0
  60. modelrack-0.5.0/tests/fixtures/providers/ollama/show_qwen.json +32 -0
  61. modelrack-0.5.0/tests/fixtures/providers/ollama/tags.json +38 -0
  62. modelrack-0.5.0/tests/fixtures/providers/ollama/tags_empty.json +1 -0
  63. modelrack-0.5.0/tests/fixtures/providers/ollama/version.json +1 -0
  64. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/.gitkeep +0 -0
  65. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/chat_complete.json +21 -0
  66. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/chat_complete_array.json +1 -0
  67. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/chat_complete_error_200.json +1 -0
  68. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/chat_complete_tool_calls.json +31 -0
  69. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/chat_complete_tool_calls_malformed.json +31 -0
  70. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/chat_stream.sse +16 -0
  71. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/chat_stream_field_variety.sse +5 -0
  72. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/chat_stream_inband_error.sse +6 -0
  73. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/chat_stream_malformed.sse +4 -0
  74. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/chat_stream_multiline.sse +26 -0
  75. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/chat_stream_no_finish_reason.sse +4 -0
  76. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/chat_stream_non_object.sse +6 -0
  77. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/chat_stream_tool_call_no_index.sse +6 -0
  78. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/chat_stream_tool_calls.sse +14 -0
  79. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/chat_stream_tool_calls_stray_fragment.sse +10 -0
  80. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/chat_stream_truncated.sse +6 -0
  81. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/error_bad_request.json +7 -0
  82. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/error_context_overflow.json +7 -0
  83. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/error_context_overflow_no_code.json +3 -0
  84. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/error_model_not_found.json +7 -0
  85. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/manifest.json +7 -0
  86. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/models.json +17 -0
  87. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/models_empty.json +4 -0
  88. modelrack-0.5.0/tests/fixtures/providers/openai_compatible/models_malformed.json +1 -0
  89. modelrack-0.5.0/tests/live/test_ollama_live.py +286 -0
  90. modelrack-0.5.0/tests/performance/test_overhead.py +270 -0
  91. modelrack-0.5.0/tests/unit/test_cache.py +513 -0
  92. modelrack-0.5.0/tests/unit/test_cancellation.py +477 -0
  93. modelrack-0.5.0/tests/unit/test_errors.py +166 -0
  94. modelrack-0.5.0/tests/unit/test_events.py +714 -0
  95. modelrack-0.5.0/tests/unit/test_fake_provider.py +1871 -0
  96. modelrack-0.5.0/tests/unit/test_http_transport.py +266 -0
  97. modelrack-0.5.0/tests/unit/test_ollama_adapter.py +1838 -0
  98. modelrack-0.5.0/tests/unit/test_openai_compatible_adapter.py +1245 -0
  99. modelrack-0.5.0/tests/unit/test_provider.py +299 -0
  100. modelrack-0.5.0/tests/unit/test_provider_matrix.py +101 -0
  101. modelrack-0.5.0/tests/unit/test_residency.py +361 -0
  102. modelrack-0.5.0/tests/unit/test_stream_memory.py +247 -0
  103. modelrack-0.5.0/tests/unit/test_streaming_types.py +195 -0
  104. modelrack-0.5.0/tests/unit/test_types.py +442 -0
@@ -0,0 +1,23 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ insert_final_newline = true
7
+ trim_trailing_whitespace = true
8
+ indent_style = space
9
+ indent_size = 4
10
+
11
+ [*.py]
12
+ indent_size = 4
13
+ max_line_length = 100
14
+
15
+ [*.{toml,yml,yaml,json}]
16
+ indent_size = 2
17
+
18
+ [*.md]
19
+ trim_trailing_whitespace = false
20
+ max_line_length = off
21
+
22
+ [Makefile]
23
+ indent_style = tab
@@ -0,0 +1,139 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ format:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with: { python-version: "3.12" }
15
+ # The locked ruff, not whatever released this morning: formatting changes between ruff
16
+ # versions, and an unpinned job turns that into a red build with no commit behind it.
17
+ - run: pip install --require-hashes -r requirements/ci.lock
18
+ - run: ruff format --check .
19
+
20
+ lint:
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ - uses: actions/setup-python@v5
25
+ with: { python-version: "3.12" }
26
+ - run: pip install --require-hashes -r requirements/ci.lock
27
+ - run: ruff check .
28
+
29
+ types:
30
+ runs-on: ubuntu-latest
31
+ steps:
32
+ - uses: actions/checkout@v4
33
+ - uses: actions/setup-python@v5
34
+ with: { python-version: "3.12" }
35
+ - run: pip install --require-hashes -r requirements/ci.lock
36
+ - run: pip install . --no-deps
37
+ - run: mypy src tests
38
+
39
+ boundaries:
40
+ runs-on: ubuntu-latest
41
+ steps:
42
+ - uses: actions/checkout@v4
43
+ - uses: actions/setup-python@v5
44
+ with: { python-version: "3.12" }
45
+ - run: pip install --require-hashes -r requirements/ci.lock
46
+ - run: pip install . --no-deps
47
+ - run: lint-imports
48
+
49
+ tests:
50
+ runs-on: ubuntu-latest
51
+ strategy:
52
+ matrix:
53
+ python-version: ["3.12", "3.13"]
54
+ steps:
55
+ - uses: actions/checkout@v4
56
+ - uses: actions/setup-python@v5
57
+ with: { python-version: "${{ matrix.python-version }}" }
58
+ - run: pip install --require-hashes -r requirements/ci.lock
59
+ - run: pip install . --no-deps
60
+ - run: pytest -m "not live and not performance" --cov --cov-report=xml
61
+
62
+ tests-314-early-warning:
63
+ runs-on: ubuntu-latest
64
+ continue-on-error: true
65
+ steps:
66
+ - uses: actions/checkout@v4
67
+ - uses: actions/setup-python@v5
68
+ with: { python-version: "3.14" }
69
+ # Deliberately unpinned: ci.lock is resolved on 3.13, and pinning a version that has no
70
+ # 3.14 wheels would defeat the purpose of an early warning. This job asks whether the
71
+ # ranges in pyproject.toml still resolve and pass on the next interpreter.
72
+ - run: pip install -e ".[dev]"
73
+ - run: pytest -m "not live and not performance"
74
+
75
+ coverage:
76
+ needs: [tests]
77
+ runs-on: ubuntu-latest
78
+ steps:
79
+ - uses: actions/checkout@v4
80
+ - uses: actions/setup-python@v5
81
+ with: { python-version: "3.12" }
82
+ - run: pip install --require-hashes -r requirements/ci.lock
83
+ - run: pip install . --no-deps
84
+ - run: pytest -m "not live and not performance" --cov --cov-report=term-missing --cov-fail-under=95
85
+
86
+ contracts:
87
+ runs-on: ubuntu-latest
88
+ steps:
89
+ - uses: actions/checkout@v4
90
+ - uses: actions/setup-python@v5
91
+ with: { python-version: "3.12" }
92
+ - run: pip install --require-hashes -r requirements/ci.lock
93
+ - run: pip install . --no-deps
94
+ - run: pytest -m contract
95
+
96
+ security:
97
+ runs-on: ubuntu-latest
98
+ steps:
99
+ - uses: actions/checkout@v4
100
+ # gitleaks scans *history*, and `actions/checkout` fetches a single commit by default.
101
+ # For a push it is handed `<first-pushed>^..<last-pushed>`, so the parent of the first
102
+ # pushed commit has to be in the object store; in a depth-1 clone it is not, and git
103
+ # answers "unknown revision", which the action reports as exit code 1. It fails the same
104
+ # way whether or not a secret exists, so a green run would not have meant anything either.
105
+ with: { fetch-depth: 0 }
106
+ - uses: actions/setup-python@v5
107
+ with: { python-version: "3.12" }
108
+ - run: pip install pip-audit
109
+ # Audit the locked sets, not the job's own environment: a bare `pip-audit` here would
110
+ # inspect an environment containing only pip-audit itself (Security Standards §11).
111
+ - run: pip-audit --require-hashes -r requirements/ci.lock
112
+ - run: pip-audit --require-hashes -r requirements/release.lock
113
+ - uses: gitleaks/gitleaks-action@v2
114
+ env:
115
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
116
+
117
+ build:
118
+ runs-on: ubuntu-latest
119
+ steps:
120
+ - uses: actions/checkout@v4
121
+ - uses: actions/setup-python@v5
122
+ with: { python-version: "3.12" }
123
+ - run: pip install --require-hashes -r requirements/release.lock
124
+ - run: python -m build --no-isolation
125
+ - run: twine check dist/*
126
+ - uses: actions/upload-artifact@v4
127
+ with: { name: dist, path: dist/ }
128
+
129
+ install-check:
130
+ needs: [build]
131
+ runs-on: ubuntu-latest
132
+ steps:
133
+ - uses: actions/checkout@v4
134
+ - uses: actions/setup-python@v5
135
+ with: { python-version: "3.12" }
136
+ - uses: actions/download-artifact@v4
137
+ with: { name: dist, path: dist/ }
138
+ - run: pip install dist/*.whl
139
+ - run: python -c "import modelrack"
@@ -0,0 +1,50 @@
1
+ name: Nightly
2
+
3
+ # The two suites the default gate deliberately excludes (testing standards §10), for the two
4
+ # different reasons a suite can be excluded for: `performance` asserts wall-clock budgets, which a
5
+ # shared runner under PR load distorts, and `live` needs a real Ollama that no hosted runner has.
6
+ # Both are real coverage, so they run on a schedule rather than not at all — a marked test that
7
+ # never runs anywhere is an untested behaviour with a green tick beside it.
8
+ #
9
+ # What is *not* here is as deliberate. Spec §15's per-stream memory budget is a performance budget
10
+ # by subject but a deterministic assertion by method, so it runs on every push from
11
+ # `tests/unit/test_stream_memory.py` — it caught a real regression, and nightly is the wrong
12
+ # cadence for a test that can catch one in the pull request that introduced it.
13
+
14
+ on:
15
+ schedule:
16
+ # 04:00 UTC, off the busiest window for GitHub's shared runners.
17
+ - cron: "0 4 * * *"
18
+ workflow_dispatch:
19
+
20
+ jobs:
21
+ performance:
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ - uses: actions/setup-python@v5
26
+ with: { python-version: "3.12" }
27
+ - run: pip install --require-hashes -r requirements/ci.lock
28
+ - run: pip install . --no-deps
29
+ # Spec §15's timing budgets, measured against a transport that does no I/O, so what the
30
+ # clock sees is this package's own work rather than a provider's.
31
+ - run: pytest -m performance -p no:randomly
32
+
33
+ live:
34
+ # No hosted runner has an Ollama, so this needs a self-hosted machine with one. Until the
35
+ # suite has that machine, the job is present and disabled rather than absent: the command it
36
+ # would run is the thing worth keeping under review.
37
+ if: false
38
+ runs-on: [self-hosted, ollama]
39
+ steps:
40
+ - uses: actions/checkout@v4
41
+ - uses: actions/setup-python@v5
42
+ with: { python-version: "3.12" }
43
+ - run: pip install --require-hashes -r requirements/ci.lock
44
+ - run: pip install . --no-deps
45
+ # MODELRACK_REQUIRE_OLLAMA=1 turns an unreachable provider from a skip into a failure: a
46
+ # silently skipped provider is an untested provider, and a nightly hardware job is exactly
47
+ # where that must not be allowed to hide.
48
+ - run: pytest -m live -p no:randomly
49
+ env:
50
+ MODELRACK_REQUIRE_OLLAMA: "1"
@@ -0,0 +1,57 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*.*.*"]
6
+ workflow_dispatch: # manual TestPyPI dry run; see publish-testpypi below
7
+
8
+ permissions:
9
+ id-token: write # required for PyPI Trusted Publishing
10
+ contents: write # required to create the GitHub release
11
+
12
+ jobs:
13
+ release:
14
+ # Tag pushes only. Without this, clicking "Run workflow" for the TestPyPI dry run below would
15
+ # also fire this job and publish to real PyPI — the exact opposite of a dry run.
16
+ if: github.event_name == 'push'
17
+ runs-on: ubuntu-latest
18
+ environment: pypi # must match the Environment name set on the PyPI trusted publisher
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - uses: actions/setup-python@v5
22
+ with: { python-version: "3.12" }
23
+ # Byte-for-byte the dry run's build chain below. A real release that resolved `build` and
24
+ # `hatchling` fresh from PyPI would not be the artifact the dry run proved.
25
+ - run: pip install --require-hashes -r requirements/release.lock
26
+ - run: python -m build --no-isolation
27
+ - run: twine check dist/*
28
+ - run: pip install "dist/$(ls dist | grep .whl)[dev]"
29
+ - run: pytest -m "not live and not performance"
30
+ - name: Publish to PyPI
31
+ uses: pypa/gh-action-pypi-publish@release/v1
32
+ - name: Create GitHub release
33
+ uses: softprops/action-gh-release@v2
34
+ with:
35
+ generate_release_notes: true
36
+ files: dist/*
37
+
38
+ publish-testpypi:
39
+ # Manual only, via Actions -> Release -> Run workflow. Packaging and Release Standards §6
40
+ # requires a successful TestPyPI publish ahead of a package's first real release; 0.5.0 is
41
+ # this package's first published version, so run this once before tagging v0.5.0. Later
42
+ # releases may skip it, or use it again as a dry run.
43
+ if: github.event_name == 'workflow_dispatch'
44
+ runs-on: ubuntu-latest
45
+ steps:
46
+ - uses: actions/checkout@v4
47
+ - uses: actions/setup-python@v5
48
+ with: { python-version: "3.12" }
49
+ - run: pip install --require-hashes -r requirements/release.lock
50
+ - run: python -m build --no-isolation
51
+ - run: twine check dist/*
52
+ - run: pip install "dist/$(ls dist | grep .whl)[dev]"
53
+ - run: pytest -m "not live and not performance"
54
+ - name: Publish to TestPyPI
55
+ uses: pypa/gh-action-pypi-publish@release/v1
56
+ with:
57
+ repository-url: https://test.pypi.org/legacy/
@@ -0,0 +1,100 @@
1
+ # ---- Python ----
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+ MANIFEST
23
+
24
+ # ---- Packaging / build backends ----
25
+ pip-wheel-metadata/
26
+ share/python-wheels/
27
+
28
+ # ---- Testing / coverage ----
29
+ .pytest_cache/
30
+ .cache
31
+ .coverage
32
+ .coverage.*
33
+ coverage.xml
34
+ *.cover
35
+ *.py,cover
36
+ htmlcov/
37
+ nosetests.xml
38
+ .hypothesis/
39
+
40
+ # ---- Type checking / linting ----
41
+ .mypy_cache/
42
+ .dmypy.json
43
+ dmypy.json
44
+ .ruff_cache/
45
+ .pytype/
46
+
47
+ # ---- Virtual environments ----
48
+ .venv/
49
+ venv/
50
+ ENV/
51
+ env/
52
+ env.bak/
53
+ venv.bak/
54
+ .python-version
55
+
56
+ # ---- Distribution / dependency locking ----
57
+ # requirements/*.lock is deliberately NOT ignored. The lock files are committed
58
+ # inputs: CI and release jobs install from them with --require-hashes (Packaging
59
+ # and Release Standards §4, Security Standards §11), so an ignored lock file
60
+ # means a checkout that cannot build.
61
+
62
+ # ---- Editors / OS ----
63
+ .vscode/
64
+ .idea/
65
+ *.swp
66
+ *.swo
67
+ .DS_Store
68
+ Thumbs.db
69
+
70
+ # ---- Suite runtime state (this component's local data) ----
71
+ # The application writes to XDG paths at runtime (~/.config, ~/.local/share,
72
+ # ~/.local/state per Master Architecture §1.2), never inside the repository.
73
+ # These entries only guard against a developer pointing XDG_* at the repo
74
+ # during local testing.
75
+ .local/
76
+ .config/
77
+ *.sqlite3
78
+ *.sqlite3-journal
79
+ *.sqlite3-wal
80
+ *.sqlite3-shm
81
+ /data/
82
+ /logs/
83
+ /backups/
84
+ /artifacts/
85
+ /exports/
86
+
87
+ # ---- Secrets ----
88
+ # Per Security Standards §8: secrets are never committed. Config files may
89
+ # only name where a secret comes from (*_env / *_file), never the value.
90
+ .env
91
+ .env.*
92
+ *.key
93
+ *.pem
94
+ secrets.toml
95
+
96
+ # ---- Node-free JS assets (MirrorWall consumers may still use a local tool) ----
97
+ node_modules/
98
+
99
+ # ---- Build artifacts from docs generation ----
100
+ docs/api/openapi-v1.json.tmp
@@ -0,0 +1,27 @@
1
+ [importlinter]
2
+ root_packages =
3
+ modelrack
4
+ # The forbidden modules below are external distributions, not submodules of modelrack, so the
5
+ # graph has to include external packages for the contracts to be able to see them at all.
6
+ include_external_packages = True
7
+
8
+ [importlinter:contract:no-application-imports]
9
+ name = ModelRack must not import applications
10
+ type = forbidden
11
+ source_modules =
12
+ modelrack
13
+ forbidden_modules =
14
+ freeweight
15
+ loadcoach
16
+ ideapress
17
+
18
+ [importlinter:contract:no-sibling-packages]
19
+ name = ModelRack must not import sibling suite packages
20
+ type = forbidden
21
+ source_modules =
22
+ modelrack
23
+ forbidden_modules =
24
+ setspec
25
+ sweatmeter
26
+ weightsdb
27
+ mirrorwall
@@ -0,0 +1,22 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.6.9
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
8
+ - repo: https://github.com/pre-commit/pre-commit-hooks
9
+ rev: v4.6.0
10
+ hooks:
11
+ - id: trailing-whitespace
12
+ - id: end-of-file-fixer
13
+ - id: check-toml
14
+ - id: check-json
15
+ - id: check-added-large-files
16
+ - id: check-merge-conflict
17
+ - id: mixed-line-ending
18
+ args: [--fix=lf]
19
+ - repo: https://github.com/gitleaks/gitleaks
20
+ rev: v8.18.4
21
+ hooks:
22
+ - id: gitleaks