localqueue 1.1.0__tar.gz → 1.1.2__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 (60) hide show
  1. localqueue-1.1.2/.github/workflows/ci.yml +245 -0
  2. localqueue-1.1.2/.github/workflows/docs.yml +68 -0
  3. localqueue-1.1.2/.github/workflows/release.yml +104 -0
  4. {localqueue-1.1.0 → localqueue-1.1.2}/.github/workflows/stress.yml +3 -3
  5. localqueue-1.1.2/.github/workflows/wheels.yml +298 -0
  6. {localqueue-1.1.0 → localqueue-1.1.2}/.gitignore +5 -0
  7. localqueue-1.1.2/.pre-commit-config.yaml +31 -0
  8. {localqueue-1.1.0 → localqueue-1.1.2}/CHANGELOG.md +51 -0
  9. {localqueue-1.1.0 → localqueue-1.1.2}/Cargo.lock +1 -1
  10. {localqueue-1.1.0 → localqueue-1.1.2}/Cargo.toml +1 -1
  11. {localqueue-1.1.0 → localqueue-1.1.2}/PKG-INFO +31 -10
  12. {localqueue-1.1.0 → localqueue-1.1.2}/README.md +22 -8
  13. {localqueue-1.1.0 → localqueue-1.1.2}/benchmarks/queue_bench.py +10 -7
  14. localqueue-1.1.2/deny.toml +19 -0
  15. localqueue-1.1.2/docs/getting-started.md +75 -0
  16. localqueue-1.1.2/docs/index.md +52 -0
  17. {localqueue-1.1.0 → localqueue-1.1.2}/docs/internal/initial_idea.md +0 -1
  18. {localqueue-1.1.0 → localqueue-1.1.2}/pyproject.toml +46 -2
  19. {localqueue-1.1.0 → localqueue-1.1.2}/python/localqueue/bus/bus.py +2 -3
  20. {localqueue-1.1.0 → localqueue-1.1.2}/python/localqueue/bus/topology.py +2 -5
  21. localqueue-1.1.2/scripts/check_release_version.py +56 -0
  22. {localqueue-1.1.0 → localqueue-1.1.2}/stress/run_soak.py +4 -4
  23. localqueue-1.1.2/tasks/plan.md +663 -0
  24. localqueue-1.1.2/tasks/todo.md +101 -0
  25. {localqueue-1.1.0 → localqueue-1.1.2}/tests/test_batch.py +2 -7
  26. {localqueue-1.1.0 → localqueue-1.1.2}/tests/test_bus.py +24 -30
  27. {localqueue-1.1.0 → localqueue-1.1.2}/tests/test_bus_static_topology.py +9 -28
  28. {localqueue-1.1.0 → localqueue-1.1.2}/tests/test_bus_topology.py +0 -1
  29. {localqueue-1.1.0 → localqueue-1.1.2}/tests/test_concurrency.py +0 -1
  30. {localqueue-1.1.0 → localqueue-1.1.2}/tests/test_contract.py +3 -7
  31. {localqueue-1.1.0 → localqueue-1.1.2}/tests/test_core.py +1 -2
  32. {localqueue-1.1.0 → localqueue-1.1.2}/tests/test_maintenance.py +0 -1
  33. {localqueue-1.1.0 → localqueue-1.1.2}/tests/test_worker.py +0 -3
  34. localqueue-1.1.2/uv.lock +1253 -0
  35. localqueue-1.1.2/zensical.toml +30 -0
  36. localqueue-1.1.0/.github/workflows/ci.yml +0 -140
  37. localqueue-1.1.0/.github/workflows/wheels.yml +0 -173
  38. {localqueue-1.1.0 → localqueue-1.1.2}/LICENSE +0 -0
  39. {localqueue-1.1.0 → localqueue-1.1.2}/benchmarks/README.md +0 -0
  40. {localqueue-1.1.0 → localqueue-1.1.2}/docs/event-bus.md +0 -0
  41. {localqueue-1.1.0 → localqueue-1.1.2}/docs/guarantees.md +0 -0
  42. {localqueue-1.1.0 → localqueue-1.1.2}/examples/basic.py +0 -0
  43. {localqueue-1.1.0 → localqueue-1.1.2}/python/localqueue/__init__.py +0 -0
  44. {localqueue-1.1.0 → localqueue-1.1.2}/python/localqueue/bus/__init__.py +0 -0
  45. {localqueue-1.1.0 → localqueue-1.1.2}/python/localqueue/bus/consumer.py +0 -0
  46. {localqueue-1.1.0 → localqueue-1.1.2}/python/localqueue/bus/event.py +0 -0
  47. {localqueue-1.1.0 → localqueue-1.1.2}/python/localqueue/bus/registry.py +0 -0
  48. {localqueue-1.1.0 → localqueue-1.1.2}/python/localqueue/bus/subscription.py +0 -0
  49. {localqueue-1.1.0 → localqueue-1.1.2}/python/localqueue/core.py +0 -0
  50. {localqueue-1.1.0 → localqueue-1.1.2}/python/localqueue/exceptions.py +0 -0
  51. {localqueue-1.1.0 → localqueue-1.1.2}/python/localqueue/job.py +0 -0
  52. {localqueue-1.1.0 → localqueue-1.1.2}/python/localqueue/localqueue.pyi +0 -0
  53. {localqueue-1.1.0 → localqueue-1.1.2}/python/localqueue/worker.py +0 -0
  54. {localqueue-1.1.0 → localqueue-1.1.2}/src/error.rs +0 -0
  55. {localqueue-1.1.0 → localqueue-1.1.2}/src/lib.rs +0 -0
  56. {localqueue-1.1.0 → localqueue-1.1.2}/src/queue.rs +0 -0
  57. {localqueue-1.1.0 → localqueue-1.1.2}/src/schema.rs +0 -0
  58. {localqueue-1.1.0 → localqueue-1.1.2}/src/storage.rs +0 -0
  59. {localqueue-1.1.0 → localqueue-1.1.2}/tests/__init__.py +0 -0
  60. {localqueue-1.1.0 → localqueue-1.1.2}/tests/test_gil.py +0 -0
@@ -0,0 +1,245 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [main]
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ concurrency:
13
+ group: ci-${{ github.workflow }}-${{ github.ref }}
14
+ cancel-in-progress: true
15
+
16
+ jobs:
17
+ python-quality:
18
+ name: Python lint and types
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - name: Check out repository
22
+ uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
23
+
24
+ - name: Set up Python
25
+ uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
26
+ with:
27
+ python-version: '3.14'
28
+ cache: pip
29
+
30
+ - name: Install Python quality tools
31
+ run: |
32
+ python -m pip install --upgrade \
33
+ "pydantic>=2,<3" \
34
+ "ruff>=0.15,<1" \
35
+ "pyrefly>=1.1,<2"
36
+
37
+ - name: Run Ruff
38
+ run: |
39
+ ruff check .
40
+ ruff format --check .
41
+
42
+ - name: Run Pyrefly
43
+ env:
44
+ PYTHONPATH: python
45
+ run: pyrefly check --preset default --progress-bar no python/localqueue
46
+
47
+ secrets:
48
+ name: Secret scan
49
+ runs-on: ubuntu-latest
50
+ steps:
51
+ - name: Check out repository
52
+ uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
53
+ with:
54
+ fetch-depth: 0
55
+
56
+ - name: Run Gitleaks
57
+ uses: gitleaks/gitleaks-action@ff98106e4c7b2bc287b24eaf42907196329070c7 # v2
58
+ env:
59
+ # The CLI result is the quality gate. Keep SARIF uploads opt-in so
60
+ # a transient Actions artifact quota cannot hide scan results.
61
+ GITLEAKS_ENABLE_UPLOAD_ARTIFACT: "false"
62
+ GITLEAKS_ENABLE_COMMENTS: "false"
63
+
64
+ rust-quality:
65
+ name: Rust format and Clippy
66
+ runs-on: ubuntu-latest
67
+ steps:
68
+ - name: Check out repository
69
+ uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
70
+
71
+ - name: Install Rust
72
+ uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # master
73
+ with:
74
+ toolchain: stable
75
+ components: rustfmt, clippy
76
+
77
+ - name: Cache Cargo dependencies
78
+ uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
79
+ with:
80
+ path: |
81
+ ~/.cargo/registry
82
+ ~/.cargo/git
83
+ target
84
+ key: ${{ runner.os }}-cargo-${{ hashFiles('Cargo.toml', 'Cargo.lock') }}
85
+ restore-keys: |
86
+ ${{ runner.os }}-cargo-
87
+
88
+ - name: Check formatting
89
+ run: cargo fmt --all --check
90
+
91
+ - name: Run Clippy
92
+ run: cargo clippy --locked --all-targets --all-features -- -D warnings
93
+
94
+ rust-dependencies:
95
+ name: Rust dependencies
96
+ runs-on: ubuntu-latest
97
+ steps:
98
+ - name: Check out repository
99
+ uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
100
+
101
+ - name: Run cargo-deny
102
+ uses: EmbarkStudios/cargo-deny-action@3c6349835b2b7b196a839186cb8b78e02f7b5f25 # v2
103
+ with:
104
+ command: check
105
+
106
+ msrv:
107
+ name: Rust MSRV 1.83
108
+ runs-on: ubuntu-latest
109
+ steps:
110
+ - name: Check out repository
111
+ uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
112
+
113
+ - name: Install Rust 1.83
114
+ uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # master
115
+ with:
116
+ toolchain: '1.83'
117
+
118
+ - name: Check with MSRV
119
+ run: cargo check --locked
120
+
121
+ python-tests:
122
+ name: Python tests (${{ matrix.os }}, Python ${{ matrix.python }})
123
+ strategy:
124
+ fail-fast: false
125
+ matrix:
126
+ include:
127
+ - os: ubuntu-latest
128
+ python: '3.10'
129
+ - os: ubuntu-latest
130
+ python: '3.14'
131
+ - os: macos-15
132
+ python: '3.14'
133
+ - os: windows-latest
134
+ python: '3.14'
135
+ runs-on: ${{ matrix.os }}
136
+ steps:
137
+ - name: Check out repository
138
+ uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
139
+
140
+ - name: Set up Python
141
+ uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
142
+ with:
143
+ python-version: ${{ matrix.python }}
144
+ cache: pip
145
+
146
+ - name: Cache Cargo dependencies and build outputs
147
+ uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
148
+ with:
149
+ path: |
150
+ ~/.cargo/registry
151
+ ~/.cargo/git
152
+ target
153
+ key: ${{ runner.os }}-cargo-py${{ matrix.python }}-${{ hashFiles('Cargo.toml', 'Cargo.lock') }}
154
+ restore-keys: |
155
+ ${{ runner.os }}-cargo-py${{ matrix.python }}-
156
+ ${{ runner.os }}-cargo-
157
+
158
+ - name: Build extension in a virtual environment
159
+ shell: bash
160
+ run: |
161
+ python -m venv .venv
162
+ if [ "$RUNNER_OS" = "Windows" ]; then
163
+ source .venv/Scripts/activate
164
+ else
165
+ source .venv/bin/activate
166
+ fi
167
+ python -m pip install --upgrade \
168
+ "maturin>=1.14,<2" \
169
+ "pytest>=8,<10" \
170
+ "pytest-cov>=7,<8" \
171
+ "pydantic>=2,<3"
172
+ maturin develop --locked
173
+
174
+ - name: Run tests
175
+ if: matrix.os != 'ubuntu-latest' || matrix.python != '3.14'
176
+ shell: bash
177
+ run: |
178
+ if [ "$RUNNER_OS" = "Windows" ]; then
179
+ source .venv/Scripts/activate
180
+ else
181
+ source .venv/bin/activate
182
+ fi
183
+ pytest -ra
184
+
185
+ - name: Run tests with branch coverage
186
+ if: matrix.os == 'ubuntu-latest' && matrix.python == '3.14'
187
+ shell: bash
188
+ run: |
189
+ source .venv/bin/activate
190
+ pytest -ra \
191
+ --cov=localqueue \
192
+ --cov-branch \
193
+ --cov-report=term-missing \
194
+ --cov-report=xml \
195
+ --cov-fail-under=80
196
+
197
+ - name: Upload coverage to Codecov
198
+ if: matrix.os == 'ubuntu-latest' && matrix.python == '3.14'
199
+ uses: codecov/codecov-action@0fb7174895f61a3b6b78fc075e0cd60383518dac # v5
200
+ with:
201
+ token: ${{ secrets.CODECOV_TOKEN }}
202
+ files: coverage.xml
203
+ fail_ci_if_error: false
204
+
205
+ wheel-smoke:
206
+ name: Build and smoke-test wheel
207
+ needs: [python-quality, secrets, rust-quality, rust-dependencies, python-tests]
208
+ runs-on: ubuntu-latest
209
+ steps:
210
+ - name: Check out repository
211
+ uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
212
+
213
+ - name: Set up Python
214
+ uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
215
+ with:
216
+ python-version: '3.13'
217
+
218
+ - name: Install maturin
219
+ run: python -m pip install --upgrade "maturin>=1.14,<2"
220
+
221
+ - name: Build wheel
222
+ run: maturin build --release --locked -i python
223
+
224
+ - name: Install wheel
225
+ shell: bash
226
+ run: python -m pip install --force-reinstall target/wheels/*.whl
227
+
228
+ - name: Import package outside the checkout
229
+ shell: bash
230
+ run: |
231
+ cd "$RUNNER_TEMP"
232
+ python - <<'PY'
233
+ import tempfile
234
+
235
+ from localqueue import SimpleQueue
236
+
237
+ with tempfile.TemporaryDirectory() as path:
238
+ queue = SimpleQueue(path)
239
+ queue.put({"source": "wheel-smoke"})
240
+ job = queue.get(block=False)
241
+ assert job.data == {"source": "wheel-smoke"}
242
+ queue.ack(job)
243
+ assert queue.stats()["acked"] == 1
244
+ queue.close()
245
+ PY
@@ -0,0 +1,68 @@
1
+ name: Documentation
2
+
3
+ on:
4
+ pull_request:
5
+ paths:
6
+ - "docs/**"
7
+ - "zensical.toml"
8
+ - ".github/workflows/docs.yml"
9
+ - "pyproject.toml"
10
+ - "uv.lock"
11
+ push:
12
+ branches: [main]
13
+ paths:
14
+ - "docs/**"
15
+ - "zensical.toml"
16
+ - ".github/workflows/docs.yml"
17
+ - "pyproject.toml"
18
+ - "uv.lock"
19
+ workflow_dispatch:
20
+
21
+ permissions:
22
+ contents: read
23
+
24
+ concurrency:
25
+ group: docs-${{ github.workflow }}-${{ github.ref }}
26
+ cancel-in-progress: true
27
+
28
+ jobs:
29
+ build:
30
+ name: Build documentation
31
+ runs-on: ubuntu-latest
32
+ steps:
33
+ - name: Check out repository
34
+ uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
35
+
36
+ - name: Set up Python
37
+ uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
38
+ with:
39
+ python-version: '3.14'
40
+ cache: pip
41
+
42
+ - name: Install Zensical
43
+ run: python -m pip install --upgrade "zensical>=0.0.51,<0.1"
44
+
45
+ - name: Build site
46
+ run: zensical build --clean
47
+
48
+ - name: Upload Pages artifact
49
+ if: github.event_name != 'pull_request'
50
+ uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5
51
+ with:
52
+ path: site
53
+
54
+ deploy:
55
+ name: Deploy documentation
56
+ if: github.event_name != 'pull_request'
57
+ needs: build
58
+ runs-on: ubuntu-latest
59
+ permissions:
60
+ pages: write
61
+ id-token: write
62
+ environment:
63
+ name: github-pages
64
+ url: ${{ steps.deployment.outputs.page_url }}
65
+ steps:
66
+ - name: Deploy to GitHub Pages
67
+ id: deployment
68
+ uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5
@@ -0,0 +1,104 @@
1
+ name: Create release tag
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ dry_run:
7
+ description: Calculate the next version without writing, tagging, or pushing
8
+ required: true
9
+ default: true
10
+ type: boolean
11
+
12
+ permissions:
13
+ contents: write
14
+
15
+ concurrency:
16
+ group: release
17
+ cancel-in-progress: false
18
+
19
+ jobs:
20
+ release:
21
+ name: Calculate and tag release
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - name: Check out main with full history
25
+ uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
26
+ with:
27
+ ref: main
28
+ fetch-depth: 0
29
+
30
+ - name: Confirm main is current
31
+ run: |
32
+ git fetch origin main --tags
33
+ test "$(git rev-parse HEAD)" = "$(git rev-parse origin/main)"
34
+
35
+ - name: Set up Python
36
+ uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
37
+ with:
38
+ python-version: '3.14'
39
+
40
+ - name: Set up Rust
41
+ uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # master
42
+ with:
43
+ toolchain: stable
44
+
45
+ - name: Install release and test tooling
46
+ run: |
47
+ python -m pip install --upgrade \
48
+ "python-semantic-release>=10.6,<11" \
49
+ "maturin>=1.14,<2" \
50
+ "pytest>=8,<10" \
51
+ "pydantic>=2,<3"
52
+
53
+ - name: Validate release history
54
+ run: |
55
+ current_version=$(python -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')
56
+ last_released=$(semantic-release version --print-last-released)
57
+ test "$current_version" = "$last_released" || {
58
+ echo "pyproject.toml is $current_version but Semantic Release sees $last_released." >&2
59
+ echo "Reconcile the published release tag with main before automating the next release." >&2
60
+ exit 1
61
+ }
62
+
63
+ - name: Calculate next version
64
+ id: version
65
+ run: |
66
+ current_version=$(python -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')
67
+ version=$(semantic-release version --print)
68
+ echo "version=$version" >> "$GITHUB_OUTPUT"
69
+ echo "tag=v$version" >> "$GITHUB_OUTPUT"
70
+ if [[ "$version" == "$current_version" ]]; then
71
+ echo "release_needed=false" >> "$GITHUB_OUTPUT"
72
+ else
73
+ echo "release_needed=true" >> "$GITHUB_OUTPUT"
74
+ fi
75
+
76
+ - name: Report dry run
77
+ if: inputs.dry_run
78
+ run: |
79
+ if [[ "${{ steps.version.outputs.release_needed }}" == true ]]; then
80
+ echo "Next release would be ${{ steps.version.outputs.tag }}"
81
+ else
82
+ echo "No release is needed. ${{ steps.version.outputs.tag }} is current."
83
+ fi
84
+
85
+ - name: Create local release commit and tag
86
+ if: inputs.dry_run == false && steps.version.outputs.release_needed == 'true'
87
+ env:
88
+ GH_TOKEN: ${{ github.token }}
89
+ run: semantic-release version --no-push --no-vcs-release
90
+
91
+ - name: Validate versioned tree
92
+ if: inputs.dry_run == false && steps.version.outputs.release_needed == 'true'
93
+ run: |
94
+ python scripts/check_release_version.py --tag "${{ steps.version.outputs.tag }}"
95
+ cargo fmt --all --check
96
+ cargo check --locked
97
+ maturin build --release --locked -i python
98
+ python -m pip install --force-reinstall target/wheels/*.whl
99
+ pytest -ra
100
+
101
+ - name: Push release commit and tag atomically
102
+ if: inputs.dry_run == false && steps.version.outputs.release_needed == 'true'
103
+ run: |
104
+ git push --atomic origin HEAD:main "${{ steps.version.outputs.tag }}"
@@ -24,10 +24,10 @@ jobs:
24
24
  timeout-minutes: 40
25
25
  steps:
26
26
  - name: Check out repository
27
- uses: actions/checkout@v6
27
+ uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
28
28
 
29
29
  - name: Set up Python
30
- uses: actions/setup-python@v6
30
+ uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
31
31
  with:
32
32
  python-version: '3.13'
33
33
 
@@ -50,7 +50,7 @@ jobs:
50
50
 
51
51
  - name: Upload stress report
52
52
  if: always()
53
- uses: actions/upload-artifact@v4
53
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
54
54
  with:
55
55
  name: stress-report-${{ github.run_id }}
56
56
  path: stress-report.json