eventsource-py 0.1.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 (153) hide show
  1. eventsource_py-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
  2. eventsource_py-0.1.0/.github/ISSUE_TEMPLATE/config.yml +8 -0
  3. eventsource_py-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
  4. eventsource_py-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +29 -0
  5. eventsource_py-0.1.0/.github/workflows/ci.yml +162 -0
  6. eventsource_py-0.1.0/.github/workflows/docs.yml +145 -0
  7. eventsource_py-0.1.0/.github/workflows/release.yml +197 -0
  8. eventsource_py-0.1.0/.gitignore +96 -0
  9. eventsource_py-0.1.0/.pre-commit-config.yaml +36 -0
  10. eventsource_py-0.1.0/CHANGELOG.md +40 -0
  11. eventsource_py-0.1.0/LICENSE +21 -0
  12. eventsource_py-0.1.0/PKG-INFO +332 -0
  13. eventsource_py-0.1.0/README.md +274 -0
  14. eventsource_py-0.1.0/RELEASING.md +197 -0
  15. eventsource_py-0.1.0/docker-compose.test.yml +62 -0
  16. eventsource_py-0.1.0/docs/adrs/0000-template.md +129 -0
  17. eventsource_py-0.1.0/docs/adrs/0001-async-first-design.md +278 -0
  18. eventsource_py-0.1.0/docs/adrs/0002-pydantic-event-models.md +318 -0
  19. eventsource_py-0.1.0/docs/adrs/0003-optimistic-locking.md +292 -0
  20. eventsource_py-0.1.0/docs/adrs/0004-projection-error-handling.md +387 -0
  21. eventsource_py-0.1.0/docs/adrs/0005-api-design-patterns.md +341 -0
  22. eventsource_py-0.1.0/docs/adrs/0006-event-registry-serialization.md +393 -0
  23. eventsource_py-0.1.0/docs/adrs/index.md +103 -0
  24. eventsource_py-0.1.0/docs/api/aggregates.md +514 -0
  25. eventsource_py-0.1.0/docs/api/bus.md +540 -0
  26. eventsource_py-0.1.0/docs/api/events.md +331 -0
  27. eventsource_py-0.1.0/docs/api/index.md +580 -0
  28. eventsource_py-0.1.0/docs/api/projections.md +514 -0
  29. eventsource_py-0.1.0/docs/api/stores.md +660 -0
  30. eventsource_py-0.1.0/docs/architecture.md +382 -0
  31. eventsource_py-0.1.0/docs/development/code-structure.md +814 -0
  32. eventsource_py-0.1.0/docs/development/testing.md +1664 -0
  33. eventsource_py-0.1.0/docs/eventsource-py.code-workspace +14 -0
  34. eventsource_py-0.1.0/docs/examples/basic-order.md +285 -0
  35. eventsource_py-0.1.0/docs/examples/multi-tenant.md +941 -0
  36. eventsource_py-0.1.0/docs/examples/projections.md +682 -0
  37. eventsource_py-0.1.0/docs/examples/sqlite-usage.md +649 -0
  38. eventsource_py-0.1.0/docs/examples/testing.md +477 -0
  39. eventsource_py-0.1.0/docs/faq.md +784 -0
  40. eventsource_py-0.1.0/docs/getting-started.md +502 -0
  41. eventsource_py-0.1.0/docs/guides/authentication.md +1239 -0
  42. eventsource_py-0.1.0/docs/guides/error-handling.md +926 -0
  43. eventsource_py-0.1.0/docs/guides/multi-tenant.md +941 -0
  44. eventsource_py-0.1.0/docs/guides/production.md +1548 -0
  45. eventsource_py-0.1.0/docs/guides/sqlite-backend.md +460 -0
  46. eventsource_py-0.1.0/docs/index.md +152 -0
  47. eventsource_py-0.1.0/docs/infrastructure-tracking.md +140 -0
  48. eventsource_py-0.1.0/examples/__init__.py +8 -0
  49. eventsource_py-0.1.0/examples/aggregate_example.py +473 -0
  50. eventsource_py-0.1.0/examples/basic_usage.py +264 -0
  51. eventsource_py-0.1.0/examples/projection_example.py +511 -0
  52. eventsource_py-0.1.0/mkdocs.yml +95 -0
  53. eventsource_py-0.1.0/py.typed +0 -0
  54. eventsource_py-0.1.0/pyproject.toml +136 -0
  55. eventsource_py-0.1.0/scripts/validate_examples.py +287 -0
  56. eventsource_py-0.1.0/src/eventsource/__init__.py +231 -0
  57. eventsource_py-0.1.0/src/eventsource/aggregates/__init__.py +21 -0
  58. eventsource_py-0.1.0/src/eventsource/aggregates/base.py +443 -0
  59. eventsource_py-0.1.0/src/eventsource/aggregates/repository.py +294 -0
  60. eventsource_py-0.1.0/src/eventsource/bus/__init__.py +76 -0
  61. eventsource_py-0.1.0/src/eventsource/bus/interface.py +302 -0
  62. eventsource_py-0.1.0/src/eventsource/bus/memory.py +580 -0
  63. eventsource_py-0.1.0/src/eventsource/bus/redis.py +1487 -0
  64. eventsource_py-0.1.0/src/eventsource/config.py +7 -0
  65. eventsource_py-0.1.0/src/eventsource/events/__init__.py +33 -0
  66. eventsource_py-0.1.0/src/eventsource/events/base.py +281 -0
  67. eventsource_py-0.1.0/src/eventsource/events/registry.py +436 -0
  68. eventsource_py-0.1.0/src/eventsource/exceptions.py +112 -0
  69. eventsource_py-0.1.0/src/eventsource/migrations/SCHEMA_DESIGN.md +238 -0
  70. eventsource_py-0.1.0/src/eventsource/migrations/__init__.py +319 -0
  71. eventsource_py-0.1.0/src/eventsource/migrations/schemas/all.sql +170 -0
  72. eventsource_py-0.1.0/src/eventsource/migrations/schemas/checkpoints.sql +1 -0
  73. eventsource_py-0.1.0/src/eventsource/migrations/schemas/dlq.sql +1 -0
  74. eventsource_py-0.1.0/src/eventsource/migrations/schemas/events.sql +1 -0
  75. eventsource_py-0.1.0/src/eventsource/migrations/schemas/events_partitioned.sql +1 -0
  76. eventsource_py-0.1.0/src/eventsource/migrations/schemas/outbox.sql +1 -0
  77. eventsource_py-0.1.0/src/eventsource/migrations/schemas/sqlite_all.sql +154 -0
  78. eventsource_py-0.1.0/src/eventsource/migrations/templates/alembic/all_tables.py.template +213 -0
  79. eventsource_py-0.1.0/src/eventsource/migrations/templates/alembic/checkpoints.py.template +166 -0
  80. eventsource_py-0.1.0/src/eventsource/migrations/templates/alembic/dlq.py.template +234 -0
  81. eventsource_py-0.1.0/src/eventsource/migrations/templates/alembic/events.py.template +141 -0
  82. eventsource_py-0.1.0/src/eventsource/migrations/templates/alembic/outbox.py.template +145 -0
  83. eventsource_py-0.1.0/src/eventsource/migrations/templates/checkpoints.sql +165 -0
  84. eventsource_py-0.1.0/src/eventsource/migrations/templates/dlq.sql +303 -0
  85. eventsource_py-0.1.0/src/eventsource/migrations/templates/events.sql +113 -0
  86. eventsource_py-0.1.0/src/eventsource/migrations/templates/events_partitioned.sql +238 -0
  87. eventsource_py-0.1.0/src/eventsource/migrations/templates/outbox.sql +191 -0
  88. eventsource_py-0.1.0/src/eventsource/migrations/templates/sqlite/checkpoints.sql +65 -0
  89. eventsource_py-0.1.0/src/eventsource/migrations/templates/sqlite/dlq.sql +101 -0
  90. eventsource_py-0.1.0/src/eventsource/migrations/templates/sqlite/events.sql +103 -0
  91. eventsource_py-0.1.0/src/eventsource/migrations/templates/sqlite/outbox.sql +97 -0
  92. eventsource_py-0.1.0/src/eventsource/projections/__init__.py +88 -0
  93. eventsource_py-0.1.0/src/eventsource/projections/base.py +799 -0
  94. eventsource_py-0.1.0/src/eventsource/projections/coordinator.py +542 -0
  95. eventsource_py-0.1.0/src/eventsource/projections/decorators.py +102 -0
  96. eventsource_py-0.1.0/src/eventsource/projections/protocols.py +161 -0
  97. eventsource_py-0.1.0/src/eventsource/py.typed +0 -0
  98. eventsource_py-0.1.0/src/eventsource/repositories/__init__.py +86 -0
  99. eventsource_py-0.1.0/src/eventsource/repositories/_connection.py +65 -0
  100. eventsource_py-0.1.0/src/eventsource/repositories/_json.py +84 -0
  101. eventsource_py-0.1.0/src/eventsource/repositories/checkpoint.py +717 -0
  102. eventsource_py-0.1.0/src/eventsource/repositories/dlq.py +1124 -0
  103. eventsource_py-0.1.0/src/eventsource/repositories/outbox.py +816 -0
  104. eventsource_py-0.1.0/src/eventsource/stores/__init__.py +45 -0
  105. eventsource_py-0.1.0/src/eventsource/stores/in_memory.py +573 -0
  106. eventsource_py-0.1.0/src/eventsource/stores/interface.py +696 -0
  107. eventsource_py-0.1.0/src/eventsource/stores/postgresql.py +919 -0
  108. eventsource_py-0.1.0/src/eventsource/stores/sqlite.py +978 -0
  109. eventsource_py-0.1.0/src/eventsource/types.py +23 -0
  110. eventsource_py-0.1.0/tests/__init__.py +1 -0
  111. eventsource_py-0.1.0/tests/conftest.py +248 -0
  112. eventsource_py-0.1.0/tests/fixtures/__init__.py +1 -0
  113. eventsource_py-0.1.0/tests/integration/__init__.py +22 -0
  114. eventsource_py-0.1.0/tests/integration/bus/__init__.py +1 -0
  115. eventsource_py-0.1.0/tests/integration/bus/test_redis.py +597 -0
  116. eventsource_py-0.1.0/tests/integration/conftest.py +774 -0
  117. eventsource_py-0.1.0/tests/integration/e2e/__init__.py +1 -0
  118. eventsource_py-0.1.0/tests/integration/e2e/test_full_flow.py +548 -0
  119. eventsource_py-0.1.0/tests/integration/projections/__init__.py +1 -0
  120. eventsource_py-0.1.0/tests/integration/projections/test_database_projection.py +586 -0
  121. eventsource_py-0.1.0/tests/integration/repositories/__init__.py +1 -0
  122. eventsource_py-0.1.0/tests/integration/repositories/test_checkpoint.py +298 -0
  123. eventsource_py-0.1.0/tests/integration/repositories/test_dlq.py +460 -0
  124. eventsource_py-0.1.0/tests/integration/repositories/test_outbox.py +478 -0
  125. eventsource_py-0.1.0/tests/integration/stores/__init__.py +1 -0
  126. eventsource_py-0.1.0/tests/integration/stores/test_postgresql.py +895 -0
  127. eventsource_py-0.1.0/tests/repositories/__init__.py +1 -0
  128. eventsource_py-0.1.0/tests/repositories/test_sqlite_repos.py +954 -0
  129. eventsource_py-0.1.0/tests/stores/__init__.py +1 -0
  130. eventsource_py-0.1.0/tests/stores/test_sqlite_event_store.py +1214 -0
  131. eventsource_py-0.1.0/tests/unit/__init__.py +1 -0
  132. eventsource_py-0.1.0/tests/unit/test_additional_coverage.py +493 -0
  133. eventsource_py-0.1.0/tests/unit/test_aggregate_repository.py +1000 -0
  134. eventsource_py-0.1.0/tests/unit/test_aggregate_root.py +1349 -0
  135. eventsource_py-0.1.0/tests/unit/test_checkpoint_repository.py +682 -0
  136. eventsource_py-0.1.0/tests/unit/test_connection_helper.py +316 -0
  137. eventsource_py-0.1.0/tests/unit/test_dlq_repository.py +1148 -0
  138. eventsource_py-0.1.0/tests/unit/test_domain_event.py +854 -0
  139. eventsource_py-0.1.0/tests/unit/test_edge_cases.py +621 -0
  140. eventsource_py-0.1.0/tests/unit/test_event_bus.py +989 -0
  141. eventsource_py-0.1.0/tests/unit/test_event_registry.py +749 -0
  142. eventsource_py-0.1.0/tests/unit/test_event_store_interface.py +852 -0
  143. eventsource_py-0.1.0/tests/unit/test_exceptions.py +260 -0
  144. eventsource_py-0.1.0/tests/unit/test_in_memory_event_store.py +1157 -0
  145. eventsource_py-0.1.0/tests/unit/test_json_encoder.py +166 -0
  146. eventsource_py-0.1.0/tests/unit/test_outbox_repository.py +846 -0
  147. eventsource_py-0.1.0/tests/unit/test_postgresql_event_store.py +1248 -0
  148. eventsource_py-0.1.0/tests/unit/test_projection_base.py +1076 -0
  149. eventsource_py-0.1.0/tests/unit/test_projection_coordinator.py +666 -0
  150. eventsource_py-0.1.0/tests/unit/test_projection_decorators.py +229 -0
  151. eventsource_py-0.1.0/tests/unit/test_projection_protocols.py +236 -0
  152. eventsource_py-0.1.0/tests/unit/test_redis_event_bus.py +1132 -0
  153. eventsource_py-0.1.0/uv.lock +1660 -0
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: Bug Report
3
+ description: Report a bug or unexpected behavior
4
+ labels: ["bug"]
5
+ ---
6
+
7
+ ## Description
8
+
9
+ A clear and concise description of the bug.
10
+
11
+ ## Steps to Reproduce
12
+
13
+ 1. Step one
14
+ 2. Step two
15
+ 3. ...
16
+
17
+ ## Expected Behavior
18
+
19
+ What you expected to happen.
20
+
21
+ ## Actual Behavior
22
+
23
+ What actually happened.
24
+
25
+ ## Environment
26
+
27
+ - Python version: [e.g., 3.11.5]
28
+ - eventsource-client version: [e.g., 0.1.0]
29
+ - OS: [e.g., Ubuntu 22.04, macOS 14.0, Windows 11]
30
+
31
+ ## Additional Context
32
+
33
+ Add any other context, stack traces, or screenshots.
@@ -0,0 +1,8 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Documentation
4
+ url: https://[ORGANIZATION].github.io/eventsource-py
5
+ about: Check our documentation for answers
6
+ - name: Questions & Discussions
7
+ url: https://github.com/[ORGANIZATION]/eventsource-py/discussions
8
+ about: Ask questions and discuss ideas
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: Feature Request
3
+ description: Suggest a new feature or enhancement
4
+ labels: ["enhancement"]
5
+ ---
6
+
7
+ ## Problem Statement
8
+
9
+ Describe the problem you're trying to solve or the limitation you've encountered.
10
+
11
+ ## Proposed Solution
12
+
13
+ Describe the solution you'd like to see.
14
+
15
+ ## Alternatives Considered
16
+
17
+ What alternatives have you considered?
18
+
19
+ ## Additional Context
20
+
21
+ Add any other context, mockups, or examples.
@@ -0,0 +1,29 @@
1
+ ## Summary
2
+
3
+ Brief description of what this PR does.
4
+
5
+ ## Type of Change
6
+
7
+ - [ ] Bug fix (non-breaking change that fixes an issue)
8
+ - [ ] New feature (non-breaking change that adds functionality)
9
+ - [ ] Breaking change (fix or feature that would cause existing functionality to change)
10
+ - [ ] Documentation update
11
+ - [ ] Refactoring (no functional changes)
12
+ - [ ] Tests only
13
+
14
+ ## Checklist
15
+
16
+ - [ ] My code follows the project's code style
17
+ - [ ] I have added tests that prove my fix/feature works
18
+ - [ ] All new and existing tests pass
19
+ - [ ] I have updated the documentation (if applicable)
20
+ - [ ] I have updated the CHANGELOG.md
21
+ - [ ] I have added type hints to new code
22
+
23
+ ## Related Issues
24
+
25
+ Closes #(issue number)
26
+
27
+ ## Additional Notes
28
+
29
+ Any additional context for reviewers.
@@ -0,0 +1,162 @@
1
+ # CI Workflow
2
+ # Runs linting, type checking, and tests on push and pull requests
3
+ #
4
+ # Jobs:
5
+ # - lint: ruff check and format verification
6
+ # - type-check: mypy strict type checking
7
+ # - test: pytest with coverage (matrix: Python 3.11, 3.12)
8
+
9
+ name: CI
10
+
11
+ on:
12
+ push:
13
+ branches: [main]
14
+ pull_request:
15
+ branches: [main]
16
+ workflow_call: # Allow release workflow to call this
17
+
18
+ concurrency:
19
+ group: ci-${{ github.ref }}
20
+ cancel-in-progress: true
21
+
22
+ permissions:
23
+ contents: read
24
+
25
+ jobs:
26
+ # Linting with ruff
27
+ lint:
28
+ runs-on: ubuntu-latest
29
+ steps:
30
+ - name: Checkout
31
+ uses: actions/checkout@v4
32
+
33
+ - name: Setup Python
34
+ uses: actions/setup-python@v5
35
+ with:
36
+ python-version: '3.11'
37
+ cache: 'pip'
38
+ cache-dependency-path: pyproject.toml
39
+
40
+ - name: Install dependencies
41
+ run: |
42
+ pip install --upgrade pip
43
+ pip install -e ".[dev]"
44
+
45
+ - name: Run ruff check
46
+ run: ruff check .
47
+
48
+ - name: Run ruff format check
49
+ run: ruff format --check .
50
+
51
+ # Type checking with mypy
52
+ type-check:
53
+ runs-on: ubuntu-latest
54
+ steps:
55
+ - name: Checkout
56
+ uses: actions/checkout@v4
57
+
58
+ - name: Setup Python
59
+ uses: actions/setup-python@v5
60
+ with:
61
+ python-version: '3.11'
62
+ cache: 'pip'
63
+ cache-dependency-path: pyproject.toml
64
+
65
+ - name: Install dependencies
66
+ run: |
67
+ pip install --upgrade pip
68
+ pip install -e ".[dev,all]"
69
+
70
+ - name: Run mypy
71
+ run: mypy src/
72
+
73
+ # Testing with pytest
74
+ test:
75
+ runs-on: ubuntu-latest
76
+ strategy:
77
+ fail-fast: false
78
+ matrix:
79
+ python-version: ['3.11', '3.12']
80
+
81
+ steps:
82
+ - name: Checkout
83
+ uses: actions/checkout@v4
84
+
85
+ - name: Setup Python ${{ matrix.python-version }}
86
+ uses: actions/setup-python@v5
87
+ with:
88
+ python-version: ${{ matrix.python-version }}
89
+ cache: 'pip'
90
+ cache-dependency-path: pyproject.toml
91
+
92
+ - name: Install dependencies
93
+ run: |
94
+ pip install --upgrade pip
95
+ pip install -e ".[dev,all]"
96
+
97
+ - name: Run tests
98
+ run: |
99
+ pytest --cov=src/eventsource --cov-report=xml --cov-report=term-missing \
100
+ -m "not integration and not postgres and not redis and not e2e"
101
+
102
+ - name: Upload coverage report
103
+ if: matrix.python-version == '3.11'
104
+ uses: actions/upload-artifact@v4
105
+ with:
106
+ name: coverage-report
107
+ path: coverage.xml
108
+ retention-days: 7
109
+
110
+ # Integration tests (optional, requires services)
111
+ integration:
112
+ runs-on: ubuntu-latest
113
+ needs: [lint, type-check, test]
114
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
115
+
116
+ services:
117
+ postgres:
118
+ image: postgres:16
119
+ env:
120
+ POSTGRES_USER: test
121
+ POSTGRES_PASSWORD: test
122
+ POSTGRES_DB: eventsource_test
123
+ ports:
124
+ - 5432:5432
125
+ options: >-
126
+ --health-cmd pg_isready
127
+ --health-interval 10s
128
+ --health-timeout 5s
129
+ --health-retries 5
130
+
131
+ redis:
132
+ image: redis:7
133
+ ports:
134
+ - 6379:6379
135
+ options: >-
136
+ --health-cmd "redis-cli ping"
137
+ --health-interval 10s
138
+ --health-timeout 5s
139
+ --health-retries 5
140
+
141
+ steps:
142
+ - name: Checkout
143
+ uses: actions/checkout@v4
144
+
145
+ - name: Setup Python
146
+ uses: actions/setup-python@v5
147
+ with:
148
+ python-version: '3.11'
149
+ cache: 'pip'
150
+ cache-dependency-path: pyproject.toml
151
+
152
+ - name: Install dependencies
153
+ run: |
154
+ pip install --upgrade pip
155
+ pip install -e ".[dev,all]"
156
+
157
+ - name: Run integration tests
158
+ env:
159
+ DATABASE_URL: postgresql://test:test@localhost:5432/eventsource_test
160
+ REDIS_URL: redis://localhost:6379
161
+ run: |
162
+ pytest -m "integration or postgres or redis" --cov=src/eventsource --cov-report=term-missing
@@ -0,0 +1,145 @@
1
+ # Documentation CI/CD Workflow
2
+ # Builds, validates, and deploys documentation to GitHub Pages
3
+ #
4
+ # Triggers:
5
+ # - Push to main (docs paths) -> Build + Deploy
6
+ # - Pull requests (docs paths) -> Build only (no deploy)
7
+ # - Manual dispatch -> Build + Deploy (if on main)
8
+
9
+ name: Documentation
10
+
11
+ on:
12
+ push:
13
+ branches: [main]
14
+ paths:
15
+ - 'docs/**'
16
+ - 'mkdocs.yml'
17
+ - 'src/**/*.py' # For API doc generation
18
+ - 'examples/**' # Example files
19
+ - 'scripts/validate_examples.py'
20
+ - '.github/workflows/docs.yml'
21
+ pull_request:
22
+ branches: [main]
23
+ paths:
24
+ - 'docs/**'
25
+ - 'mkdocs.yml'
26
+ - 'src/**/*.py'
27
+ - 'examples/**'
28
+ - 'scripts/validate_examples.py'
29
+ - '.github/workflows/docs.yml'
30
+ workflow_dispatch:
31
+
32
+ # Allow only one concurrent deployment, skip in-progress for PRs
33
+ concurrency:
34
+ group: pages-${{ github.ref }}
35
+ cancel-in-progress: true
36
+
37
+ # Sets permissions of the GITHUB_TOKEN for Pages deployment
38
+ permissions:
39
+ contents: read
40
+
41
+ jobs:
42
+ # Build documentation
43
+ build:
44
+ runs-on: ubuntu-latest
45
+ steps:
46
+ - name: Checkout
47
+ uses: actions/checkout@v4
48
+ with:
49
+ fetch-depth: 0 # Fetch all history for git-based plugins
50
+
51
+ - name: Setup Python
52
+ uses: actions/setup-python@v5
53
+ with:
54
+ python-version: '3.11'
55
+ cache: 'pip'
56
+ cache-dependency-path: pyproject.toml
57
+
58
+ - name: Install dependencies
59
+ run: |
60
+ pip install --upgrade pip
61
+ pip install -e ".[docs]"
62
+
63
+ - name: Build documentation
64
+ run: mkdocs build --strict
65
+
66
+ - name: Upload artifact for GitHub Pages
67
+ uses: actions/upload-pages-artifact@v3
68
+ with:
69
+ path: site/
70
+
71
+ - name: Upload artifact for PR review
72
+ if: github.event_name == 'pull_request'
73
+ uses: actions/upload-artifact@v4
74
+ with:
75
+ name: docs-preview
76
+ path: site/
77
+ retention-days: 7
78
+
79
+ # Validate code examples
80
+ validate-examples:
81
+ runs-on: ubuntu-latest
82
+ steps:
83
+ - name: Checkout
84
+ uses: actions/checkout@v4
85
+
86
+ - name: Setup Python
87
+ uses: actions/setup-python@v5
88
+ with:
89
+ python-version: '3.11'
90
+ cache: 'pip'
91
+ cache-dependency-path: pyproject.toml
92
+
93
+ - name: Install package
94
+ run: |
95
+ pip install --upgrade pip
96
+ pip install -e .
97
+
98
+ - name: Validate example syntax
99
+ run: python scripts/validate_examples.py --syntax
100
+
101
+ - name: Run examples
102
+ run: python scripts/validate_examples.py
103
+
104
+ # Check for broken links
105
+ link-check:
106
+ runs-on: ubuntu-latest
107
+ steps:
108
+ - name: Checkout
109
+ uses: actions/checkout@v4
110
+
111
+ - name: Link Checker
112
+ uses: lycheeverse/lychee-action@v1
113
+ with:
114
+ args: >-
115
+ --verbose
116
+ --no-progress
117
+ --accept 200,204,206
118
+ --exclude-mail
119
+ --exclude-path './site'
120
+ --exclude 'your-org'
121
+ --exclude 'localhost'
122
+ --exclude '127.0.0.1'
123
+ 'docs/**/*.md'
124
+ 'README.md'
125
+ fail: true
126
+
127
+ # Deploy to GitHub Pages (only on push to main)
128
+ deploy:
129
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
130
+ needs: [build, link-check, validate-examples]
131
+ runs-on: ubuntu-latest
132
+
133
+ # Grant permissions for GitHub Pages deployment
134
+ permissions:
135
+ pages: write
136
+ id-token: write
137
+
138
+ environment:
139
+ name: github-pages
140
+ url: ${{ steps.deployment.outputs.page_url }}
141
+
142
+ steps:
143
+ - name: Deploy to GitHub Pages
144
+ id: deployment
145
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,197 @@
1
+ # Release Workflow
2
+ # Publishes package to PyPI when a version tag is pushed
3
+ #
4
+ # Triggers on tags matching v* (e.g., v0.1.0, v1.0.0a1)
5
+ # - Stable versions (v1.0.0) -> PyPI
6
+ # - Pre-releases (v1.0.0a1, v1.0.0b1) -> TestPyPI
7
+ # - Release candidates (v1.0.0rc1) -> PyPI (marked as pre-release)
8
+
9
+ name: Release
10
+
11
+ on:
12
+ push:
13
+ tags:
14
+ - 'v*'
15
+
16
+ permissions:
17
+ contents: write # For GitHub Release creation
18
+ id-token: write # For Trusted Publishing (OIDC)
19
+
20
+ jobs:
21
+ # Validate release tag and extract version info
22
+ validate:
23
+ runs-on: ubuntu-latest
24
+ outputs:
25
+ version: ${{ steps.version.outputs.version }}
26
+ is_prerelease: ${{ steps.version.outputs.is_prerelease }}
27
+ publish_target: ${{ steps.version.outputs.publish_target }}
28
+ steps:
29
+ - name: Checkout
30
+ uses: actions/checkout@v4
31
+
32
+ - name: Extract version from tag
33
+ id: version
34
+ run: |
35
+ TAG=${GITHUB_REF#refs/tags/v}
36
+ echo "version=$TAG" >> $GITHUB_OUTPUT
37
+
38
+ # Determine if this is a pre-release and where to publish
39
+ if [[ "$TAG" =~ (a|b)[0-9]+ ]]; then
40
+ # Alpha or Beta -> TestPyPI
41
+ echo "is_prerelease=true" >> $GITHUB_OUTPUT
42
+ echo "publish_target=testpypi" >> $GITHUB_OUTPUT
43
+ elif [[ "$TAG" =~ rc[0-9]+ ]]; then
44
+ # Release candidate -> PyPI but marked as pre-release
45
+ echo "is_prerelease=true" >> $GITHUB_OUTPUT
46
+ echo "publish_target=pypi" >> $GITHUB_OUTPUT
47
+ else
48
+ # Stable release -> PyPI
49
+ echo "is_prerelease=false" >> $GITHUB_OUTPUT
50
+ echo "publish_target=pypi" >> $GITHUB_OUTPUT
51
+ fi
52
+
53
+ - name: Setup Python
54
+ uses: actions/setup-python@v5
55
+ with:
56
+ python-version: '3.11'
57
+
58
+ - name: Validate version matches pyproject.toml
59
+ run: |
60
+ pip install tomli
61
+ PYPROJECT_VERSION=$(python -c "import tomli; print(tomli.load(open('pyproject.toml', 'rb'))['project']['version'])")
62
+ if [[ "${{ steps.version.outputs.version }}" != "$PYPROJECT_VERSION" ]]; then
63
+ echo "::error::Tag version (${{ steps.version.outputs.version }}) does not match pyproject.toml ($PYPROJECT_VERSION)"
64
+ exit 1
65
+ fi
66
+ echo "Version validated: $PYPROJECT_VERSION"
67
+
68
+ # Run CI checks (reuse existing workflow)
69
+ ci:
70
+ needs: validate
71
+ uses: ./.github/workflows/ci.yml
72
+
73
+ # Build distribution packages
74
+ build:
75
+ needs: ci
76
+ runs-on: ubuntu-latest
77
+ steps:
78
+ - name: Checkout
79
+ uses: actions/checkout@v4
80
+
81
+ - name: Setup Python
82
+ uses: actions/setup-python@v5
83
+ with:
84
+ python-version: '3.11'
85
+
86
+ - name: Install build tools
87
+ run: pip install build
88
+
89
+ - name: Build distributions
90
+ run: python -m build
91
+
92
+ - name: Upload artifacts
93
+ uses: actions/upload-artifact@v4
94
+ with:
95
+ name: dist
96
+ path: dist/
97
+
98
+ # Publish to PyPI (stable releases and RCs)
99
+ publish-pypi:
100
+ needs: [validate, build]
101
+ if: needs.validate.outputs.publish_target == 'pypi'
102
+ runs-on: ubuntu-latest
103
+ environment: pypi
104
+ steps:
105
+ - name: Download artifacts
106
+ uses: actions/download-artifact@v4
107
+ with:
108
+ name: dist
109
+ path: dist/
110
+
111
+ - name: Publish to PyPI
112
+ uses: pypa/gh-action-pypi-publish@release/v1
113
+
114
+ # Publish to TestPyPI (alpha and beta releases)
115
+ publish-testpypi:
116
+ needs: [validate, build]
117
+ if: needs.validate.outputs.publish_target == 'testpypi'
118
+ runs-on: ubuntu-latest
119
+ environment: testpypi
120
+ steps:
121
+ - name: Download artifacts
122
+ uses: actions/download-artifact@v4
123
+ with:
124
+ name: dist
125
+ path: dist/
126
+
127
+ - name: Publish to TestPyPI
128
+ uses: pypa/gh-action-pypi-publish@release/v1
129
+ with:
130
+ repository-url: https://test.pypi.org/legacy/
131
+
132
+ # Create GitHub Release
133
+ github-release:
134
+ needs: [validate, build, publish-pypi, publish-testpypi]
135
+ if: always() && needs.build.result == 'success' && (needs.publish-pypi.result == 'success' || needs.publish-testpypi.result == 'success' || needs.publish-pypi.result == 'skipped' || needs.publish-testpypi.result == 'skipped')
136
+ runs-on: ubuntu-latest
137
+ steps:
138
+ - name: Checkout
139
+ uses: actions/checkout@v4
140
+
141
+ - name: Download artifacts
142
+ uses: actions/download-artifact@v4
143
+ with:
144
+ name: dist
145
+ path: dist/
146
+
147
+ - name: Extract changelog for this version
148
+ id: changelog
149
+ run: |
150
+ VERSION=${{ needs.validate.outputs.version }}
151
+ # Extract the section for this version from CHANGELOG.md
152
+ # This captures everything between ## [VERSION] and the next ## [
153
+ CONTENT=$(awk "/^## \[$VERSION\]/{flag=1; next} /^## \[/{flag=0} flag" CHANGELOG.md)
154
+
155
+ # Handle multi-line content for GitHub Actions
156
+ echo "content<<EOF" >> $GITHUB_OUTPUT
157
+ echo "$CONTENT" >> $GITHUB_OUTPUT
158
+ echo "EOF" >> $GITHUB_OUTPUT
159
+
160
+ - name: Create GitHub Release
161
+ uses: softprops/action-gh-release@v2
162
+ with:
163
+ files: dist/*
164
+ prerelease: ${{ needs.validate.outputs.is_prerelease }}
165
+ body: |
166
+ ## What's Changed
167
+
168
+ ${{ steps.changelog.outputs.content }}
169
+
170
+ ## Installation
171
+
172
+ ```bash
173
+ pip install eventsource-py==${{ needs.validate.outputs.version }}
174
+ ```
175
+ generate_release_notes: false
176
+
177
+ # Post-publish verification
178
+ verify:
179
+ needs: [validate, publish-pypi]
180
+ if: needs.publish-pypi.result == 'success'
181
+ runs-on: ubuntu-latest
182
+ steps:
183
+ - name: Wait for PyPI propagation
184
+ run: sleep 60
185
+
186
+ - name: Setup Python
187
+ uses: actions/setup-python@v5
188
+ with:
189
+ python-version: '3.11'
190
+
191
+ - name: Install from PyPI
192
+ run: pip install eventsource-py==${{ needs.validate.outputs.version }}
193
+
194
+ - name: Verify import and version
195
+ run: |
196
+ python -c "import eventsource; print(f'Installed version: {eventsource.__version__}')"
197
+ python -c "from eventsource import DomainEvent, InMemoryEventStore; print('Basic imports successful')"
@@ -0,0 +1,96 @@
1
+ docs/futures/
2
+ docs/tasks/
3
+
4
+ # Byte-compiled / optimized / DLL files
5
+ __pycache__/
6
+ *.py[cod]
7
+ *$py.class
8
+
9
+ # C extensions
10
+ *.so
11
+
12
+ # Distribution / packaging
13
+ .Python
14
+ build/
15
+ develop-eggs/
16
+ dist/
17
+ downloads/
18
+ eggs/
19
+ .eggs/
20
+ lib/
21
+ lib64/
22
+ parts/
23
+ sdist/
24
+ var/
25
+ wheels/
26
+ *.egg-info/
27
+ .installed.cfg
28
+ *.egg
29
+
30
+ # PyInstaller
31
+ *.manifest
32
+ *.spec
33
+
34
+ # Installer logs
35
+ pip-log.txt
36
+ pip-delete-this-directory.txt
37
+
38
+ # Unit test / coverage reports
39
+ htmlcov/
40
+ .tox/
41
+ .nox/
42
+ .coverage
43
+ .coverage.*
44
+ .cache
45
+ nosetests.xml
46
+ coverage.xml
47
+ *.cover
48
+ *.py,cover
49
+ .hypothesis/
50
+ .pytest_cache/
51
+
52
+ # Translations
53
+ *.mo
54
+ *.pot
55
+
56
+ # Environments
57
+ .env
58
+ .venv
59
+ env/
60
+ venv/
61
+ ENV/
62
+ env.bak/
63
+ venv.bak/
64
+
65
+ # mypy
66
+ .mypy_cache/
67
+ .dmypy.json
68
+ dmypy.json
69
+
70
+ # ruff
71
+ .ruff_cache/
72
+
73
+ # IDEs
74
+ .idea/
75
+ .vscode/
76
+ *.swp
77
+ *.swo
78
+ *~
79
+ .project
80
+ .pydevproject
81
+ .settings/
82
+
83
+ # Jupyter Notebook
84
+ .ipynb_checkpoints
85
+
86
+ # Local development
87
+ *.local
88
+ .env.local
89
+ .env.*.local
90
+
91
+ # OS files
92
+ .DS_Store
93
+ Thumbs.db
94
+
95
+ # MkDocs documentation site
96
+ site/