pgbg 26.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 (62) hide show
  1. pgbg-26.1.0/.github/AI_POLICY.md +77 -0
  2. pgbg-26.1.0/.github/CODE_OF_CONDUCT.md +16 -0
  3. pgbg-26.1.0/.github/CONTRIBUTING.md +232 -0
  4. pgbg-26.1.0/.github/FUNDING.yml +4 -0
  5. pgbg-26.1.0/.github/PULL_REQUEST_TEMPLATE.md +31 -0
  6. pgbg-26.1.0/.github/SECURITY.md +15 -0
  7. pgbg-26.1.0/.github/dependabot.yml +13 -0
  8. pgbg-26.1.0/.github/workflows/ci.yml +217 -0
  9. pgbg-26.1.0/.github/workflows/codeql-analysis.yml +42 -0
  10. pgbg-26.1.0/.github/workflows/pypi-package.yml +82 -0
  11. pgbg-26.1.0/.github/workflows/zizmor.yml +33 -0
  12. pgbg-26.1.0/.gitignore +11 -0
  13. pgbg-26.1.0/.pre-commit-config.yaml +27 -0
  14. pgbg-26.1.0/.python-version +1 -0
  15. pgbg-26.1.0/.readthedocs.yaml +27 -0
  16. pgbg-26.1.0/CHANGELOG.md +23 -0
  17. pgbg-26.1.0/LICENSE +19 -0
  18. pgbg-26.1.0/PKG-INFO +93 -0
  19. pgbg-26.1.0/README.md +64 -0
  20. pgbg-26.1.0/codebook.toml +4 -0
  21. pgbg-26.1.0/conftest.py +149 -0
  22. pgbg-26.1.0/docs/api-sqlalchemy.md +9 -0
  23. pgbg-26.1.0/docs/api-typing.md +11 -0
  24. pgbg-26.1.0/docs/api.md +51 -0
  25. pgbg-26.1.0/docs/assets/javascript/readthedocs.js +8 -0
  26. pgbg-26.1.0/docs/dispatch.md +43 -0
  27. pgbg-26.1.0/docs/examples/dispatch.py +76 -0
  28. pgbg-26.1.0/docs/examples/elected_thread.py +59 -0
  29. pgbg-26.1.0/docs/examples/indie_thread.py +42 -0
  30. pgbg-26.1.0/docs/examples/indie_with_init.py +56 -0
  31. pgbg-26.1.0/docs/glossary.md +195 -0
  32. pgbg-26.1.0/docs/index.md +9 -0
  33. pgbg-26.1.0/docs/leader-election.md +97 -0
  34. pgbg-26.1.0/docs/observability.md +82 -0
  35. pgbg-26.1.0/docs/services.md +118 -0
  36. pgbg-26.1.0/docs/tutorial.md +187 -0
  37. pgbg-26.1.0/pyproject.toml +253 -0
  38. pgbg-26.1.0/src/pgbg/__init__.py +31 -0
  39. pgbg-26.1.0/src/pgbg/__main__.py +86 -0
  40. pgbg-26.1.0/src/pgbg/_backoff.py +33 -0
  41. pgbg-26.1.0/src/pgbg/_dispatcher.py +474 -0
  42. pgbg-26.1.0/src/pgbg/_services.py +1213 -0
  43. pgbg-26.1.0/src/pgbg/_supervisor.py +195 -0
  44. pgbg-26.1.0/src/pgbg/_tables.py +67 -0
  45. pgbg-26.1.0/src/pgbg/exceptions.py +8 -0
  46. pgbg-26.1.0/src/pgbg/py.typed +0 -0
  47. pgbg-26.1.0/src/pgbg/sqlalchemy.py +189 -0
  48. pgbg-26.1.0/src/pgbg/typing.py +168 -0
  49. pgbg-26.1.0/tests/__init__.py +0 -0
  50. pgbg-26.1.0/tests/test_backoff.py +78 -0
  51. pgbg-26.1.0/tests/test_cli.py +130 -0
  52. pgbg-26.1.0/tests/test_dispatcher.py +570 -0
  53. pgbg-26.1.0/tests/test_services.py +2059 -0
  54. pgbg-26.1.0/tests/test_sqlalchemy.py +201 -0
  55. pgbg-26.1.0/tests/test_supervisor.py +565 -0
  56. pgbg-26.1.0/tox.ini +76 -0
  57. pgbg-26.1.0/typing_tests/README.md +4 -0
  58. pgbg-26.1.0/typing_tests/__init__.py +0 -0
  59. pgbg-26.1.0/typing_tests/core.py +209 -0
  60. pgbg-26.1.0/typing_tests/sqlalchemy.py +59 -0
  61. pgbg-26.1.0/uv.lock +1370 -0
  62. pgbg-26.1.0/zensical.toml +153 -0
@@ -0,0 +1,77 @@
1
+ # Generative AI / LLM Policy
2
+
3
+ We appreciate that we can't realistically police how you author your pull requests, which includes whether you employ large-language model (LLM)-based development tools.
4
+ So, we don't.
5
+
6
+ However, due to both legal and human reasons, we have to establish boundaries.
7
+
8
+ > [!CAUTION]
9
+ > **TL;DR:**
10
+ > - We take the responsibility for this project very seriously and we expect you to take your responsibility for your contributions seriously, too.
11
+ > This used to be a given, but it changed now that a pull request is just one prompt away.
12
+ >
13
+ > - Every contribution has to be backed by a human who unequivocally owns the copyright for all changes.
14
+ > No LLM bots in `Co-authored-by:`s.
15
+ >
16
+ > - DoS-by-slop leads to a permanent ban.
17
+ >
18
+ > - Absolutely **no** unsupervised agentic tools like OpenClaw.
19
+ >
20
+ > - Do **not** trigger bots like Copilot on this repository.
21
+ > GitHub won't let us block Copilot, but it's a great way to tell you didn't read this.
22
+ >
23
+ > ---
24
+ >
25
+ > By submitting a pull request, you certify that:
26
+ >
27
+ > - You are the author of the contribution or have the legal right to submit it.
28
+ >
29
+ > - You either hold the copyright to the changes or have explicit legal authorization to contribute them under this project's license.
30
+ >
31
+ > - You understand the code.
32
+ >
33
+ > - You accept full responsibility for it.
34
+
35
+
36
+ ## Legal
37
+
38
+ There is ongoing legal uncertainty regarding the copyright status of LLM-generated works and their provenance.
39
+ Since we do not have a formal [Contributor License Agreement](https://en.wikipedia.org/wiki/Contributor_license_agreement) (CLA), you retain your copyright to your changes to this project.
40
+
41
+ Therefore, allowing contributions by LLMs has unpredictable consequences for the copyright status of this project – even when leaving aside possible copyright violations due to plagiarism.
42
+
43
+
44
+ ## Human
45
+
46
+ As the makers of software that is used by millions of people worldwide and with a reputation for high-quality maintenance, we take our responsibility to our users very seriously.
47
+ No matter what LLM vendors or boosters on LinkedIn tell you, we have to manually review every change before merging, because it's **our responsibility** to keep the project stable.
48
+
49
+ Please understand that by opening low-quality pull requests you're not helping anyone.
50
+ Worse, you're [poisoning the open source ecosystem](https://lwn.net/Articles/1058266/) that was precarious even before the arrival of LLM tools.
51
+ Having to wade through plausible-looking-but-low-quality pull requests and trying to determine which ones are legit is extremely demoralizing and has already burned out many good maintainers.
52
+
53
+ Put bluntly, we have no time or interest to become part of your vibe coding loop where you drop LLM slop at our door, we spend time and energy to review it, and you just feed it back into the LLM for another iteration.
54
+
55
+ This dynamic is especially pernicious because it poisons the well for mentoring new contributors which we are committed to.
56
+
57
+
58
+ ## Summary
59
+
60
+ In practice, this means:
61
+
62
+ - Pull requests that have an LLM product listed as co-author can't be merged and will be closed without further discussion.
63
+ We cannot risk the copyright status of this project.
64
+
65
+ If you used LLM tools during development, you may still submit – but you must remove any LLM co-author tags and take full ownership of every line.
66
+
67
+ - By submitting a pull request, **you** take full **technical and legal** responsibility for the contents of the pull request and promise that **you** hold the copyright for the changes submitted.
68
+
69
+ "An LLM wrote it" is **not** an acceptable response to questions or critique.
70
+ **If you cannot explain and defend the changes you submit, do not submit them** and open a high-quality bug report/feature request instead.
71
+
72
+ - Accounts that exercise bot-like behavior – like automated mass pull requests – will be permanently banned, whether they belong to a human or not.
73
+
74
+ - Do **not** post LLM-generated review comments – we can prompt LLMs ourselves should we desire their wisdom.
75
+ Do **not** post summaries unless you've fact-checked them and take responsibility for 100% of their content.
76
+ Remember that *all* LLM output *looks* **plausible**.
77
+ When using these tools, it's **your** responsibility to ensure that it's also **correct** and has a reasonable signal-to-noise ratio.
@@ -0,0 +1,16 @@
1
+ # Code of Conduct
2
+
3
+ While not being a [Python Software Foundation](https://www.python.org/psf-landing/) project, everyone interacting in this project is expected to follow the [PSF Code of Conduct](https://policies.python.org/python.org/code-of-conduct/).
4
+
5
+ In general, this means that everyone is expected to be **open**, **considerate**, and **respectful** of others no matter what their position is within the project.
6
+
7
+
8
+ ## Enforcement
9
+
10
+ We take Code of Conduct violations seriously, and will act to ensure our spaces are welcoming, inclusive, and professional environments to communicate in.
11
+
12
+ If you need to raise a Code of Conduct report, you may do so privately by email to [Hynek Schlawack](mailto:hs@ox.cx).
13
+
14
+ Reports will be treated confidentially.
15
+
16
+ Alternately you can make a [report to the Python Software Foundation](https://policies.python.org/python.org/code-of-conduct/Procedures-for-Reporting-Incidents/).
@@ -0,0 +1,232 @@
1
+ # How To Contribute
2
+
3
+ > [!IMPORTANT]
4
+ > - This document is mainly to help you to get started by codifying tribal knowledge and expectations and make it more accessible to everyone.
5
+ > But don't be afraid to open half-finished PRs and ask questions if something is unclear!
6
+ >
7
+ > - If you use LLM / "AI" tools for your contributions, please read and follow our [_Generative AI / LLM Policy_][llm].
8
+
9
+
10
+ ## Workflow
11
+
12
+ > [!WARNING]
13
+ > Before starting to work on **feature** pull requests, **please** discuss your idea with us on the [Ideas board](https://github.com/hynek/pgbg/discussions/categories/ideas) to save you time and effort!
14
+
15
+ First off, thank you for considering to contribute!
16
+ It's people like *you* who make this project such a great tool for everyone.
17
+
18
+ - No contribution is too small!
19
+ Please submit as many fixes for typos and grammar bloopers as you can!
20
+
21
+ - **Only contribute code that you fully understand.**
22
+ See also our [AI policy][llm].
23
+
24
+ - Very relatedly, our pull request check list is our mandatory [Van Halen test](https://en.wikipedia.org/wiki/Van_Halen_test).
25
+ Sadly, the current state of the world has forced us into being stricter about policies – sorry fellow humans!
26
+
27
+ - Try to limit each pull request to *one* change only.
28
+
29
+ - Since we squash on merge, it's up to you how you handle updates to the `main` branch.
30
+ Whether you prefer to rebase on `main` or merge `main` into your branch, do whatever is more comfortable for you.
31
+
32
+ - *Always* add tests and docs for your code.
33
+ This is a hard rule; patches with missing tests or documentation won't be merged.
34
+
35
+ - Consider updating [`CHANGELOG.md`](../CHANGELOG.md) to reflect the changes as observed by people using this library.
36
+
37
+ - Make sure your changes pass our [CI](https://github.com/hynek/pgbg/actions).
38
+ You won't get any feedback until it's green unless you ask for it.
39
+ For the CI to pass, the coverage must be 100%.
40
+ If you have problems to test something, open anyway and ask for advice.
41
+ In some situations, we may agree to add an `# pragma: no cover`.
42
+
43
+ - Once you've addressed review feedback, make sure to bump the pull request with a short note, so we know you're done.
44
+
45
+ - Don't break [backwards-compatibility](SECURITY.md).
46
+
47
+
48
+ ## Local Development Environment
49
+
50
+ ### PostgreSQL
51
+
52
+ The test suite requires a running PostgreSQL database that is accessible via the `postgresql://postgres@127.0.0.1/postgres` DSN (no password).
53
+ It will use it only to create a database `pgbg` with a no-password user `pgbg` that is used for the actual tests.
54
+
55
+
56
+ ### Python
57
+
58
+ First, **fork** the repository on GitHub.
59
+ Make sure to **uncheck** the `Copy the main branch only` radio button on the `Create a new fork` page.
60
+ If you don't, our test suite will fail because we use Git tags for packaging.
61
+
62
+ Finally, **clone** it using one of the alternatives that you can copy-paste by pressing the big green button labeled `<> Code`.
63
+
64
+ You can (and should) run our test suite using [*tox*](https://tox.wiki/), and keep in mind that `tox run-parallel` is much faster than `tox run`.
65
+ However, you'll probably want a more traditional environment as well.
66
+
67
+ We recommend using the Python version from the `.python-version` file in the project's root directory, because that's the one that is used in the CI by default, too.
68
+
69
+ We use a fully-locked development environment based on [*uv*](https://docs.astral.sh/uv/) and a checked-in `uv.lock`, so the easiest way to get started is to [install *uv*] and run `uv run pytest` to run the tests immediately.
70
+
71
+ If you'd like a traditional virtual environment, run `uv sync` and it will create one named `.venv` with the correct Python version and all the dependencies installed – including *tox*.
72
+
73
+ If you're using [*direnv*](https://direnv.net), you can automate the creation and activation of the project's virtual environment with the correct Python version by adding the following `.envrc` to the project root:
74
+
75
+ ```bash
76
+ uv sync
77
+ . .venv/bin/activate
78
+ ```
79
+
80
+ > [!WARNING]
81
+ > - **Before** you start working on a new pull request, use the "*Sync fork*" button in GitHub's web UI to ensure your fork is up to date.
82
+ > - **Always create a new branch off `main` for each new pull request.**
83
+ > Yes, you can work on `main` in your fork and submit pull requests.
84
+ > But this will *inevitably* lead to you not being able to synchronize your fork with upstream and having to start over.
85
+
86
+ When working on the documentation, use:
87
+
88
+ ```console
89
+ $ tox run -e docs-serve
90
+ ```
91
+
92
+ This will build the documentation, watch for changes, and rebuild it whenever you save a file.
93
+
94
+ To just build the documentation and exit immediately use:
95
+
96
+ ```console
97
+ $ tox run -e docs-build
98
+ ```
99
+
100
+ You will find the built documentation in `site`.
101
+
102
+
103
+ ## Code
104
+
105
+ - Obey [PEP 8](https://peps.python.org/pep-0008/) and [PEP 257](https://peps.python.org/pep-0257/).
106
+ We use the `"""`-on-separate-lines style for docstrings with [Napoleon](https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html)-style API documentation:
107
+
108
+ ```python
109
+ def func(x: str, y: int) -> str:
110
+ """
111
+ Do something.
112
+
113
+ Args:
114
+ x: A very important argument.
115
+
116
+ y:
117
+ Another very important argument, but its description is so long
118
+ that it doesn't fit on one line. So, we start the whole block on
119
+ a fresh new line to keep the block together.
120
+
121
+ Returns:
122
+ The result of doing something.
123
+ """
124
+ ```
125
+
126
+ - We use [Ruff](https://ruff.rs/) to sort our imports and format our code with a line length of 79 characters.
127
+ As long as you run our full *tox* suite before committing, you won't have to spend any time on formatting your code at all.
128
+ If you don't, CI will catch it for you – but that seems like a waste of everyone's time!
129
+
130
+
131
+ ## Tests
132
+
133
+ - Write your asserts as `expected == actual` to line them up nicely, and leave an empty line before them:
134
+
135
+ ```python
136
+ x = f()
137
+
138
+ assert 42 == x.some_attribute
139
+ assert "foo" == x._a_private_attribute
140
+ ```
141
+
142
+ - You can run the test suite runs with all (optional) dependencies against all supported Python versions just as it will in our CI by running `tox`.
143
+
144
+ - Write [good test docstrings](https://jml.io/test-docstrings/).
145
+
146
+
147
+ ## Documentation
148
+
149
+ - Use [semantic newlines] in [Markdown](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax) (`*.md`) files:
150
+
151
+ ```markdown
152
+ This is a sentence.
153
+ This is another sentence.
154
+
155
+ This is a new paragraph.
156
+ ```
157
+
158
+ - If you start a new section, add two blank lines before and one blank line after the header except if two headers follow immediately after each other:
159
+
160
+ ```markdown
161
+ # Main Header
162
+
163
+ Last line of previous section.
164
+
165
+
166
+ ## Header of New Top Section
167
+
168
+ ### Header of New Section
169
+
170
+ First line of new section.
171
+ ```
172
+
173
+
174
+ ### Changelog
175
+
176
+ If your change is interesting to end-users, there needs to be an entry in our `CHANGELOG.md`, so they can learn about it.
177
+
178
+ - The changelog follows the [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) standard.
179
+ Add the best-fitting section if it's missing for the current release.
180
+ We use the following order: `Security`, `Removed`, `Deprecated`, `Added`, `Changed`, `Fixed`.
181
+
182
+ - As with other docs, use [semantic newlines] in the changelog.
183
+
184
+ - Make the last line a link to your pull request.
185
+ You probably have to open it first to know the number.
186
+
187
+ - Leave an empty line between entries, so it doesn't look like a wall of text.
188
+
189
+ - Refer to all symbols by their fully-qualified names.
190
+ For example, `pgbg.Foo` – not just `Foo`.
191
+
192
+ - Wrap symbols like modules, functions, or classes into backticks, so they are rendered in a `monospace font`.
193
+
194
+ - Wrap arguments into asterisks so they are *italicized* like in API documentation:
195
+ `Added new argument *an_argument*.`
196
+
197
+ - If you mention functions or methods, add parentheses at the end of their names:
198
+ `pgbg.func()` or `pgbg.Class.method()`.
199
+ This makes the changelog a lot more readable.
200
+
201
+ - Prefer simple past tense or constructions with "now".
202
+ In the `Added` section, you can leave out the "Added" prefix:
203
+
204
+ ```markdown
205
+ ### Added
206
+
207
+ - `pgbg.func()` that does foo.
208
+ It's pretty cool.
209
+ [#1](https://github.com/hynek/pgbg/pull/1)
210
+
211
+
212
+ ### Fixed
213
+
214
+ - `pgbg.func()` now doesn't crash the Large Hadron Collider anymore.
215
+ That was a nasty bug!
216
+ [#2](https://github.com/hynek/pgbg/pull/2)
217
+ ```
218
+
219
+
220
+ ## See You on GitHub!
221
+
222
+ Again, this whole file is mainly to help you to get started by codifying tribal knowledge and expectations to save you time and turnarounds.
223
+ It is **not** meant to be a barrier to entry, so don't be afraid to open half-finished PRs and ask questions if something is unclear!
224
+
225
+ Please note that this project is released with a Contributor [Code of Conduct](CODE_OF_CONDUCT.md).
226
+ By participating in this project you agree to abide by its terms.
227
+ Please report any harm to [Hynek Schlawack](https://hynek.me/about/) in any way you find appropriate.
228
+
229
+
230
+ [semantic newlines]: https://rhodesmill.org/brandon/2012/one-sentence-per-line/
231
+ [llm]: https://github.com/hynek/pgbg/blob/main/.github/AI_POLICY.md
232
+ [install *uv*]: https://docs.astral.sh/uv/getting-started/installation/
@@ -0,0 +1,4 @@
1
+ ---
2
+ github: hynek
3
+ thanks_dev: u/gh/hynek
4
+ custom: https://hynek.me/say-thanks/
@@ -0,0 +1,31 @@
1
+ # Summary
2
+
3
+ <!-- Please tell us what your pull request is about here. -->
4
+
5
+
6
+ # Pull Request Check List
7
+
8
+ <!--
9
+ This list is our brown M&M test:
10
+ Ignoring -- or even deleting -- leads to instant closing of this pull request.
11
+ The only exceptions are pure documentation fixes.
12
+
13
+ Please read our [contribution guide](https://github.com/hynek/pgbg/blob/main/.github/CONTRIBUTING.md) at least once; it will save you unnecessary review cycles!
14
+
15
+ You may check boxes that don't apply to your pull request to indicate that there isn't anything left to do.
16
+ -->
17
+
18
+ - [ ] I acknowledge this project's [**AI policy**](https://github.com/hynek/pgbg/blob/main/.github/AI_POLICY.md).
19
+ - [ ] Typos aside (please, always submit typo fixes!), I understand that this pull request may be **closed** in case there was **no [previous discussion](https://github.com/hynek/pgbg/discussions/categories/ideas)**.
20
+ - [ ] This pull request is [**not** from my `main` branch](https://hynek.me/articles/pull-requests-branch/).
21
+ - Consider granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork), so maintainers can fix minor issues themselves without pestering you.
22
+ - [ ] There's **tests** for all new and changed code.
23
+ - [ ] **New APIs** are added to our typing tests at <https://github.com/hynek/pgbg/blob/main/typing_tests/>.
24
+ - [ ] Updated **documentation** for changed code.
25
+ - [ ] Documentation in `.md` files is written using [**semantic newlines**](https://rhodesmill.org/brandon/2012/one-sentence-per-line/).
26
+ - [ ] Changes (and possible deprecations) are documented in the [**changelog**](https://github.com/hynek/pgbg/blob/main/CHANGELOG.md).
27
+
28
+ <!--
29
+ If you have *any* questions to *any* of the points above, just **submit and ask**!
30
+ Given the ongoing AI slop wave we need to be strict about policies, but we're happy to help out fellow humans.
31
+ -->
@@ -0,0 +1,15 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ We currently only support the latest version.
6
+
7
+ Until the package is pronounced stable, there are no backwards-compatibility guarantees.
8
+ The code has been in production for years, but we want some leeway to adjust APIs in the early days.
9
+
10
+
11
+ ## Reporting a Vulnerability
12
+
13
+ If you think you found a vulnerability, please use [GitHub's security advisory form](https://github.com/hynek/pgbg/security/advisories/new), or email Hynek Schlawack at <hs@ox.cx>.
14
+
15
+ If you submit AI slop, you will be permanently blocked.
@@ -0,0 +1,13 @@
1
+ ---
2
+ version: 2
3
+ updates:
4
+ - package-ecosystem: github-actions
5
+ directory: /
6
+ schedule:
7
+ interval: monthly
8
+ cooldown:
9
+ default-days: 7
10
+ groups:
11
+ github-actions:
12
+ patterns:
13
+ - "*"
@@ -0,0 +1,217 @@
1
+ ---
2
+ name: CI
3
+
4
+ on:
5
+ push:
6
+ branches: [main]
7
+ pull_request:
8
+ workflow_dispatch:
9
+
10
+ env:
11
+ FORCE_COLOR: "1" # Make tools pretty.
12
+ UV_LOCKED: "1" # Crash loudly on uv.lock vs pyproject.toml inconsistencies
13
+
14
+ concurrency:
15
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
16
+ cancel-in-progress: true
17
+
18
+ permissions: {}
19
+
20
+ jobs:
21
+ build-package:
22
+ name: Build & verify package
23
+ runs-on: ubuntu-latest
24
+
25
+ steps:
26
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
27
+ with:
28
+ fetch-depth: 0
29
+ persist-credentials: false
30
+
31
+ - uses: hynek/build-and-inspect-python-package@2abe76da66d0a6a4a227101f9348ee855797cfa5 # v3.0.1
32
+ id: baipp
33
+
34
+ outputs:
35
+ # Used to define the matrix for tests below. The value is based on
36
+ # packaging metadata (trove classifiers).
37
+ python-versions: ${{ steps.baipp.outputs.supported_python_classifiers_json_array }}
38
+
39
+ tests:
40
+ name: Tests on Python ${{ matrix.python-version }}
41
+ runs-on: ubuntu-24.04 # the version affects postgres paths!
42
+ needs: build-package
43
+
44
+ strategy:
45
+ fail-fast: false
46
+ matrix:
47
+ # Created by the build-and-inspect-python-package action above.
48
+ python-version: ${{ fromJson(needs.build-package.outputs.python-versions) }}
49
+
50
+ env:
51
+ PYTHON: ${{ matrix.python-version }}
52
+
53
+ steps:
54
+ - name: Download built packages
55
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
56
+ with:
57
+ name: Packages
58
+ path: dist
59
+
60
+ - name: Extract source distribution
61
+ run: |
62
+ tar xf dist/*.tar.gz --strip-components=1
63
+ rm -rf src
64
+
65
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
66
+ with:
67
+ python-version: ${{ matrix.python-version }}
68
+ allow-prereleases: true
69
+
70
+ - uses: hynek/setup-cached-uv@34e35d30f1ebc7421a5cc733bca38dcc62603960 # v2.6.0
71
+
72
+ - name: Start PostgreSQL
73
+ run: |
74
+ printf '%s\n' \
75
+ 'local all all trust' \
76
+ 'host all all 127.0.0.1/32 trust' \
77
+ 'host all all ::1/128 trust' \
78
+ | sudo tee /etc/postgresql/16/main/pg_hba.conf >/dev/null
79
+
80
+ sudo systemctl start postgresql.service
81
+
82
+ until sudo -u postgres pg_isready -q; do sleep 1; done
83
+
84
+ - name: Run tests
85
+ run: >
86
+ uv run --only-group tox
87
+ tox run
88
+ --installpkg dist/*.whl
89
+ -f ${PYTHON}-tests
90
+
91
+ - name: Upload coverage data
92
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
93
+ with:
94
+ name: coverage-data-${{ matrix.python-version }}
95
+ path: .coverage.*
96
+ include-hidden-files: true
97
+ if-no-files-found: error
98
+
99
+ coverage:
100
+ name: Require 100% coverage
101
+ runs-on: ubuntu-latest
102
+ needs: tests
103
+ if: always()
104
+
105
+ steps:
106
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
107
+ with:
108
+ persist-credentials: false
109
+
110
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
111
+ with:
112
+ python-version-file: .python-version
113
+
114
+ - uses: hynek/setup-cached-uv@34e35d30f1ebc7421a5cc733bca38dcc62603960 # v2.6.0
115
+
116
+ - name: Download coverage data
117
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
118
+ with:
119
+ pattern: coverage-data-*
120
+ merge-multiple: true
121
+
122
+ - name: Combine and report coverage
123
+ run: |
124
+ uv run --only-group cov coverage combine
125
+ uv run --only-group cov coverage html --skip-covered --skip-empty
126
+ uv run --only-group cov coverage report --format=markdown >> "$GITHUB_STEP_SUMMARY"
127
+ uv run --only-group cov coverage report --fail-under=100
128
+
129
+ - name: Upload HTML report after a failure
130
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
131
+ with:
132
+ name: html-report
133
+ path: htmlcov
134
+ if: ${{ failure() }}
135
+
136
+ typing:
137
+ name: Check public types
138
+ runs-on: ubuntu-latest
139
+ needs: build-package
140
+
141
+ steps:
142
+ - name: Download built packages
143
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
144
+ with:
145
+ name: Packages
146
+ path: dist
147
+
148
+ - name: Extract source distribution
149
+ run: tar xf dist/*.tar.gz --strip-components=1
150
+
151
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
152
+ with:
153
+ python-version-file: .python-version
154
+
155
+ - uses: hynek/setup-cached-uv@34e35d30f1ebc7421a5cc733bca38dcc62603960 # v2.6.0
156
+
157
+ - name: Run type checkers
158
+ run: >
159
+ uv run --only-group tox
160
+ tox run
161
+ --installpkg dist/*.whl
162
+ -f typing
163
+
164
+ lint:
165
+ name: Lint repository
166
+ runs-on: ubuntu-latest
167
+
168
+ steps:
169
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
170
+ with:
171
+ persist-credentials: false
172
+
173
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
174
+ with:
175
+ python-version-file: .python-version
176
+
177
+ - uses: hynek/setup-cached-uv@34e35d30f1ebc7421a5cc733bca38dcc62603960 # v2.6.0
178
+
179
+ - name: Run linters
180
+ run: >
181
+ uv run --only-group tox
182
+ tox run
183
+ -f lint
184
+
185
+ install-dev:
186
+ name: Check locked development environment
187
+ runs-on: ubuntu-latest
188
+
189
+ steps:
190
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
191
+ with:
192
+ persist-credentials: false
193
+
194
+ - uses: hynek/setup-cached-uv@34e35d30f1ebc7421a5cc733bca38dcc62603960 # v2.6.0
195
+
196
+ - run: uv sync
197
+
198
+ - name: Import public modules
199
+ run: |
200
+ .venv/bin/python -Ic 'import pgbg'
201
+ .venv/bin/python -Ic 'import pgbg.sqlalchemy'
202
+
203
+ required-checks-pass:
204
+ name: Require all checks
205
+ if: always()
206
+ needs:
207
+ - coverage
208
+ - install-dev
209
+ - lint
210
+ - typing
211
+ runs-on: ubuntu-latest
212
+
213
+ steps:
214
+ - name: Evaluate required jobs
215
+ uses: re-actors/alls-green@b5b5b37504aa4183270bd3d855c52a67f212be35 # v1.3.0
216
+ with:
217
+ jobs: ${{ toJSON(needs) }}
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: CodeQL
3
+
4
+ on:
5
+ schedule:
6
+ - cron: "41 3 * * 6"
7
+ workflow_dispatch:
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}
11
+ cancel-in-progress: true
12
+
13
+ permissions: {}
14
+
15
+ jobs:
16
+ analyze:
17
+ name: Analyze
18
+ runs-on: ubuntu-latest
19
+ permissions:
20
+ security-events: write # necessary according to docs
21
+
22
+ strategy:
23
+ fail-fast: false
24
+ matrix:
25
+ language: [python]
26
+
27
+ steps:
28
+ - name: Checkout repository
29
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
30
+ with:
31
+ persist-credentials: false
32
+
33
+ - name: Initialize CodeQL
34
+ uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
35
+ with:
36
+ languages: ${{ matrix.language }}
37
+
38
+ - name: Autobuild
39
+ uses: github/codeql-action/autobuild@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
40
+
41
+ - name: Perform CodeQL Analysis
42
+ uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9