psycache 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.
- psycache-26.1.0/.github/AI_POLICY.md +71 -0
- psycache-26.1.0/.github/CODE_OF_CONDUCT.md +16 -0
- psycache-26.1.0/.github/CONTRIBUTING.md +241 -0
- psycache-26.1.0/.github/FUNDING.yml +5 -0
- psycache-26.1.0/.github/PULL_REQUEST_TEMPLATE.md +34 -0
- psycache-26.1.0/.github/dependabot.yml +14 -0
- psycache-26.1.0/.github/workflows/ci.yml +226 -0
- psycache-26.1.0/.github/workflows/codeql-analysis.yml +42 -0
- psycache-26.1.0/.github/workflows/pypi-package.yml +82 -0
- psycache-26.1.0/.github/workflows/zizmor.yml +33 -0
- psycache-26.1.0/.gitignore +12 -0
- psycache-26.1.0/.pre-commit-config.yaml +35 -0
- psycache-26.1.0/.python-version +1 -0
- psycache-26.1.0/CHANGELOG.md +16 -0
- psycache-26.1.0/LICENSE +19 -0
- psycache-26.1.0/PKG-INFO +381 -0
- psycache-26.1.0/README.md +343 -0
- psycache-26.1.0/conftest.py +137 -0
- psycache-26.1.0/pyproject.toml +195 -0
- psycache-26.1.0/src/psycache/__init__.py +18 -0
- psycache-26.1.0/src/psycache/__main__.py +57 -0
- psycache-26.1.0/src/psycache/_async.py +203 -0
- psycache-26.1.0/src/psycache/_durations.py +55 -0
- psycache-26.1.0/src/psycache/_sql.py +33 -0
- psycache-26.1.0/src/psycache/_sync.py +198 -0
- psycache-26.1.0/src/psycache/_tables.py +24 -0
- psycache-26.1.0/src/psycache/instrumentation/__init__.py +12 -0
- psycache-26.1.0/src/psycache/instrumentation/_spans.py +173 -0
- psycache-26.1.0/src/psycache/instrumentation/prometheus.py +156 -0
- psycache-26.1.0/src/psycache/instrumentation/sentry.py +142 -0
- psycache-26.1.0/src/psycache/psycopg_pool.py +56 -0
- psycache-26.1.0/src/psycache/py.typed +0 -0
- psycache-26.1.0/src/psycache/sqlalchemy.py +51 -0
- psycache-26.1.0/src/psycache/typing.py +154 -0
- psycache-26.1.0/tests/__init__.py +3 -0
- psycache-26.1.0/tests/test_cli.py +45 -0
- psycache-26.1.0/tests/test_maintenance.py +379 -0
- psycache-26.1.0/tests/test_psycopg_pool.py +166 -0
- psycache-26.1.0/tests/test_raw.py +63 -0
- psycache-26.1.0/tests/test_raw_async.py +103 -0
- psycache-26.1.0/tests/test_sqlalchemy.py +85 -0
- psycache-26.1.0/tests/typing/README.md +4 -0
- psycache-26.1.0/tests/typing/core.py +37 -0
- psycache-26.1.0/tests/typing/psycopg_pool.py +20 -0
- psycache-26.1.0/tests/typing/sqlalchemy.py +21 -0
- psycache-26.1.0/tox.ini +86 -0
|
@@ -0,0 +1,71 @@
|
|
|
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
|
+
> ---
|
|
21
|
+
>
|
|
22
|
+
> By submitting a pull request, you certify that:
|
|
23
|
+
>
|
|
24
|
+
> - You are the author of the contribution or have the legal right to submit it.
|
|
25
|
+
> - You either hold the copyright to the changes or have explicit legal authorization to contribute them under this project's license.
|
|
26
|
+
> - You understand the code.
|
|
27
|
+
> - You accept full responsibility for it.
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## Legal
|
|
31
|
+
|
|
32
|
+
There is ongoing legal uncertainty regarding the copyright status of LLM-generated works and their provenance.
|
|
33
|
+
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.
|
|
34
|
+
|
|
35
|
+
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.
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
## Human
|
|
39
|
+
|
|
40
|
+
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.
|
|
41
|
+
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.
|
|
42
|
+
|
|
43
|
+
Please understand that by opening low-quality pull requests you're not helping anyone.
|
|
44
|
+
Worse, you're [poisoning the open source ecosystem](https://lwn.net/Articles/1058266/) that was precarious even before the arrival of LLM tools.
|
|
45
|
+
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.
|
|
46
|
+
|
|
47
|
+
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.
|
|
48
|
+
|
|
49
|
+
This dynamic is especially pernicious because it poisons the well for mentoring new contributors which we are committed to.
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
## Summary
|
|
53
|
+
|
|
54
|
+
In practice, this means:
|
|
55
|
+
|
|
56
|
+
- Pull requests that have an LLM product listed as co-author can't be merged and will be closed without further discussion.
|
|
57
|
+
We cannot risk the copyright status of this project.
|
|
58
|
+
|
|
59
|
+
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.
|
|
60
|
+
|
|
61
|
+
- 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.
|
|
62
|
+
|
|
63
|
+
"An LLM wrote it" is **not** an acceptable response to questions or critique.
|
|
64
|
+
**If you cannot explain and defend the changes you submit, do not submit them** and open a high-quality bug report/feature request instead.
|
|
65
|
+
|
|
66
|
+
- Accounts that exercise bot-like behavior – like automated mass pull requests – will be permanently banned, whether they belong to a human or not.
|
|
67
|
+
|
|
68
|
+
- Do **not** post LLM-generated review comments – we can prompt LLMs ourselves should we desire their wisdom.
|
|
69
|
+
Do **not** post summaries unless you've fact-checked them and take responsibility for 100% of their content.
|
|
70
|
+
Remember that *all* LLM output *looks* **plausible**.
|
|
71
|
+
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,241 @@
|
|
|
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/psycache/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/psycache/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
|
+
### Postgres
|
|
51
|
+
|
|
52
|
+
The test suite requires a running Postgres 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 `psycache` with a no-password user `psycache` 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/).
|
|
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
|
+
If you're using [*direnv*](https://direnv.net), you can automate the creation of the project virtual environment with the correct Python version by adding the following `.envrc` to the project root:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
layout python python$(cat .python-version)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
or, if you like [*uv*](https://github.com/astral-sh/uv):
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
test -d .venv || (uv venv && uv pip install -e . --group dev)
|
|
79
|
+
. .venv/bin/activate
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
> [!WARNING]
|
|
83
|
+
> - **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.
|
|
84
|
+
> - **Always create a new branch off `main` for each new pull request.**
|
|
85
|
+
> Yes, you can work on `main` in your fork and submit pull requests.
|
|
86
|
+
> But this will *inevitably* lead to you not being able to synchronize your fork with upstream and having to start over.
|
|
87
|
+
|
|
88
|
+
Change into the newly created directory and after activating a virtual environment, install an editable version of this project along with its tests requirements:
|
|
89
|
+
|
|
90
|
+
```console
|
|
91
|
+
$ pip install -e . --group dev # or `uv pip install -e . --group dev`
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Now you can run the test suite:
|
|
95
|
+
|
|
96
|
+
```console
|
|
97
|
+
$ python -Im pytest
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
To run doctests:
|
|
101
|
+
|
|
102
|
+
```console
|
|
103
|
+
$ tox run -e docs-doctests
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
## Code
|
|
108
|
+
|
|
109
|
+
- Obey [PEP 8](https://peps.python.org/pep-0008/) and [PEP 257](https://peps.python.org/pep-0257/).
|
|
110
|
+
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:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
def func(x: str, y: int) -> str:
|
|
114
|
+
"""
|
|
115
|
+
Do something.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
x: A very important argument.
|
|
119
|
+
|
|
120
|
+
y:
|
|
121
|
+
Another very important argument, but its description is so long
|
|
122
|
+
that it doesn't fit on one line. So, we start the whole block on a
|
|
123
|
+
fresh new line to keep the block together.
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
The result of doing something.
|
|
127
|
+
"""
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Please note that unlike everything else, the API docstrings are still reStructuredText.
|
|
131
|
+
|
|
132
|
+
- If you add or change public APIs, tag the docstring using `.. versionadded:: 26.1.0 WHAT` or `.. versionchanged:: 26.1.0 WHAT`.
|
|
133
|
+
We follow [Calendar Versioning](https://calver.org/), so the next version will be the current with with the middle number incremented (for example, `26.1.0` -> `26.2.0`).
|
|
134
|
+
|
|
135
|
+
- We use [Ruff](https://ruff.rs/) to sort our imports and format our code with a line length of 79 characters.
|
|
136
|
+
As long as you run our full *tox* suite before committing, or install our [*pre-commit*](https://pre-commit.com/) hooks (ideally you'll do both -- see [*Local Development Environment*](#local-development-environment) above), you won't have to spend any time on formatting your code at all.
|
|
137
|
+
If you don't, CI will catch it for you -- but that seems like a waste of your time!
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
## Tests
|
|
141
|
+
|
|
142
|
+
- Write your asserts as `expected == actual` to line them up nicely, and leave an empty line before them:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
x = f()
|
|
146
|
+
|
|
147
|
+
assert 42 == x.some_attribute
|
|
148
|
+
assert "foo" == x._a_private_attribute
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
- 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`.
|
|
152
|
+
|
|
153
|
+
- Write [good test docstrings](https://jml.io/test-docstrings/).
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
## Documentation
|
|
157
|
+
|
|
158
|
+
- Use [semantic newlines] in [reStructuredText](https://www.sphinx-doc.org/en/stable/usage/restructuredtext/basics.html) (`*.rst`) and [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:
|
|
159
|
+
|
|
160
|
+
```markdown
|
|
161
|
+
This is a sentence.
|
|
162
|
+
This is another sentence.
|
|
163
|
+
|
|
164
|
+
This is a new paragraph.
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
- 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:
|
|
168
|
+
|
|
169
|
+
```markdown
|
|
170
|
+
# Main Header
|
|
171
|
+
|
|
172
|
+
Last line of previous section.
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
## Header of New Top Section
|
|
176
|
+
|
|
177
|
+
### Header of New Section
|
|
178
|
+
|
|
179
|
+
First line of new section.
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
### Changelog
|
|
184
|
+
|
|
185
|
+
If your change is interesting to end-users, there needs to be an entry in our `CHANGELOG.md`, so they can learn about it.
|
|
186
|
+
|
|
187
|
+
- The changelog follows the [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) standard.
|
|
188
|
+
Add the best-fitting section if it's missing for the current release.
|
|
189
|
+
We use the following order: `Security`, `Removed`, `Deprecated`, `Added`, `Changed`, `Fixed`.
|
|
190
|
+
|
|
191
|
+
- As with other docs, please use [semantic newlines] in the changelog.
|
|
192
|
+
|
|
193
|
+
- Make the last line a link to your pull request.
|
|
194
|
+
You probably have to open it first to know the number.
|
|
195
|
+
|
|
196
|
+
- Leave an empty line between entries, so it doesn't look like a wall of text.
|
|
197
|
+
|
|
198
|
+
- Refer to all symbols by their fully-qualified names.
|
|
199
|
+
For example, `psycache.Foo` -- not just `Foo`.
|
|
200
|
+
|
|
201
|
+
- Wrap symbols like modules, functions, or classes into backticks, so they are rendered in a `monospace font`.
|
|
202
|
+
|
|
203
|
+
- Wrap arguments into asterisks so they are *italicized* like in API documentation:
|
|
204
|
+
`Added new argument *an_argument*.`
|
|
205
|
+
|
|
206
|
+
- If you mention functions or methods, add parentheses at the end of their names:
|
|
207
|
+
`psycache.func()` or `psycache.Class.method()`.
|
|
208
|
+
This makes the changelog a lot more readable.
|
|
209
|
+
|
|
210
|
+
- Prefer simple past tense or constructions with "now".
|
|
211
|
+
In the `Added` section, you can leave out the "Added" prefix:
|
|
212
|
+
|
|
213
|
+
```markdown
|
|
214
|
+
### Added
|
|
215
|
+
|
|
216
|
+
- `psycache.func()` that does foo.
|
|
217
|
+
It's pretty cool.
|
|
218
|
+
[#1](https://github.com/hynek/psycache/pull/1)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
### Fixed
|
|
222
|
+
|
|
223
|
+
- `psycache.func()` now doesn't crash the Large Hadron Collider anymore.
|
|
224
|
+
That was a nasty bug!
|
|
225
|
+
[#2](https://github.com/hynek/psycache/pull/2)
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
## See you on GitHub!
|
|
230
|
+
|
|
231
|
+
Again, this whole file is mainly to help you to get started by codifying tribal knowledge and expectations to save you time and turnarounds.
|
|
232
|
+
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!
|
|
233
|
+
|
|
234
|
+
Please note that this project is released with a Contributor [Code of Conduct](CODE_OF_CONDUCT.md).
|
|
235
|
+
By participating in this project you agree to abide by its terms.
|
|
236
|
+
Please report any harm to [Hynek Schlawack](https://hynek.me/about/) in any way you find appropriate.
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
[semantic newlines]: https://rhodesmill.org/brandon/2012/one-sentence-per-line/
|
|
240
|
+
[llm]: AI_POLICY.md
|
|
241
|
+
[install *uv*]: https://docs.astral.sh/uv/getting-started/installation/
|
|
@@ -0,0 +1,34 @@
|
|
|
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/psycache/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/psycache/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/psycache/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/psycache/blob/main/tests/typing/>.
|
|
24
|
+
- [ ] Updated **documentation** for changed code.
|
|
25
|
+
- [ ] New functions/classes have to be added to `docs/core-concepts.md` or one of the integration guides by hand.
|
|
26
|
+
- [ ] Changed/added classes/methods/functions have appropriate `versionadded`, `versionchanged`, or `deprecated` [directives](http://www.sphinx-doc.org/en/stable/markup/para.html#directive-versionadded).
|
|
27
|
+
- The next version is the second number in the current release + 1. The first number represents the current year. So if the current version on PyPI is 26.1.0, the next version is gonna be 26.2.0. If the next version is the first in the new year, it'll be 27.1.0.
|
|
28
|
+
- [ ] Documentation in `.md` files is written using [**semantic newlines**](https://rhodesmill.org/brandon/2012/one-sentence-per-line/).
|
|
29
|
+
- [ ] Changes (and possible deprecations) are documented in the [**changelog**](https://github.com/hynek/psycache/blob/main/CHANGELOG.md).
|
|
30
|
+
|
|
31
|
+
<!--
|
|
32
|
+
If you have *any* questions to *any* of the points above, just **submit and ask**!
|
|
33
|
+
Given the ongoing AI slop wave we need to be strict about policies, but we're happy to help out fellow humans.
|
|
34
|
+
-->
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 2
|
|
3
|
+
updates:
|
|
4
|
+
- package-ecosystem: github-actions
|
|
5
|
+
directory: /
|
|
6
|
+
schedule:
|
|
7
|
+
interval: monthly
|
|
8
|
+
cooldown:
|
|
9
|
+
# https://blog.yossarian.net/2025/11/21/We-should-all-be-using-dependency-cooldowns
|
|
10
|
+
default-days: 7
|
|
11
|
+
groups:
|
|
12
|
+
github-actions:
|
|
13
|
+
patterns:
|
|
14
|
+
- "*"
|
|
@@ -0,0 +1,226 @@
|
|
|
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
|
+
PIP_DISABLE_PIP_VERSION_CHECK: "1"
|
|
13
|
+
PIP_NO_PYTHON_VERSION_WARNING: "1"
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
17
|
+
cancel-in-progress: true
|
|
18
|
+
|
|
19
|
+
permissions: {}
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
build-package:
|
|
23
|
+
name: Build & verify package
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
28
|
+
with:
|
|
29
|
+
fetch-depth: 0
|
|
30
|
+
persist-credentials: false
|
|
31
|
+
|
|
32
|
+
- uses: hynek/build-and-inspect-python-package@d44ca7d91762de7a7d5436ddae667c6da6d1c3df # v2.18.0
|
|
33
|
+
id: baipp
|
|
34
|
+
|
|
35
|
+
outputs:
|
|
36
|
+
# Used to define the matrix for tests below. The value is based on
|
|
37
|
+
# packaging metadata (trove classifiers).
|
|
38
|
+
python-versions: ${{ steps.baipp.outputs.supported_python_classifiers_json_array }}
|
|
39
|
+
|
|
40
|
+
tests:
|
|
41
|
+
name: Tests on ${{ matrix.python-version }}
|
|
42
|
+
runs-on: ubuntu-24.04 # the version affects postgres paths!
|
|
43
|
+
needs: build-package
|
|
44
|
+
|
|
45
|
+
strategy:
|
|
46
|
+
fail-fast: false
|
|
47
|
+
matrix:
|
|
48
|
+
# Created by the build-and-inspect-python-package action above.
|
|
49
|
+
python-version: ${{ fromJson(needs.build-package.outputs.python-versions) }}
|
|
50
|
+
|
|
51
|
+
env:
|
|
52
|
+
PYTHON: ${{ matrix.python-version }}
|
|
53
|
+
|
|
54
|
+
steps:
|
|
55
|
+
- name: Download pre-built packages
|
|
56
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
57
|
+
with:
|
|
58
|
+
name: Packages
|
|
59
|
+
path: dist
|
|
60
|
+
- run: |
|
|
61
|
+
tar xf dist/*.tar.gz --strip-components=1
|
|
62
|
+
rm -rf src
|
|
63
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
64
|
+
with:
|
|
65
|
+
python-version: ${{ matrix.python-version }}
|
|
66
|
+
allow-prereleases: true
|
|
67
|
+
- uses: hynek/setup-cached-uv@4300ec2180bc77d705e626a34e381b81a4772c51 # v2.5.0
|
|
68
|
+
|
|
69
|
+
- name: Start PostgreSQL
|
|
70
|
+
run: |
|
|
71
|
+
printf '%s\n' \
|
|
72
|
+
'local all all trust' \
|
|
73
|
+
'host all all 127.0.0.1/32 trust' \
|
|
74
|
+
'host all all ::1/128 trust' \
|
|
75
|
+
| sudo tee /etc/postgresql/16/main/pg_hba.conf >/dev/null
|
|
76
|
+
|
|
77
|
+
sudo systemctl start postgresql.service
|
|
78
|
+
|
|
79
|
+
until sudo -u postgres pg_isready -q; do sleep 1; done
|
|
80
|
+
|
|
81
|
+
- name: Run tests
|
|
82
|
+
run: >
|
|
83
|
+
uvx --with tox-uv tox run
|
|
84
|
+
--installpkg dist/*.whl
|
|
85
|
+
-f ${PYTHON}-tests
|
|
86
|
+
|
|
87
|
+
- name: Upload coverage data
|
|
88
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
89
|
+
with:
|
|
90
|
+
name: coverage-data-${{ matrix.python-version }}
|
|
91
|
+
path: .coverage.*
|
|
92
|
+
include-hidden-files: true
|
|
93
|
+
if-no-files-found: ignore
|
|
94
|
+
|
|
95
|
+
coverage:
|
|
96
|
+
name: Ensure 100% test coverage
|
|
97
|
+
runs-on: ubuntu-latest
|
|
98
|
+
needs: tests
|
|
99
|
+
if: always()
|
|
100
|
+
|
|
101
|
+
steps:
|
|
102
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
103
|
+
with:
|
|
104
|
+
persist-credentials: false
|
|
105
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
106
|
+
with:
|
|
107
|
+
python-version-file: .python-version
|
|
108
|
+
- uses: hynek/setup-cached-uv@4300ec2180bc77d705e626a34e381b81a4772c51 # v2.5.0
|
|
109
|
+
|
|
110
|
+
- name: Download coverage data
|
|
111
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
112
|
+
with:
|
|
113
|
+
pattern: coverage-data-*
|
|
114
|
+
merge-multiple: true
|
|
115
|
+
|
|
116
|
+
- name: Combine coverage and fail if it's <100%.
|
|
117
|
+
run: |
|
|
118
|
+
uv tool install coverage
|
|
119
|
+
|
|
120
|
+
coverage combine
|
|
121
|
+
coverage html --skip-covered --skip-empty
|
|
122
|
+
|
|
123
|
+
# Report and write to summary.
|
|
124
|
+
coverage report --format=markdown >> $GITHUB_STEP_SUMMARY
|
|
125
|
+
|
|
126
|
+
# Report again and fail if under 100%.
|
|
127
|
+
coverage report --fail-under=100
|
|
128
|
+
|
|
129
|
+
- name: Upload HTML report if check failed.
|
|
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 types using supported type checkers
|
|
138
|
+
runs-on: ubuntu-latest
|
|
139
|
+
needs: build-package
|
|
140
|
+
|
|
141
|
+
steps:
|
|
142
|
+
- name: Download pre-built packages
|
|
143
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
144
|
+
with:
|
|
145
|
+
name: Packages
|
|
146
|
+
path: dist
|
|
147
|
+
- run: tar xf dist/*.tar.gz --strip-components=1
|
|
148
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
149
|
+
with:
|
|
150
|
+
python-version-file: .python-version
|
|
151
|
+
- uses: hynek/setup-cached-uv@4300ec2180bc77d705e626a34e381b81a4772c51 # v2.5.0
|
|
152
|
+
|
|
153
|
+
- run: >
|
|
154
|
+
uvx --with tox-uv
|
|
155
|
+
tox run -f typing
|
|
156
|
+
|
|
157
|
+
docs:
|
|
158
|
+
name: Run doctests
|
|
159
|
+
needs: build-package
|
|
160
|
+
runs-on: ubuntu-latest
|
|
161
|
+
steps:
|
|
162
|
+
- name: Download pre-built packages
|
|
163
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
164
|
+
with:
|
|
165
|
+
name: Packages
|
|
166
|
+
path: dist
|
|
167
|
+
- run: tar xf dist/*.tar.gz --strip-components=1
|
|
168
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
169
|
+
with:
|
|
170
|
+
# Keep in sync with tox.ini's base_python_file.
|
|
171
|
+
python-version-file: .python-version
|
|
172
|
+
- uses: hynek/setup-cached-uv@4300ec2180bc77d705e626a34e381b81a4772c51 # v2.5.0
|
|
173
|
+
|
|
174
|
+
- name: Start PostgreSQL
|
|
175
|
+
# The README examples connect to a real database, so the doctests need
|
|
176
|
+
# a running PostgreSQL with password-less local access.
|
|
177
|
+
run: |
|
|
178
|
+
printf '%s\n' \
|
|
179
|
+
'local all all trust' \
|
|
180
|
+
'host all all 127.0.0.1/32 trust' \
|
|
181
|
+
'host all all ::1/128 trust' \
|
|
182
|
+
| sudo tee /etc/postgresql/16/main/pg_hba.conf >/dev/null
|
|
183
|
+
|
|
184
|
+
sudo systemctl start postgresql.service
|
|
185
|
+
|
|
186
|
+
until sudo -u postgres pg_isready -q; do sleep 1; done
|
|
187
|
+
|
|
188
|
+
- run: >
|
|
189
|
+
uvx --with tox-uv
|
|
190
|
+
tox run -e docs-doctests
|
|
191
|
+
|
|
192
|
+
install-dev:
|
|
193
|
+
name: Verify dev env
|
|
194
|
+
runs-on: ubuntu-latest
|
|
195
|
+
|
|
196
|
+
steps:
|
|
197
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
198
|
+
with:
|
|
199
|
+
persist-credentials: false
|
|
200
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
201
|
+
with:
|
|
202
|
+
python-version-file: .python-version
|
|
203
|
+
- uses: hynek/setup-cached-uv@4300ec2180bc77d705e626a34e381b81a4772c51 # v2.5.0
|
|
204
|
+
|
|
205
|
+
- run: uv venv
|
|
206
|
+
- run: uv pip install -e . --group dev
|
|
207
|
+
|
|
208
|
+
- run: .venv/bin/python -Ic 'from importlib.metadata import version; print(version("psycache"))'
|
|
209
|
+
|
|
210
|
+
required-checks-pass:
|
|
211
|
+
name: Ensure everything required is passing for branch protection
|
|
212
|
+
if: always()
|
|
213
|
+
|
|
214
|
+
needs:
|
|
215
|
+
- coverage
|
|
216
|
+
- install-dev
|
|
217
|
+
- typing
|
|
218
|
+
- docs
|
|
219
|
+
|
|
220
|
+
runs-on: ubuntu-latest
|
|
221
|
+
|
|
222
|
+
steps:
|
|
223
|
+
- name: Decide whether the needed jobs succeeded or failed
|
|
224
|
+
uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2
|
|
225
|
+
with:
|
|
226
|
+
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@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
30
|
+
with:
|
|
31
|
+
persist-credentials: false
|
|
32
|
+
|
|
33
|
+
- name: Initialize CodeQL
|
|
34
|
+
uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
|
|
35
|
+
with:
|
|
36
|
+
languages: ${{ matrix.language }}
|
|
37
|
+
|
|
38
|
+
- name: Autobuild
|
|
39
|
+
uses: github/codeql-action/autobuild@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
|
|
40
|
+
|
|
41
|
+
- name: Perform CodeQL Analysis
|
|
42
|
+
uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
|