pydocket 0.7.0__tar.gz → 0.13.0b1__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.

Potentially problematic release.


This version of pydocket might be problematic. Click here for more details.

Files changed (98) hide show
  1. pydocket-0.13.0b1/.coveragerc-memory +10 -0
  2. {pydocket-0.7.0 → pydocket-0.13.0b1}/.github/workflows/chaos.yml +2 -0
  3. pydocket-0.13.0b1/.github/workflows/ci.yml +97 -0
  4. pydocket-0.13.0b1/.github/workflows/claude-code-review.yml +40 -0
  5. pydocket-0.13.0b1/.github/workflows/claude.yml +42 -0
  6. {pydocket-0.7.0 → pydocket-0.13.0b1}/.github/workflows/publish.yml +9 -4
  7. {pydocket-0.7.0 → pydocket-0.13.0b1}/.gitignore +8 -8
  8. pydocket-0.13.0b1/CLAUDE.md +125 -0
  9. {pydocket-0.7.0 → pydocket-0.13.0b1}/PKG-INFO +26 -4
  10. {pydocket-0.7.0 → pydocket-0.13.0b1}/README.md +16 -1
  11. {pydocket-0.7.0 → pydocket-0.13.0b1}/chaos/driver.py +36 -6
  12. pydocket-0.13.0b1/docs/advanced-patterns.md +690 -0
  13. pydocket-0.13.0b1/docs/dependencies.md +489 -0
  14. pydocket-0.13.0b1/docs/getting-started.md +198 -0
  15. pydocket-0.13.0b1/docs/production.md +407 -0
  16. pydocket-0.13.0b1/docs/testing.md +426 -0
  17. pydocket-0.13.0b1/examples/agenda_scatter.py +128 -0
  18. pydocket-0.13.0b1/examples/concurrency_control.py +114 -0
  19. pydocket-0.13.0b1/examples/fastapi_background_tasks.py +204 -0
  20. pydocket-0.13.0b1/examples/local_development.py +98 -0
  21. pydocket-0.13.0b1/examples/task_progress.py +111 -0
  22. {pydocket-0.7.0 → pydocket-0.13.0b1}/mkdocs.yml +4 -0
  23. {pydocket-0.7.0 → pydocket-0.13.0b1}/pyproject.toml +27 -6
  24. pydocket-0.13.0b1/sitecustomize.py +7 -0
  25. {pydocket-0.7.0 → pydocket-0.13.0b1}/src/docket/__init__.py +8 -1
  26. pydocket-0.13.0b1/src/docket/agenda.py +202 -0
  27. {pydocket-0.7.0 → pydocket-0.13.0b1}/src/docket/annotations.py +7 -1
  28. {pydocket-0.7.0 → pydocket-0.13.0b1}/src/docket/cli.py +427 -18
  29. {pydocket-0.7.0 → pydocket-0.13.0b1}/src/docket/dependencies.py +250 -60
  30. {pydocket-0.7.0 → pydocket-0.13.0b1}/src/docket/docket.py +229 -80
  31. pydocket-0.13.0b1/src/docket/execution.py +1212 -0
  32. {pydocket-0.7.0 → pydocket-0.13.0b1}/src/docket/instrumentation.py +20 -1
  33. {pydocket-0.7.0 → pydocket-0.13.0b1}/src/docket/tasks.py +2 -2
  34. {pydocket-0.7.0 → pydocket-0.13.0b1}/src/docket/worker.py +298 -62
  35. pydocket-0.13.0b1/tests/cli/run.py +53 -0
  36. pydocket-0.13.0b1/tests/cli/test_clear.py +202 -0
  37. pydocket-0.13.0b1/tests/cli/test_module.py +10 -0
  38. {pydocket-0.7.0 → pydocket-0.13.0b1}/tests/cli/test_parsing.py +7 -0
  39. pydocket-0.13.0b1/tests/cli/test_snapshot.py +342 -0
  40. {pydocket-0.7.0 → pydocket-0.13.0b1}/tests/cli/test_striking.py +78 -108
  41. {pydocket-0.7.0 → pydocket-0.13.0b1}/tests/cli/test_tasks.py +32 -45
  42. pydocket-0.13.0b1/tests/cli/test_url_validation.py +59 -0
  43. {pydocket-0.7.0 → pydocket-0.13.0b1}/tests/cli/test_version.py +5 -6
  44. pydocket-0.13.0b1/tests/cli/test_watch.py +404 -0
  45. {pydocket-0.7.0 → pydocket-0.13.0b1}/tests/cli/test_worker.py +46 -68
  46. {pydocket-0.7.0 → pydocket-0.13.0b1}/tests/cli/test_workers.py +27 -29
  47. pydocket-0.13.0b1/tests/cli/waiting.py +133 -0
  48. pydocket-0.13.0b1/tests/conftest.py +210 -0
  49. pydocket-0.13.0b1/tests/test_agenda.py +404 -0
  50. pydocket-0.13.0b1/tests/test_concurrency_basic.py +31 -0
  51. pydocket-0.13.0b1/tests/test_concurrency_control.py +336 -0
  52. pydocket-0.13.0b1/tests/test_concurrency_refresh.py +196 -0
  53. pydocket-0.13.0b1/tests/test_dependencies.py +666 -0
  54. pydocket-0.13.0b1/tests/test_docket.py +210 -0
  55. pydocket-0.13.0b1/tests/test_execution_progress.py +835 -0
  56. {pydocket-0.7.0 → pydocket-0.13.0b1}/tests/test_fundamentals.py +417 -7
  57. {pydocket-0.7.0 → pydocket-0.13.0b1}/tests/test_instrumentation.py +207 -4
  58. pydocket-0.13.0b1/tests/test_memory_backend.py +113 -0
  59. pydocket-0.13.0b1/tests/test_results.py +429 -0
  60. {pydocket-0.7.0 → pydocket-0.13.0b1}/tests/test_striking.py +2 -0
  61. pydocket-0.13.0b1/tests/test_worker.py +1780 -0
  62. pydocket-0.13.0b1/uv.lock +2243 -0
  63. pydocket-0.7.0/.github/workflows/ci.yml +0 -65
  64. pydocket-0.7.0/docs/getting-started.md +0 -286
  65. pydocket-0.7.0/src/docket/execution.py +0 -436
  66. pydocket-0.7.0/tests/cli/conftest.py +0 -8
  67. pydocket-0.7.0/tests/cli/test_module.py +0 -22
  68. pydocket-0.7.0/tests/cli/test_snapshot.py +0 -175
  69. pydocket-0.7.0/tests/conftest.py +0 -176
  70. pydocket-0.7.0/tests/test_dependencies.py +0 -262
  71. pydocket-0.7.0/tests/test_docket.py +0 -14
  72. pydocket-0.7.0/tests/test_worker.py +0 -515
  73. pydocket-0.7.0/uv.lock +0 -1443
  74. {pydocket-0.7.0 → pydocket-0.13.0b1}/.cursor/rules/general.mdc +0 -0
  75. {pydocket-0.7.0 → pydocket-0.13.0b1}/.cursor/rules/python-style.mdc +0 -0
  76. {pydocket-0.7.0 → pydocket-0.13.0b1}/.github/codecov.yml +0 -0
  77. {pydocket-0.7.0 → pydocket-0.13.0b1}/.github/workflows/docs.yml +0 -0
  78. {pydocket-0.7.0 → pydocket-0.13.0b1}/.pre-commit-config.yaml +0 -0
  79. {pydocket-0.7.0 → pydocket-0.13.0b1}/LICENSE +0 -0
  80. {pydocket-0.7.0 → pydocket-0.13.0b1}/chaos/README.md +0 -0
  81. {pydocket-0.7.0 → pydocket-0.13.0b1}/chaos/__init__.py +0 -0
  82. {pydocket-0.7.0 → pydocket-0.13.0b1}/chaos/producer.py +0 -0
  83. {pydocket-0.7.0 → pydocket-0.13.0b1}/chaos/run +0 -0
  84. {pydocket-0.7.0 → pydocket-0.13.0b1}/chaos/tasks.py +0 -0
  85. {pydocket-0.7.0 → pydocket-0.13.0b1}/docs/api-reference.md +0 -0
  86. {pydocket-0.7.0 → pydocket-0.13.0b1}/docs/index.md +0 -0
  87. {pydocket-0.7.0 → pydocket-0.13.0b1}/examples/__init__.py +0 -0
  88. {pydocket-0.7.0 → pydocket-0.13.0b1}/examples/common.py +0 -0
  89. {pydocket-0.7.0 → pydocket-0.13.0b1}/examples/find_and_flood.py +0 -0
  90. {pydocket-0.7.0 → pydocket-0.13.0b1}/examples/self_perpetuating.py +0 -0
  91. {pydocket-0.7.0 → pydocket-0.13.0b1}/src/docket/__main__.py +0 -0
  92. {pydocket-0.7.0 → pydocket-0.13.0b1}/src/docket/py.typed +0 -0
  93. {pydocket-0.7.0 → pydocket-0.13.0b1}/telemetry/.gitignore +0 -0
  94. {pydocket-0.7.0 → pydocket-0.13.0b1}/telemetry/start +0 -0
  95. {pydocket-0.7.0 → pydocket-0.13.0b1}/telemetry/stop +0 -0
  96. {pydocket-0.7.0 → pydocket-0.13.0b1}/tests/__init__.py +0 -0
  97. {pydocket-0.7.0 → pydocket-0.13.0b1}/tests/cli/__init__.py +0 -0
  98. {pydocket-0.7.0 → pydocket-0.13.0b1}/tests/test_execution.py +0 -0
@@ -0,0 +1,10 @@
1
+ # Coverage configuration for memory backend testing
2
+ # CLI tests are skipped with memory:// URLs, so exclude CLI from coverage
3
+
4
+ [run]
5
+ branch = true
6
+ parallel = true
7
+ omit =
8
+ src/docket/__main__.py
9
+ src/docket/cli.py
10
+ tests/cli/test_*.py
@@ -15,6 +15,8 @@ jobs:
15
15
 
16
16
  steps:
17
17
  - uses: actions/checkout@v4
18
+ with:
19
+ fetch-depth: 0
18
20
 
19
21
  - name: Install uv and set Python version
20
22
  uses: astral-sh/setup-uv@v5
@@ -0,0 +1,97 @@
1
+ name: Docket CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_call:
8
+
9
+ jobs:
10
+ test:
11
+ name: Test Python ${{ matrix.python-version }}, ${{ matrix.backend.name }}
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
17
+ backend:
18
+ - name: "Redis 6.2, redis-py <5"
19
+ redis-version: "6.2"
20
+ redis-py-version: ">=5,<6"
21
+ - name: "Redis 7.4, redis-py >=5"
22
+ redis-version: "7.4"
23
+ redis-py-version: ">=5"
24
+ - name: "Valkey 8.0, redis-py >=5"
25
+ redis-version: "valkey-8.0"
26
+ redis-py-version: ">=5"
27
+ - name: "Memory (in-memory backend)"
28
+ redis-version: "memory"
29
+ redis-py-version: ">=5"
30
+ include:
31
+ - python-version: "3.10"
32
+ cov-threshold: 100
33
+ pytest-args: ""
34
+ # Python 3.11 coverage reporting is unstable, so use 98% threshold
35
+ - python-version: "3.11"
36
+ cov-threshold: 98
37
+ pytest-args: ""
38
+ - python-version: "3.12"
39
+ cov-threshold: 100
40
+ pytest-args: ""
41
+ - python-version: "3.13"
42
+ cov-threshold: 100
43
+ pytest-args: ""
44
+ - python-version: "3.14"
45
+ cov-threshold: 100
46
+ pytest-args: ""
47
+ # Memory backend: CLI tests are skipped via pytest skip markers because
48
+ # CLI rejects memory:// URLs. Use separate coverage config to exclude CLI.
49
+ - backend:
50
+ name: "Memory (in-memory backend)"
51
+ redis-version: "memory"
52
+ redis-py-version: ">=5"
53
+ cov-threshold: 98 # CLI tests are excluded from coverage and some lines are only covered by CLI tests
54
+ pytest-args: "--cov-config=.coveragerc-memory"
55
+
56
+ steps:
57
+ - uses: actions/checkout@v4
58
+
59
+ - name: Install uv and set Python version
60
+ uses: astral-sh/setup-uv@v5
61
+ with:
62
+ python-version: ${{ matrix.python-version }}
63
+ enable-cache: true
64
+ cache-dependency-glob: "pyproject.toml"
65
+
66
+ - name: Install dependencies
67
+ run: uv sync --upgrade-package 'redis${{ matrix.backend.redis-py-version }}'
68
+
69
+ - name: Run tests
70
+ env:
71
+ REDIS_VERSION: ${{ matrix.backend.redis-version }}
72
+ run: uv run pytest --cov-branch --cov-fail-under=${{ matrix.cov-threshold }} --cov-report=xml --cov-report=term-missing:skip-covered ${{ matrix.pytest-args }}
73
+
74
+ - name: Upload coverage reports to Codecov
75
+ uses: codecov/codecov-action@v5
76
+ with:
77
+ token: ${{ secrets.CODECOV_TOKEN }}
78
+ flags: python-${{ matrix.python-version }}
79
+
80
+ prek:
81
+ name: Prek checks
82
+ runs-on: ubuntu-latest
83
+ steps:
84
+ - uses: actions/checkout@v4
85
+
86
+ - name: Install uv and set Python version
87
+ uses: astral-sh/setup-uv@v5
88
+ with:
89
+ python-version: "3.10"
90
+ enable-cache: true
91
+ cache-dependency-glob: "pyproject.toml"
92
+
93
+ - name: Install dependencies
94
+ run: uv sync
95
+
96
+ - name: Run prek
97
+ uses: j178/prek-action@v1
@@ -0,0 +1,40 @@
1
+ name: Claude Code Review
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize]
6
+
7
+ jobs:
8
+ claude-review:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ contents: read
12
+ pull-requests: read
13
+ issues: read
14
+ id-token: write
15
+
16
+ steps:
17
+ - name: Checkout repository
18
+ uses: actions/checkout@v4
19
+ with:
20
+ fetch-depth: 1
21
+
22
+ - name: Run Claude Code Review
23
+ id: claude-review
24
+ uses: anthropics/claude-code-action@beta
25
+ with:
26
+ anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
27
+ model: "claude-opus-4-1-20250805"
28
+
29
+ # Direct prompt for automated review (no @claude mention needed)
30
+ direct_prompt: |
31
+ Please review this pull request and provide feedback on:
32
+ - Code quality and best practices
33
+ - Potential bugs or issues
34
+ - Performance considerations
35
+ - Security concerns
36
+ - Test coverage, which must be maintained at 100% for this project
37
+
38
+ Be constructive and helpful in your feedback.
39
+
40
+ use_sticky_comment: true
@@ -0,0 +1,42 @@
1
+ name: Claude Code
2
+
3
+ on:
4
+ issue_comment:
5
+ types: [created]
6
+ pull_request_review_comment:
7
+ types: [created]
8
+ issues:
9
+ types: [opened, assigned]
10
+ pull_request_review:
11
+ types: [submitted]
12
+
13
+ jobs:
14
+ claude:
15
+ if: |
16
+ (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
17
+ (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
18
+ (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
19
+ (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
20
+ runs-on: ubuntu-latest
21
+ permissions:
22
+ contents: read
23
+ pull-requests: read
24
+ issues: read
25
+ id-token: write
26
+ actions: read # Required for Claude to read CI results on PRs
27
+ steps:
28
+ - name: Checkout repository
29
+ uses: actions/checkout@v4
30
+ with:
31
+ fetch-depth: 1
32
+
33
+ - name: Run Claude Code
34
+ id: claude
35
+ uses: anthropics/claude-code-action@beta
36
+ with:
37
+ anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
38
+
39
+ additional_permissions: |
40
+ actions: read
41
+
42
+ model: "claude-opus-4-1-20250805"
@@ -13,8 +13,11 @@ jobs:
13
13
  name: Build and publish to PyPI
14
14
  runs-on: ubuntu-latest
15
15
  needs: ci
16
+ environment:
17
+ name: pypi
18
+ url: https://pypi.org/p/pydocket
16
19
  permissions:
17
- id-token: write
20
+ id-token: write # Required for trusted publishing and PEP 740 attestations
18
21
  contents: read
19
22
 
20
23
  steps:
@@ -31,10 +34,12 @@ jobs:
31
34
  cache-dependency-glob: "pyproject.toml"
32
35
 
33
36
  - name: Install build dependencies
34
- run: uv pip install build hatchling hatch-vcs
37
+ run: uv pip install hatchling hatch-vcs
35
38
 
36
39
  - name: Build package
37
40
  run: uv build
38
41
 
39
- - name: Publish to PyPI
40
- run: uv publish
42
+ - name: Publish to PyPI with PEP 740 attestations
43
+ uses: pypa/gh-action-pypi-publish@release/v1
44
+ with:
45
+ packages-dir: dist/
@@ -1,13 +1,13 @@
1
- # Python-generated files
2
- __pycache__/
1
+ *.egg-info
3
2
  *.py[oc]
3
+ .coverage
4
+ .envrc
5
+ .python-version
6
+ .venv
7
+ .worktrees/
8
+ __pycache__/
4
9
  build/
5
10
  dist/
6
11
  wheels/
7
- *.egg-info
8
12
 
9
- # Virtual environments
10
- .venv
11
- .coverage
12
- .envrc
13
- .python-version
13
+ .coverage.*
@@ -0,0 +1,125 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ **Docket** (`pydocket` on PyPI) is a distributed background task system for Python functions with Redis-backed persistence. It enables scheduling both immediate and future work with comprehensive dependency injection, retry mechanisms, and fault tolerance.
8
+
9
+ **Key Requirements**: Python 3.10+, Redis 6.2+ or Valkey 8.0+
10
+
11
+ ## Development Commands
12
+
13
+ ### Testing
14
+
15
+ ```bash
16
+ # Run full test suite with coverage and parallel execution
17
+ pytest
18
+
19
+ # Run specific test
20
+ pytest tests/test_docket.py::test_specific_function
21
+
22
+ ```
23
+
24
+ The project REQUIRES 100% test coverage
25
+
26
+ ### Code Quality
27
+
28
+ ```bash
29
+ # Lint and format code
30
+ ruff check
31
+ ruff format
32
+
33
+ # Type checking
34
+ pyright
35
+ pyright tests
36
+
37
+ # Run all prek hooks
38
+ uv run prek run --all-files
39
+ ```
40
+
41
+ ### Development Setup
42
+
43
+ ```bash
44
+ # Install development dependencies
45
+ uv sync --group dev
46
+
47
+ # Install prek hooks
48
+ uv run prek install
49
+ ```
50
+
51
+ ### Git Workflow
52
+
53
+ - This project uses Github for issue tracking
54
+ - This project can use git worktrees under .worktrees/
55
+
56
+ ## Core Architecture
57
+
58
+ ### Key Classes
59
+
60
+ - **`Docket`** (`src/docket/docket.py`): Central task registry and scheduler
61
+ - `add()`: Schedule tasks for execution
62
+ - `replace()`: Replace existing scheduled tasks
63
+ - `cancel()`: Cancel pending tasks
64
+ - `strike()`/`restore()`: Conditionally block/unblock tasks
65
+ - `snapshot()`: Get current state for observability
66
+
67
+ - **`Worker`** (`src/docket/worker.py`): Task execution engine
68
+ - `run_forever()`/`run_until_finished()`: Main execution loops
69
+ - Handles concurrency, retries, and dependency injection
70
+ - Maintains heartbeat for liveness tracking
71
+
72
+ - **`Execution`** (`src/docket/execution.py`): Task execution context with metadata
73
+
74
+ ### Dependencies System (`src/docket/dependencies.py`)
75
+
76
+ Rich dependency injection supporting:
77
+
78
+ - Context access: `CurrentDocket`, `CurrentWorker`, `CurrentExecution`
79
+ - Retry strategies: `Retry`, `ExponentialRetry`
80
+ - Special behaviors: `Perpetual` (self-rescheduling), `Timeout`
81
+ - Custom injection: `Depends()`
82
+ - Contextual logging: `TaskLogger`
83
+
84
+ ### Redis Data Model
85
+
86
+ - **Streams**: `{docket}:stream` (ready tasks), `{docket}:strikes` (commands)
87
+ - **Sorted Sets**: `{docket}:queue` (scheduled tasks), `{docket}:workers` (heartbeats)
88
+ - **Hashes**: `{docket}:{key}` (parked task data)
89
+ - **Sets**: `{docket}:worker-tasks:{worker}` (worker capabilities)
90
+
91
+ ### Task Lifecycle
92
+
93
+ 1. Registration with `Docket.register()` or `@docket.task`
94
+ 2. Scheduling: immediate → Redis stream, future → Redis sorted set
95
+ 3. Worker processing: scheduler moves due tasks, workers consume via consumer groups
96
+ 4. Execution: dependency injection, retry logic, acknowledgment
97
+
98
+ ## Project Structure
99
+
100
+ ### Source Code
101
+
102
+ - `src/docket/` - Main package
103
+ - `__init__.py` - Public API exports
104
+ - `docket.py` - Core Docket class
105
+ - `worker.py` - Worker implementation
106
+ - `execution.py` - Task execution context
107
+ - `dependencies.py` - Dependency injection system
108
+ - `tasks.py` - Built-in utility tasks
109
+ - `cli.py` - Command-line interface
110
+
111
+ ### Testing and Examples
112
+
113
+ - `tests/` - Comprehensive test suite
114
+ - `examples/` - Usage examples
115
+ - `chaos/` - Chaos testing framework
116
+
117
+ ## CLI Usage
118
+
119
+ ```bash
120
+ # Run a worker
121
+ docket worker --url redis://localhost:6379/0 --tasks your.module --concurrency 4
122
+
123
+ # See all commands
124
+ docket --help
125
+ ```
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydocket
3
- Version: 0.7.0
3
+ Version: 0.13.0b1
4
4
  Summary: A distributed background task system for Python functions
5
5
  Project-URL: Homepage, https://github.com/chrisguidry/docket
6
6
  Project-URL: Bug Tracker, https://github.com/chrisguidry/docket/issues
@@ -19,18 +19,25 @@ Classifier: Development Status :: 4 - Beta
19
19
  Classifier: License :: OSI Approved :: MIT License
20
20
  Classifier: Operating System :: OS Independent
21
21
  Classifier: Programming Language :: Python :: 3
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
22
24
  Classifier: Programming Language :: Python :: 3.12
23
25
  Classifier: Programming Language :: Python :: 3.13
26
+ Classifier: Programming Language :: Python :: 3.14
24
27
  Classifier: Typing :: Typed
25
- Requires-Python: >=3.12
28
+ Requires-Python: >=3.10
26
29
  Requires-Dist: cloudpickle>=3.1.1
30
+ Requires-Dist: exceptiongroup>=1.2.0; python_version < '3.11'
31
+ Requires-Dist: fakeredis[lua]>=2.32.1
27
32
  Requires-Dist: opentelemetry-api>=1.30.0
28
33
  Requires-Dist: opentelemetry-exporter-prometheus>=0.51b0
29
34
  Requires-Dist: prometheus-client>=0.21.1
35
+ Requires-Dist: py-key-value-aio[memory,redis]>=0.2.8
30
36
  Requires-Dist: python-json-logger>=3.2.1
31
- Requires-Dist: redis>=4.6
37
+ Requires-Dist: redis>=5
32
38
  Requires-Dist: rich>=13.9.4
33
39
  Requires-Dist: typer>=0.15.1
40
+ Requires-Dist: typing-extensions>=4.12.0
34
41
  Requires-Dist: uuid7>=0.1.0
35
42
  Description-Content-Type: text/markdown
36
43
 
@@ -69,6 +76,7 @@ from docket import Docket, Worker
69
76
 
70
77
  async with Docket() as docket:
71
78
  async with Worker(docket) as worker:
79
+ worker.register(greet)
72
80
  await worker.run_until_finished()
73
81
  ```
74
82
 
@@ -93,10 +101,12 @@ reference](https://chrisguidry.github.io/docket/api-reference/).
93
101
 
94
102
  🧩 Fully type-complete and type-aware for your background task functions
95
103
 
104
+ 💉 Dependency injection like FastAPI, Typer, and FastMCP for reusable resources
105
+
96
106
  ## Installing `docket`
97
107
 
98
108
  Docket is [available on PyPI](https://pypi.org/project/pydocket/) under the package name
99
- `pydocket`. It targets Python 3.12 or above.
109
+ `pydocket`. It targets Python 3.10 or above.
100
110
 
101
111
  With [`uv`](https://docs.astral.sh/uv/):
102
112
 
@@ -117,6 +127,18 @@ pip install pydocket
117
127
  Docket requires a [Redis](http://redis.io/) server with Streams support (which was
118
128
  introduced in Redis 5.0.0). Docket is tested with Redis 6 and 7.
119
129
 
130
+ For testing without Redis, Docket includes [fakeredis](https://github.com/cunla/fakeredis-py) for in-memory operation:
131
+
132
+ ```python
133
+ from docket import Docket
134
+
135
+ async with Docket(name="my-docket", url="memory://my-docket") as docket:
136
+ # Use docket normally - all operations are in-memory
137
+ ...
138
+ ```
139
+
140
+ See [Testing with Docket](https://chrisguidry.github.io/docket/testing/#using-in-memory-backend-no-redis-required) for more details.
141
+
120
142
  # Hacking on `docket`
121
143
 
122
144
  We use [`uv`](https://docs.astral.sh/uv/) for project management, so getting set up
@@ -33,6 +33,7 @@ from docket import Docket, Worker
33
33
 
34
34
  async with Docket() as docket:
35
35
  async with Worker(docket) as worker:
36
+ worker.register(greet)
36
37
  await worker.run_until_finished()
37
38
  ```
38
39
 
@@ -57,10 +58,12 @@ reference](https://chrisguidry.github.io/docket/api-reference/).
57
58
 
58
59
  🧩 Fully type-complete and type-aware for your background task functions
59
60
 
61
+ 💉 Dependency injection like FastAPI, Typer, and FastMCP for reusable resources
62
+
60
63
  ## Installing `docket`
61
64
 
62
65
  Docket is [available on PyPI](https://pypi.org/project/pydocket/) under the package name
63
- `pydocket`. It targets Python 3.12 or above.
66
+ `pydocket`. It targets Python 3.10 or above.
64
67
 
65
68
  With [`uv`](https://docs.astral.sh/uv/):
66
69
 
@@ -81,6 +84,18 @@ pip install pydocket
81
84
  Docket requires a [Redis](http://redis.io/) server with Streams support (which was
82
85
  introduced in Redis 5.0.0). Docket is tested with Redis 6 and 7.
83
86
 
87
+ For testing without Redis, Docket includes [fakeredis](https://github.com/cunla/fakeredis-py) for in-memory operation:
88
+
89
+ ```python
90
+ from docket import Docket
91
+
92
+ async with Docket(name="my-docket", url="memory://my-docket") as docket:
93
+ # Use docket normally - all operations are in-memory
94
+ ...
95
+ ```
96
+
97
+ See [Testing with Docket](https://chrisguidry.github.io/docket/testing/#using-in-memory-backend-no-redis-required) for more details.
98
+
84
99
  # Hacking on `docket`
85
100
 
86
101
  We use [`uv`](https://docs.astral.sh/uv/) for project management, so getting set up
@@ -73,7 +73,20 @@ async def main(
73
73
  tasks: int = 20000,
74
74
  producers: int = 5,
75
75
  workers: int = 10,
76
+ base_version: str | None = None,
76
77
  ):
78
+ if base_version is None:
79
+ process = await asyncio.create_subprocess_exec(
80
+ "git",
81
+ "describe",
82
+ "--tags",
83
+ "--abbrev=0",
84
+ stdout=subprocess.PIPE,
85
+ stderr=subprocess.PIPE,
86
+ )
87
+ stdout, _ = await process.communicate()
88
+ base_version = stdout.decode("utf-8").strip()
89
+
77
90
  async with (
78
91
  run_redis("7.4.2") as (redis_url, redis_container),
79
92
  Docket(
@@ -105,11 +118,17 @@ async def main(
105
118
  )
106
119
 
107
120
  async def spawn_producer() -> Process:
121
+ docket_version = base_version if random.random() < 0.5 else "main"
122
+ base_command = ["uv", "run"]
123
+ if docket_version != "main":
124
+ logger.info("Using pydocket %s for producer", docket_version)
125
+ base_command.extend(["--with", f"pydocket=={docket_version}"])
126
+ else:
127
+ logger.info("Using main pydocket for producer")
128
+
129
+ command = [*base_command, "-m", "chaos.producer", str(tasks_per_producer)]
108
130
  return await asyncio.create_subprocess_exec(
109
- *python_entrypoint(),
110
- "-m",
111
- "chaos.producer",
112
- str(tasks_per_producer),
131
+ *command,
113
132
  env=environment | {"OTEL_SERVICE_NAME": "chaos-producer"},
114
133
  stdout=subprocess.DEVNULL,
115
134
  stderr=subprocess.DEVNULL,
@@ -122,8 +141,16 @@ async def main(
122
141
  logger.info("Spawning %d workers...", workers)
123
142
 
124
143
  async def spawn_worker() -> Process:
125
- return await asyncio.create_subprocess_exec(
126
- *python_entrypoint(),
144
+ docket_version = base_version if random.random() < 0.5 else "main"
145
+ base_command = ["uv", "run"]
146
+ if docket_version != "main":
147
+ logger.info("Using pydocket %s for worker", docket_version)
148
+ base_command.extend(["--with", f"pydocket=={docket_version}"])
149
+ else:
150
+ logger.info("Using main pydocket for worker")
151
+
152
+ command = [
153
+ *base_command,
127
154
  "-m",
128
155
  "docket",
129
156
  "worker",
@@ -135,6 +162,9 @@ async def main(
135
162
  "chaos.tasks:chaos_tasks",
136
163
  "--redelivery-timeout",
137
164
  "5s",
165
+ ]
166
+ return await asyncio.create_subprocess_exec(
167
+ *command,
138
168
  env=environment | {"OTEL_SERVICE_NAME": "chaos-worker"},
139
169
  stdout=subprocess.DEVNULL,
140
170
  stderr=subprocess.DEVNULL,