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.
- pgbg-26.1.0/.github/AI_POLICY.md +77 -0
- pgbg-26.1.0/.github/CODE_OF_CONDUCT.md +16 -0
- pgbg-26.1.0/.github/CONTRIBUTING.md +232 -0
- pgbg-26.1.0/.github/FUNDING.yml +4 -0
- pgbg-26.1.0/.github/PULL_REQUEST_TEMPLATE.md +31 -0
- pgbg-26.1.0/.github/SECURITY.md +15 -0
- pgbg-26.1.0/.github/dependabot.yml +13 -0
- pgbg-26.1.0/.github/workflows/ci.yml +217 -0
- pgbg-26.1.0/.github/workflows/codeql-analysis.yml +42 -0
- pgbg-26.1.0/.github/workflows/pypi-package.yml +82 -0
- pgbg-26.1.0/.github/workflows/zizmor.yml +33 -0
- pgbg-26.1.0/.gitignore +11 -0
- pgbg-26.1.0/.pre-commit-config.yaml +27 -0
- pgbg-26.1.0/.python-version +1 -0
- pgbg-26.1.0/.readthedocs.yaml +27 -0
- pgbg-26.1.0/CHANGELOG.md +23 -0
- pgbg-26.1.0/LICENSE +19 -0
- pgbg-26.1.0/PKG-INFO +93 -0
- pgbg-26.1.0/README.md +64 -0
- pgbg-26.1.0/codebook.toml +4 -0
- pgbg-26.1.0/conftest.py +149 -0
- pgbg-26.1.0/docs/api-sqlalchemy.md +9 -0
- pgbg-26.1.0/docs/api-typing.md +11 -0
- pgbg-26.1.0/docs/api.md +51 -0
- pgbg-26.1.0/docs/assets/javascript/readthedocs.js +8 -0
- pgbg-26.1.0/docs/dispatch.md +43 -0
- pgbg-26.1.0/docs/examples/dispatch.py +76 -0
- pgbg-26.1.0/docs/examples/elected_thread.py +59 -0
- pgbg-26.1.0/docs/examples/indie_thread.py +42 -0
- pgbg-26.1.0/docs/examples/indie_with_init.py +56 -0
- pgbg-26.1.0/docs/glossary.md +195 -0
- pgbg-26.1.0/docs/index.md +9 -0
- pgbg-26.1.0/docs/leader-election.md +97 -0
- pgbg-26.1.0/docs/observability.md +82 -0
- pgbg-26.1.0/docs/services.md +118 -0
- pgbg-26.1.0/docs/tutorial.md +187 -0
- pgbg-26.1.0/pyproject.toml +253 -0
- pgbg-26.1.0/src/pgbg/__init__.py +31 -0
- pgbg-26.1.0/src/pgbg/__main__.py +86 -0
- pgbg-26.1.0/src/pgbg/_backoff.py +33 -0
- pgbg-26.1.0/src/pgbg/_dispatcher.py +474 -0
- pgbg-26.1.0/src/pgbg/_services.py +1213 -0
- pgbg-26.1.0/src/pgbg/_supervisor.py +195 -0
- pgbg-26.1.0/src/pgbg/_tables.py +67 -0
- pgbg-26.1.0/src/pgbg/exceptions.py +8 -0
- pgbg-26.1.0/src/pgbg/py.typed +0 -0
- pgbg-26.1.0/src/pgbg/sqlalchemy.py +189 -0
- pgbg-26.1.0/src/pgbg/typing.py +168 -0
- pgbg-26.1.0/tests/__init__.py +0 -0
- pgbg-26.1.0/tests/test_backoff.py +78 -0
- pgbg-26.1.0/tests/test_cli.py +130 -0
- pgbg-26.1.0/tests/test_dispatcher.py +570 -0
- pgbg-26.1.0/tests/test_services.py +2059 -0
- pgbg-26.1.0/tests/test_sqlalchemy.py +201 -0
- pgbg-26.1.0/tests/test_supervisor.py +565 -0
- pgbg-26.1.0/tox.ini +76 -0
- pgbg-26.1.0/typing_tests/README.md +4 -0
- pgbg-26.1.0/typing_tests/__init__.py +0 -0
- pgbg-26.1.0/typing_tests/core.py +209 -0
- pgbg-26.1.0/typing_tests/sqlalchemy.py +59 -0
- pgbg-26.1.0/uv.lock +1370 -0
- 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,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,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
|