power-events 1.0.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.
- power_events-1.0.0/.github/workflows/ci.yml +201 -0
- power_events-1.0.0/.github/workflows/coverage-comment.yml +27 -0
- power_events-1.0.0/.github/workflows/publish-docs.yml +55 -0
- power_events-1.0.0/.github/workflows/release.yml +84 -0
- power_events-1.0.0/.gitignore +18 -0
- power_events-1.0.0/.pre-commit-config.yaml +39 -0
- power_events-1.0.0/CHANGELOG.md +14 -0
- power_events-1.0.0/LICENSE +21 -0
- power_events-1.0.0/PKG-INFO +182 -0
- power_events-1.0.0/README.md +138 -0
- power_events-1.0.0/docs/api/conditions.md +1 -0
- power_events-1.0.0/docs/api/exception.md +1 -0
- power_events-1.0.0/docs/api/resolver.md +5 -0
- power_events-1.0.0/docs/api/value.md +1 -0
- power_events-1.0.0/docs/index.md +5 -0
- power_events-1.0.0/docs/installation.md +47 -0
- power_events-1.0.0/docs/usage/conditions.md +174 -0
- power_events-1.0.0/docs/usage/first_steps.md +101 -0
- power_events-1.0.0/docs/usage/index.md +9 -0
- power_events-1.0.0/docs/usage/routing.md +190 -0
- power_events-1.0.0/mkdocs.yml +98 -0
- power_events-1.0.0/power_events/__init__.py +13 -0
- power_events-1.0.0/power_events/conditions/__init__.py +16 -0
- power_events-1.0.0/power_events/conditions/condition.py +122 -0
- power_events-1.0.0/power_events/conditions/value.py +283 -0
- power_events-1.0.0/power_events/exceptions.py +68 -0
- power_events-1.0.0/power_events/py.typed +0 -0
- power_events-1.0.0/power_events/resolver.py +140 -0
- power_events-1.0.0/pyproject.toml +191 -0
- power_events-1.0.0/tests/__init__.py +0 -0
- power_events-1.0.0/tests/conditions/test_condition.py +62 -0
- power_events-1.0.0/tests/conditions/test_value.py +145 -0
- power_events-1.0.0/tests/test_package.py +4 -0
- power_events-1.0.0/tests/test_resolver.py +147 -0
- power_events-1.0.0/uv.lock +1288 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
name: Checks
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main ]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
env:
|
|
11
|
+
UV_PYTHON: "3.9"
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
typos:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: crate-ci/typos@master
|
|
23
|
+
|
|
24
|
+
lint:
|
|
25
|
+
name: "Lint"
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
|
|
30
|
+
- name: "Install UV"
|
|
31
|
+
uses: astral-sh/setup-uv@v3
|
|
32
|
+
with:
|
|
33
|
+
enable-cache: true
|
|
34
|
+
cache-dependency-glob: |
|
|
35
|
+
pyproject.toml
|
|
36
|
+
|
|
37
|
+
- name: "Install lint dependencies"
|
|
38
|
+
run: uv sync --only-group lint
|
|
39
|
+
|
|
40
|
+
- name: "Python format"
|
|
41
|
+
run: uvx ruff format --diff .
|
|
42
|
+
|
|
43
|
+
- name: "Python lint"
|
|
44
|
+
run: uvx ruff check .
|
|
45
|
+
|
|
46
|
+
- name: "Python type check"
|
|
47
|
+
run: uv run mypy
|
|
48
|
+
|
|
49
|
+
build-docs:
|
|
50
|
+
name: "Build docs"
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/checkout@v4
|
|
54
|
+
|
|
55
|
+
- uses: astral-sh/setup-uv@v3
|
|
56
|
+
with:
|
|
57
|
+
enable-cache: true
|
|
58
|
+
|
|
59
|
+
- name: "Install docs dependencies"
|
|
60
|
+
run: uv sync --only-group docs
|
|
61
|
+
|
|
62
|
+
- run: uv run mkdocs build --strict
|
|
63
|
+
|
|
64
|
+
tests:
|
|
65
|
+
name: "Testing with Python ${{ matrix.python-version }}"
|
|
66
|
+
runs-on: ubuntu-latest
|
|
67
|
+
strategy:
|
|
68
|
+
matrix:
|
|
69
|
+
python-version:
|
|
70
|
+
- "3.13"
|
|
71
|
+
- "3.12"
|
|
72
|
+
- "3.11"
|
|
73
|
+
- "3.10"
|
|
74
|
+
- "3.9"
|
|
75
|
+
fail-fast: false
|
|
76
|
+
steps:
|
|
77
|
+
- uses: actions/checkout@v4
|
|
78
|
+
|
|
79
|
+
- uses: astral-sh/setup-uv@v3
|
|
80
|
+
with:
|
|
81
|
+
enable-cache: true
|
|
82
|
+
cache-dependency-glob: |
|
|
83
|
+
pyproject.toml
|
|
84
|
+
|
|
85
|
+
- name: "Install dev dependencies"
|
|
86
|
+
run: uv sync --python ${{ matrix.python-version }} --only-dev
|
|
87
|
+
|
|
88
|
+
- name: "Run tests"
|
|
89
|
+
run: uv run pytest
|
|
90
|
+
env:
|
|
91
|
+
COVERAGE_FILE: .coverage.py${{ matrix.python-version }}
|
|
92
|
+
- name: Upload coverage
|
|
93
|
+
uses: actions/upload-artifact@v4
|
|
94
|
+
with:
|
|
95
|
+
name: .coverage.py${{ matrix.python-version }}
|
|
96
|
+
path: .coverage.py${{ matrix.python-version }}
|
|
97
|
+
if-no-files-found: error
|
|
98
|
+
include-hidden-files: true
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
combine-coverage:
|
|
102
|
+
name: "Combine coverages"
|
|
103
|
+
runs-on: ubuntu-latest
|
|
104
|
+
needs: [ tests ]
|
|
105
|
+
steps:
|
|
106
|
+
- uses: actions/checkout@v4
|
|
107
|
+
- uses: actions/setup-python@v5
|
|
108
|
+
with:
|
|
109
|
+
python-version: "3.9"
|
|
110
|
+
- name: Update pip
|
|
111
|
+
run: pip install --upgrade pip
|
|
112
|
+
- name: Install coverage
|
|
113
|
+
run: pip install coverage[toml]
|
|
114
|
+
|
|
115
|
+
- name: Download coverage files
|
|
116
|
+
uses: actions/download-artifact@v4
|
|
117
|
+
with:
|
|
118
|
+
path: coverage
|
|
119
|
+
merge-multiple: true
|
|
120
|
+
|
|
121
|
+
- run: coverage combine coverage
|
|
122
|
+
- run: coverage report
|
|
123
|
+
- run: coverage html --title "Coverage for ${{ github.sha }}" -d htmlcov
|
|
124
|
+
|
|
125
|
+
- name: Store coverage data
|
|
126
|
+
uses: actions/upload-artifact@v4
|
|
127
|
+
with:
|
|
128
|
+
name: coverage-data
|
|
129
|
+
path: .coverage
|
|
130
|
+
include-hidden-files: true
|
|
131
|
+
|
|
132
|
+
- name: Upload coverage html
|
|
133
|
+
uses: actions/upload-artifact@v4
|
|
134
|
+
with:
|
|
135
|
+
name: coverage-html
|
|
136
|
+
path: htmlcov
|
|
137
|
+
include-hidden-files: true
|
|
138
|
+
if-no-files-found: error
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
comment-coverage:
|
|
142
|
+
name: "Comment coverage on PR"
|
|
143
|
+
runs-on: ubuntu-latest
|
|
144
|
+
needs: [ combine-coverage ]
|
|
145
|
+
if: github.event_name == 'pull_request'
|
|
146
|
+
permissions:
|
|
147
|
+
pull-requests: write
|
|
148
|
+
contents: write
|
|
149
|
+
|
|
150
|
+
steps:
|
|
151
|
+
- uses: actions/checkout@v4
|
|
152
|
+
- name: Download coverage files
|
|
153
|
+
uses: actions/download-artifact@v4
|
|
154
|
+
with:
|
|
155
|
+
name: coverage-data
|
|
156
|
+
|
|
157
|
+
- name: Generate coverage comment
|
|
158
|
+
id: coverage-comment
|
|
159
|
+
uses: py-cov-action/python-coverage-comment-action@v3
|
|
160
|
+
with:
|
|
161
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
162
|
+
|
|
163
|
+
- name: Store coverage comment
|
|
164
|
+
uses: actions/upload-artifact@v4
|
|
165
|
+
if: steps.coverage-comment.outputs.COMMENT_FILE_WRITTEN == 'true'
|
|
166
|
+
with:
|
|
167
|
+
name: python-coverage-comment-action
|
|
168
|
+
path: python-coverage-comment-action.txt
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
report-coverage:
|
|
172
|
+
name: Report coverages
|
|
173
|
+
runs-on: ubuntu-latest
|
|
174
|
+
needs: [ combine-coverage ]
|
|
175
|
+
permissions:
|
|
176
|
+
statuses: write
|
|
177
|
+
steps:
|
|
178
|
+
- uses: actions/checkout@v4
|
|
179
|
+
- uses: actions/setup-python@v5
|
|
180
|
+
with:
|
|
181
|
+
python-version: "3.9"
|
|
182
|
+
- name: Update pip
|
|
183
|
+
run: pip install --upgrade pip
|
|
184
|
+
|
|
185
|
+
- name: Download coverage files
|
|
186
|
+
uses: actions/download-artifact@v4
|
|
187
|
+
with:
|
|
188
|
+
name: coverage-html
|
|
189
|
+
path: htmlcov
|
|
190
|
+
|
|
191
|
+
- run: pip install smokeshow
|
|
192
|
+
|
|
193
|
+
- name: "Upload report"
|
|
194
|
+
run: smokeshow upload htmlcov
|
|
195
|
+
env:
|
|
196
|
+
SMOKESHOW_GITHUB_STATUS_DESCRIPTION: Coverage {coverage-percentage}
|
|
197
|
+
SMOKESHOW_GITHUB_COVERAGE_THRESHOLD: 100
|
|
198
|
+
SMOKESHOW_GITHUB_CONTEXT: coverage
|
|
199
|
+
SMOKESHOW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
200
|
+
SMOKESHOW_GITHUB_PR_HEAD_SHA: ${{ github.sha }}
|
|
201
|
+
SMOKESHOW_AUTH_KEY: ${{ secrets.SMOKESHOW_KEY }}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Post coverage comment
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_run:
|
|
5
|
+
workflows: ["CI"]
|
|
6
|
+
types:
|
|
7
|
+
- completed
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
post-coverage-comment:
|
|
11
|
+
name: Push coverage comment
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
|
|
14
|
+
permissions:
|
|
15
|
+
pull-requests: write
|
|
16
|
+
contents: write
|
|
17
|
+
actions: read
|
|
18
|
+
steps:
|
|
19
|
+
# DO NOT run actions/checkout here, for security reasons
|
|
20
|
+
# For details, refer to https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
|
|
21
|
+
- name: Post comment
|
|
22
|
+
uses: py-cov-action/python-coverage-comment-action@v3
|
|
23
|
+
with:
|
|
24
|
+
GITHUB_TOKEN: ${{ secret.GITHUB_TOKEN }}
|
|
25
|
+
GITHUB_PR_RUN_ID: ${{ github.event.workflow_run.id }}
|
|
26
|
+
ANNOTATE_MISSING_LINES: true
|
|
27
|
+
ANNOTATION_TYPE: warning
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: publish-docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
tags:
|
|
8
|
+
- "[0-9]+.[0-9]+.[0-9]+"
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
env:
|
|
12
|
+
UV_PYTHON: "3.9"
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
docs:
|
|
16
|
+
name: "Publish documentation"
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
permissions:
|
|
19
|
+
contents: write
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- name: Checkout gh-pages
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
with:
|
|
25
|
+
ref: gh-pages
|
|
26
|
+
|
|
27
|
+
- name: Checkout current branch
|
|
28
|
+
uses: actions/checkout@v4
|
|
29
|
+
|
|
30
|
+
- name: "set up env"
|
|
31
|
+
uses: astral-sh/setup-uv@v3
|
|
32
|
+
with:
|
|
33
|
+
enable-cache: true
|
|
34
|
+
cache-dependency-glob: |
|
|
35
|
+
pyproject.toml
|
|
36
|
+
|
|
37
|
+
- name: "Install doc deps"
|
|
38
|
+
run: uv sync --only-group docs
|
|
39
|
+
|
|
40
|
+
- name: "Configure Git Credentials"
|
|
41
|
+
run: |
|
|
42
|
+
git config user.name github-actions[bot]
|
|
43
|
+
git config user.email github-actions[bot]@users.noreply.github.com
|
|
44
|
+
|
|
45
|
+
- name: "Get version"
|
|
46
|
+
if: "startsWith(github.ref, 'refs/tags/')"
|
|
47
|
+
run: echo "TAG=$(python -c "print('.'.join('${{ github.ref_name }}'.split('.')[:2]))")">>$GITHUB_ENV
|
|
48
|
+
|
|
49
|
+
- name: "Publish version $TAG"
|
|
50
|
+
if: "startsWith(github.ref, 'refs/tags/')"
|
|
51
|
+
run: uv run mike deploy --push --update-aliases $TAG latest
|
|
52
|
+
|
|
53
|
+
- name: "Update dev docs"
|
|
54
|
+
if: "github.ref =='refs/heads/main'"
|
|
55
|
+
run: uv run mike deploy --push --update-aliases dev
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
name: "Release"
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "[0-9]+.[0-9]+.[0-9]+"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
name: "Build distribution package"
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: '3.9'
|
|
18
|
+
|
|
19
|
+
- name: "Install 'build' library"
|
|
20
|
+
run: pip install -U build
|
|
21
|
+
|
|
22
|
+
- name: build
|
|
23
|
+
run: python -m build
|
|
24
|
+
|
|
25
|
+
- name: "Upload distribution artifacts"
|
|
26
|
+
uses: actions/upload-artifact@v4
|
|
27
|
+
with:
|
|
28
|
+
name: dist
|
|
29
|
+
path: dist/
|
|
30
|
+
|
|
31
|
+
publish-pypi:
|
|
32
|
+
name: "Publish to PyPI"
|
|
33
|
+
needs: [ build ]
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
permissions:
|
|
36
|
+
id-token: write # IMPORTANT: mandatory for trusted publishing
|
|
37
|
+
environment:
|
|
38
|
+
name: pypi
|
|
39
|
+
url: https://pypi.org/p/power-events
|
|
40
|
+
steps:
|
|
41
|
+
- name: "Download distribution artifacts"
|
|
42
|
+
uses: actions/download-artifact@v4
|
|
43
|
+
with:
|
|
44
|
+
name: dist
|
|
45
|
+
path: dist/
|
|
46
|
+
- name: Publish package distributions to PyPI
|
|
47
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
48
|
+
|
|
49
|
+
gh-release:
|
|
50
|
+
name: "Create a github release"
|
|
51
|
+
needs: [ publish-pypi ]
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
permissions:
|
|
54
|
+
contents: write # IMPORTANT: mandatory for making GitHub Releases
|
|
55
|
+
id-token: write # IMPORTANT: mandatory for sigstore
|
|
56
|
+
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@v4
|
|
59
|
+
|
|
60
|
+
- uses: actions/setup-python@v5
|
|
61
|
+
with:
|
|
62
|
+
python-version: "3.9"
|
|
63
|
+
|
|
64
|
+
- name: "Download distribution artifacts"
|
|
65
|
+
uses: actions/download-artifact@v4
|
|
66
|
+
with:
|
|
67
|
+
name: dist
|
|
68
|
+
path: dist/
|
|
69
|
+
|
|
70
|
+
- name: "Sign the distribution artifacts with Sigstore"
|
|
71
|
+
uses: sigstore/gh-action-sigstore-python@v3.0.0
|
|
72
|
+
with:
|
|
73
|
+
inputs: ./dist/*
|
|
74
|
+
|
|
75
|
+
- run: pip install commitizen
|
|
76
|
+
|
|
77
|
+
- name: "Generate release body"
|
|
78
|
+
run: cz changelog --incremental --dry-run > note.md
|
|
79
|
+
|
|
80
|
+
- name: "Create Github release"
|
|
81
|
+
uses: ncipollo/release-action@v1
|
|
82
|
+
with:
|
|
83
|
+
artifacts: "dist/*"
|
|
84
|
+
bodyFile: "note.md"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Byte-compiled
|
|
2
|
+
**/__pycache__/***
|
|
3
|
+
|
|
4
|
+
**/*.egg-info/***
|
|
5
|
+
# Caches
|
|
6
|
+
/.*_cache
|
|
7
|
+
|
|
8
|
+
# Virtual envs
|
|
9
|
+
/*venv*
|
|
10
|
+
|
|
11
|
+
# Distribution / packaging
|
|
12
|
+
/dist
|
|
13
|
+
|
|
14
|
+
# Unit test / coverage reports
|
|
15
|
+
***/.coverage*
|
|
16
|
+
***/tests-reports/***
|
|
17
|
+
*.xml
|
|
18
|
+
.idea/***
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: local
|
|
3
|
+
hooks:
|
|
4
|
+
- id: ruff
|
|
5
|
+
name: ruff lint
|
|
6
|
+
entry: uvx ruff check --fix --exit-non-zero-on-fix
|
|
7
|
+
language: python
|
|
8
|
+
types_or: [python, pyi]
|
|
9
|
+
require_serial: true
|
|
10
|
+
stages: [pre-commit]
|
|
11
|
+
additional_dependencies:
|
|
12
|
+
- "uv>=0.5.0"
|
|
13
|
+
|
|
14
|
+
- id: ruff-format
|
|
15
|
+
name: ruff format
|
|
16
|
+
entry: uvx ruff format
|
|
17
|
+
language: python
|
|
18
|
+
types_or: [ python, pyi ]
|
|
19
|
+
require_serial: true
|
|
20
|
+
stages: [pre-commit]
|
|
21
|
+
additional_dependencies:
|
|
22
|
+
- "uv>=0.5.0"
|
|
23
|
+
|
|
24
|
+
- id: mypy
|
|
25
|
+
name: mypy
|
|
26
|
+
entry: uvx mypy
|
|
27
|
+
language: python
|
|
28
|
+
types_or: [ python, pyi ]
|
|
29
|
+
stages: [pre-push]
|
|
30
|
+
additional_dependencies:
|
|
31
|
+
- "uv>=0.5.0"
|
|
32
|
+
|
|
33
|
+
- id: tests
|
|
34
|
+
name: tests
|
|
35
|
+
entry: uvx pytest
|
|
36
|
+
language: python
|
|
37
|
+
stages: [pre-push]
|
|
38
|
+
additional_dependencies:
|
|
39
|
+
- "uv>=0.5.0"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
All notable changes to this project will be documented in this file.
|
|
3
|
+
|
|
4
|
+
## Power-events
|
|
5
|
+
|
|
6
|
+
## 1.0.0 (2024-11-24)
|
|
7
|
+
|
|
8
|
+
### :sparkles: Features
|
|
9
|
+
|
|
10
|
+
- change ValuePath
|
|
11
|
+
- raise error when value missing
|
|
12
|
+
- allow equals at None
|
|
13
|
+
- add resolver
|
|
14
|
+
- add conditions
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Mathieu LETRONE
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: power-events
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Author-email: mathieu LETRONE <mathieu.letrone@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2024 Mathieu LETRONE
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
28
|
+
Classifier: Natural Language :: English
|
|
29
|
+
Classifier: Operating System :: OS Independent
|
|
30
|
+
Classifier: Programming Language :: Python
|
|
31
|
+
Classifier: Programming Language :: Python :: 3
|
|
32
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
33
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
38
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
39
|
+
Classifier: Topic :: Utilities
|
|
40
|
+
Classifier: Typing :: Typed
|
|
41
|
+
Requires-Python: >=3.9
|
|
42
|
+
Requires-Dist: maypy>=1.1.2
|
|
43
|
+
Description-Content-Type: text/markdown
|
|
44
|
+
|
|
45
|
+
# Power-Events
|
|
46
|
+
<div align="center" style="margin:40px;">
|
|
47
|
+
<!-- --8<-- [start:overview-header] -->
|
|
48
|
+
|
|
49
|
+
[](https://github.com/MLetrone/power-events/actions/workflows/ci.yml)
|
|
50
|
+
[](https://coverage-badge.samuelcolvin.workers.dev/redirect/MLetrone/power-events)
|
|
51
|
+
[](https://www.python.org/)
|
|
52
|
+

|
|
53
|
+

|
|
54
|
+

|
|
55
|
+
|
|
56
|
+
<!-- --8<-- [end:overview-header] -->
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
Source Code: [https://github.com/MLetrone/power-events](https://github.com/MLetrone/power-events)
|
|
61
|
+
|
|
62
|
+
documentation: [https://mletrone.github.io/power-events](https://mletrone.github.io/power-events/)
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
</div>
|
|
66
|
+
<!-- --8<-- [start:overview-body] -->
|
|
67
|
+
|
|
68
|
+
_Take control of your event routing, effortlessly and tailored to your needs._
|
|
69
|
+
|
|
70
|
+
## Description
|
|
71
|
+
|
|
72
|
+
**Power-events** is a lightweight yet powerful library that manages event routing by defining routes with precise conditions,
|
|
73
|
+
inspired by FastAPI’s endpoint routing system.
|
|
74
|
+
It simplifies the organization of complex events by applying specific routing rules defined
|
|
75
|
+
by the user and enables actions to be triggered in response to events in a structured manner.
|
|
76
|
+
|
|
77
|
+
## Key features:
|
|
78
|
+
- **Syntax**: Lean to standards like Powertools or FastAPI.
|
|
79
|
+
- **Easy**: Design to be easy to read and use.
|
|
80
|
+
- **Flexible**: You can do whatever condition at any depth level in your event.
|
|
81
|
+
- **Fully tested**: 100% coverage.
|
|
82
|
+
- **Fully typed**: compatible out of the box with `mypy` !
|
|
83
|
+
- **Lightweight**
|
|
84
|
+
|
|
85
|
+
<!-- --8<-- [end:overview-body] -->
|
|
86
|
+
## installation
|
|
87
|
+
|
|
88
|
+
```shell
|
|
89
|
+
pip install power-events
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
That's all ! _Ready to use_
|
|
93
|
+
<!-- --8<-- [start:body] -->
|
|
94
|
+
## Examples
|
|
95
|
+
---
|
|
96
|
+
### Simple conditions
|
|
97
|
+
|
|
98
|
+
- create a `main.py` with:
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from typing import Any
|
|
102
|
+
from power_events import EventResolver
|
|
103
|
+
|
|
104
|
+
app = EventResolver()
|
|
105
|
+
|
|
106
|
+
@app.equal("type", "order_created")
|
|
107
|
+
def handler_order_created(event: dict[str, Any]) -> str:
|
|
108
|
+
return f"Order created: {event['order_id']}"
|
|
109
|
+
|
|
110
|
+
@app.one_of("type", ["order_update", "order_delete"])
|
|
111
|
+
def handle_order_modification(event: dict[str, Any]) -> str:
|
|
112
|
+
return f"Order modification <{event['type']}>: {event['order_id']}"
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
- use routing:
|
|
117
|
+
|
|
118
|
+
> N.B: assert is here to show which route has been called.
|
|
119
|
+
> In real condition, don't need to use it.
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
assert app.resolve({
|
|
123
|
+
"type": "order_created",
|
|
124
|
+
"order_id": "12345",
|
|
125
|
+
"user_id": "67890"
|
|
126
|
+
}) == ["Order created: 12345"]
|
|
127
|
+
# Note: `resolve` returns a list, because you can allow multiple routes for one event.
|
|
128
|
+
|
|
129
|
+
assert app.resolve({
|
|
130
|
+
"type": "order_delete",
|
|
131
|
+
"order_id": "12345",
|
|
132
|
+
"user_id": "67890"
|
|
133
|
+
})== ["Order modification <order_delete>: 12345"]
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
### Complex conditions
|
|
137
|
+
|
|
138
|
+
_in depth field condition and condition combinations_
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
from power_events import EventResolver
|
|
142
|
+
from power_events.conditions import Value, Neg
|
|
143
|
+
|
|
144
|
+
app = EventResolver()
|
|
145
|
+
|
|
146
|
+
# Order created and digital purchase.
|
|
147
|
+
@app.when(Value("type").equals("order_created") & Value("cart.is_digital").is_truthy())
|
|
148
|
+
def handle_digital_purchase(event: dict) -> str:
|
|
149
|
+
return f"The order created is a digital purchase: {event['order_id']}"
|
|
150
|
+
|
|
151
|
+
# Order created and physical.
|
|
152
|
+
@app.when(Value("type").equals("order_created") & Neg(Value("cart.is_digital").is_truthy()))
|
|
153
|
+
def handle_physical_purchase(event: dict) -> str:
|
|
154
|
+
return f"The order created is a physical purchase: {event['order_id']}"
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
assert app.resolve({
|
|
158
|
+
"type": "order_created",
|
|
159
|
+
"order_id": "12345",
|
|
160
|
+
"user_id": "67890",
|
|
161
|
+
"cart": {
|
|
162
|
+
"is_digital": True,
|
|
163
|
+
"items": [
|
|
164
|
+
"$10 voucher"
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
}) == ["The order created is a digital purchase: 12345"]
|
|
168
|
+
assert app.resolve({
|
|
169
|
+
"type": "order_created",
|
|
170
|
+
"order_id": "12345",
|
|
171
|
+
"user_id": "67890",
|
|
172
|
+
"cart": {
|
|
173
|
+
"is_digital": False,
|
|
174
|
+
"items": [
|
|
175
|
+
"keyboard"
|
|
176
|
+
]
|
|
177
|
+
}
|
|
178
|
+
}) == ["The order created is a physical purchase: 12345"]
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
It's possible to perform `OR`, `AND`, `NEG` operation over conditions.
|
|
182
|
+
<!-- --8<-- [end:body] -->
|