pytest-graphql 0.1.0a1__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.
- pytest_graphql-0.1.0a1/.gitignore +221 -0
- pytest_graphql-0.1.0a1/CHANGELOG.md +80 -0
- pytest_graphql-0.1.0a1/CONTRIBUTING.md +184 -0
- pytest_graphql-0.1.0a1/LICENSE +21 -0
- pytest_graphql-0.1.0a1/PKG-INFO +120 -0
- pytest_graphql-0.1.0a1/README.md +82 -0
- pytest_graphql-0.1.0a1/pyproject.toml +134 -0
- pytest_graphql-0.1.0a1/scripts/changelog_section.py +143 -0
- pytest_graphql-0.1.0a1/scripts/check_artifacts.py +319 -0
- pytest_graphql-0.1.0a1/scripts/check_core_purity.py +1792 -0
- pytest_graphql-0.1.0a1/scripts/check_no_pytest.py +168 -0
- pytest_graphql-0.1.0a1/scripts/check_publication_hygiene.py +489 -0
- pytest_graphql-0.1.0a1/scripts/git_hook_checks.py +3317 -0
- pytest_graphql-0.1.0a1/scripts/verify_release.py +700 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/__init__.py +62 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/__init__.py +7 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/auth.py +89 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/client.py +921 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/diagnostics.py +2352 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/errors.py +551 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/headers.py +40 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/lifecycle.py +1119 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/middleware.py +73 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/naming.py +107 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/operation.py +464 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/response/__init__.py +23 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/response/envelope.py +158 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/response/materialize.py +418 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/response/node.py +221 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/response/types.py +118 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/schema/__init__.py +3 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/schema/cache.py +32 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/schema/info.py +56 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/schema/source.py +112 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/selection/__init__.py +11 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/selection/builder.py +822 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/selection/model.py +202 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/selection/normalize.py +1423 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/selection/policy.py +261 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/transport/__init__.py +10 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/transport/base.py +79 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/transport/httpx_transport.py +1020 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/_core/validation.py +147 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/plugin/__init__.py +143 -0
- pytest_graphql-0.1.0a1/src/pytest_graphql/py.typed +0 -0
- pytest_graphql-0.1.0a1/tests/__init__.py +1 -0
- pytest_graphql-0.1.0a1/tests/schema/__init__.py +5 -0
- pytest_graphql-0.1.0a1/tests/schema/corpus/README.md +29 -0
- pytest_graphql-0.1.0a1/tests/schema/corpus/__init__.py +6 -0
- pytest_graphql-0.1.0a1/tests/schema/corpus/manifest.json +12 -0
- pytest_graphql-0.1.0a1/tests/schema/corpus/measure.py +546 -0
- pytest_graphql-0.1.0a1/tests/schema/corpus/sdl/catalog.graphql +141 -0
- pytest_graphql-0.1.0a1/tests/schema/corpus/sdl/feed.graphql +99 -0
- pytest_graphql-0.1.0a1/tests/schema/fake_transport.py +98 -0
- pytest_graphql-0.1.0a1/tests/schema/resolvers.py +438 -0
- pytest_graphql-0.1.0a1/tests/schema/sdl.graphql +453 -0
- pytest_graphql-0.1.0a1/tests/typing/derivable_transport.py +53 -0
- pytest_graphql-0.1.0a1/tests/typing/owned_acquisition.py +46 -0
- pytest_graphql-0.1.0a1/tests/typing/test_typing_fixtures.py +113 -0
- pytest_graphql-0.1.0a1/tests/unit/__init__.py +1 -0
- pytest_graphql-0.1.0a1/tests/unit/conftest.py +117 -0
- pytest_graphql-0.1.0a1/tests/unit/lifecycle_harness.py +625 -0
- pytest_graphql-0.1.0a1/tests/unit/lifecycle_products.py +241 -0
- pytest_graphql-0.1.0a1/tests/unit/local_http_server.py +120 -0
- pytest_graphql-0.1.0a1/tests/unit/plugin_probe.py +13 -0
- pytest_graphql-0.1.0a1/tests/unit/test_client.py +1368 -0
- pytest_graphql-0.1.0a1/tests/unit/test_client_over.py +163 -0
- pytest_graphql-0.1.0a1/tests/unit/test_cookie_isolation.py +279 -0
- pytest_graphql-0.1.0a1/tests/unit/test_core_purity.py +412 -0
- pytest_graphql-0.1.0a1/tests/unit/test_corpus_calibration.py +268 -0
- pytest_graphql-0.1.0a1/tests/unit/test_diagnostics.py +1804 -0
- pytest_graphql-0.1.0a1/tests/unit/test_errors.py +195 -0
- pytest_graphql-0.1.0a1/tests/unit/test_factory_lifecycle.py +784 -0
- pytest_graphql-0.1.0a1/tests/unit/test_hostile_schema.py +222 -0
- pytest_graphql-0.1.0a1/tests/unit/test_httpx_transport.py +1667 -0
- pytest_graphql-0.1.0a1/tests/unit/test_leak_suite.py +702 -0
- pytest_graphql-0.1.0a1/tests/unit/test_lifecycle_harness.py +219 -0
- pytest_graphql-0.1.0a1/tests/unit/test_lifecycle_interrupts.py +584 -0
- pytest_graphql-0.1.0a1/tests/unit/test_lifecycle_refusals.py +539 -0
- pytest_graphql-0.1.0a1/tests/unit/test_lifecycle_report.py +459 -0
- pytest_graphql-0.1.0a1/tests/unit/test_lifecycle_sites.py +661 -0
- pytest_graphql-0.1.0a1/tests/unit/test_naming.py +101 -0
- pytest_graphql-0.1.0a1/tests/unit/test_omission_records.py +663 -0
- pytest_graphql-0.1.0a1/tests/unit/test_operation.py +566 -0
- pytest_graphql-0.1.0a1/tests/unit/test_plugin_lifecycle.py +418 -0
- pytest_graphql-0.1.0a1/tests/unit/test_public_api.py +92 -0
- pytest_graphql-0.1.0a1/tests/unit/test_recorder.py +451 -0
- pytest_graphql-0.1.0a1/tests/unit/test_response.py +757 -0
- pytest_graphql-0.1.0a1/tests/unit/test_schema_cache.py +40 -0
- pytest_graphql-0.1.0a1/tests/unit/test_schema_info.py +64 -0
- pytest_graphql-0.1.0a1/tests/unit/test_schema_source.py +111 -0
- pytest_graphql-0.1.0a1/tests/unit/test_scripts.py +68 -0
- pytest_graphql-0.1.0a1/tests/unit/test_selection_builder.py +852 -0
- pytest_graphql-0.1.0a1/tests/unit/test_selection_model.py +119 -0
- pytest_graphql-0.1.0a1/tests/unit/test_selection_normalize.py +2854 -0
- pytest_graphql-0.1.0a1/tests/unit/test_selection_policy.py +304 -0
- pytest_graphql-0.1.0a1/tests/unit/test_selection_property.py +245 -0
- pytest_graphql-0.1.0a1/tests/unit/test_socket_guard.py +100 -0
- pytest_graphql-0.1.0a1/tests/unit/test_transport_base.py +106 -0
- pytest_graphql-0.1.0a1/tests/unit/test_validation.py +170 -0
- pytest_graphql-0.1.0a1/tests/unit/test_version.py +19 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
# Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
# uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
# poetry.lock
|
|
109
|
+
# poetry.toml
|
|
110
|
+
|
|
111
|
+
# pdm
|
|
112
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
113
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
114
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
115
|
+
# pdm.lock
|
|
116
|
+
# pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# pixi
|
|
121
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
122
|
+
# pixi.lock
|
|
123
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
124
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
125
|
+
.pixi
|
|
126
|
+
|
|
127
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
128
|
+
__pypackages__/
|
|
129
|
+
|
|
130
|
+
# Celery stuff
|
|
131
|
+
celerybeat-schedule
|
|
132
|
+
celerybeat.pid
|
|
133
|
+
|
|
134
|
+
# Redis
|
|
135
|
+
*.rdb
|
|
136
|
+
*.aof
|
|
137
|
+
*.pid
|
|
138
|
+
|
|
139
|
+
# RabbitMQ
|
|
140
|
+
mnesia/
|
|
141
|
+
rabbitmq/
|
|
142
|
+
rabbitmq-data/
|
|
143
|
+
|
|
144
|
+
# ActiveMQ
|
|
145
|
+
activemq-data/
|
|
146
|
+
|
|
147
|
+
# SageMath parsed files
|
|
148
|
+
*.sage.py
|
|
149
|
+
|
|
150
|
+
# Environments
|
|
151
|
+
.env
|
|
152
|
+
.envrc
|
|
153
|
+
.venv
|
|
154
|
+
env/
|
|
155
|
+
venv/
|
|
156
|
+
ENV/
|
|
157
|
+
env.bak/
|
|
158
|
+
venv.bak/
|
|
159
|
+
|
|
160
|
+
# Spyder project settings
|
|
161
|
+
.spyderproject
|
|
162
|
+
.spyproject
|
|
163
|
+
|
|
164
|
+
# Rope project settings
|
|
165
|
+
.ropeproject
|
|
166
|
+
|
|
167
|
+
# mkdocs documentation
|
|
168
|
+
/site
|
|
169
|
+
|
|
170
|
+
# mypy
|
|
171
|
+
.mypy_cache/
|
|
172
|
+
.dmypy.json
|
|
173
|
+
dmypy.json
|
|
174
|
+
|
|
175
|
+
# Pyre type checker
|
|
176
|
+
.pyre/
|
|
177
|
+
|
|
178
|
+
# pytype static type analyzer
|
|
179
|
+
.pytype/
|
|
180
|
+
|
|
181
|
+
# Cython debug symbols
|
|
182
|
+
cython_debug/
|
|
183
|
+
|
|
184
|
+
# PyCharm
|
|
185
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
186
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
187
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
188
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
189
|
+
# .idea/
|
|
190
|
+
|
|
191
|
+
# Abstra
|
|
192
|
+
# Abstra is an AI-powered process automation framework.
|
|
193
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
194
|
+
# Learn more at https://abstra.io/docs
|
|
195
|
+
.abstra/
|
|
196
|
+
|
|
197
|
+
# Visual Studio Code
|
|
198
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
199
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
200
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
201
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
202
|
+
# .vscode/
|
|
203
|
+
# Temporary file for partial code execution
|
|
204
|
+
tempCodeRunnerFile.py
|
|
205
|
+
|
|
206
|
+
# Ruff stuff:
|
|
207
|
+
.ruff_cache/
|
|
208
|
+
|
|
209
|
+
# PyPI configuration file
|
|
210
|
+
.pypirc
|
|
211
|
+
|
|
212
|
+
# Marimo
|
|
213
|
+
marimo/_static/
|
|
214
|
+
marimo/_lsp/
|
|
215
|
+
__marimo__/
|
|
216
|
+
|
|
217
|
+
# Streamlit
|
|
218
|
+
.streamlit/secrets.toml
|
|
219
|
+
|
|
220
|
+
# Local agent coordination state (review handoff logs), repository root only
|
|
221
|
+
/tmp/
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
|
|
7
|
+
from `1.0.0` onward. While the version is `0.x`, the API may change between minor
|
|
8
|
+
versions. Every change is recorded here with a migration note, and no deprecation
|
|
9
|
+
cycle is promised.
|
|
10
|
+
|
|
11
|
+
## [Unreleased]
|
|
12
|
+
|
|
13
|
+
## [0.1.0a1] - 2026-10-03
|
|
14
|
+
|
|
15
|
+
First alpha. It contains a working client, transport, response model and one
|
|
16
|
+
pytest fixture.
|
|
17
|
+
|
|
18
|
+
It requires `graphql-core` 3.2. graphql-core 3.3 is not supported yet, and the
|
|
19
|
+
dependency is declared as `>=3.2,<3.3` so that an install never selects it.
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- `GraphQLClient`, `ClientConfig` and `build_client()`. `query()` and
|
|
24
|
+
`mutation()` call an operation by name and build its selection set from the
|
|
25
|
+
schema. `execute()` sends a raw document and returns the response. Names are
|
|
26
|
+
snake_case in Python and the schema's own spelling on the wire.
|
|
27
|
+
- Automatic selection with depth, field count and cycle limits, set through
|
|
28
|
+
`SelectionPolicy` and `CyclePolicy`. Explicit selections use `Selection`,
|
|
29
|
+
`Field` and `AUTO`. A field left out of an automatic selection is recorded,
|
|
30
|
+
not dropped silently.
|
|
31
|
+
- Local validation of each operation against the schema before it is sent, on
|
|
32
|
+
by default. `validate=False` turns it off. Variables are always checked
|
|
33
|
+
against their declared types.
|
|
34
|
+
- Schema loading through `IntrospectionSource` or `SDLFileSource`.
|
|
35
|
+
- `HttpxTransport`, behind the `Transport` protocol. Requests are always a JSON
|
|
36
|
+
`POST`. Timeouts, connect retries and the response size are bounded. Redirects
|
|
37
|
+
are not followed, and proxy and other environment settings are ignored unless
|
|
38
|
+
`trust_env=True`.
|
|
39
|
+
- Connection isolation with the default `HttpxTransport`. The test clients of
|
|
40
|
+
one pytest session share one connection pool, and a clone shares the pool of
|
|
41
|
+
the client it came from. Each `build_client()` call without `transport=`
|
|
42
|
+
creates its own pool. Every such client has its own cookie jar. Under the
|
|
43
|
+
default `cookie_scope="none"`, no cookie survives a call. A transport you
|
|
44
|
+
supply, through `build_client(transport=...)` or an overridden
|
|
45
|
+
`gql_transport` fixture, keeps its own connection and cookie behavior.
|
|
46
|
+
- `GraphQLResponse`, `Node` and `NodeList`. Data is converted using the schema,
|
|
47
|
+
and errors and partial data raise unless that is turned off.
|
|
48
|
+
- Diagnostics. `DiagnosticSnapshot` and `as_curl()` describe a call with
|
|
49
|
+
headers, variables and known credential values redacted. Recorded calls are
|
|
50
|
+
bounded, and truncation is always stated.
|
|
51
|
+
- `Auth`, `BearerAuth` and `HeaderAuth`, and the `Middleware` protocol with
|
|
52
|
+
`BaseMiddleware`. `with_headers()`, `with_auth()`, `as_()` and `anonymous()`
|
|
53
|
+
return a client with another identity.
|
|
54
|
+
- Ownership rules for closing resources. Closing a client closes what it owns,
|
|
55
|
+
exactly once. A failure while building a client closes everything built so
|
|
56
|
+
far.
|
|
57
|
+
- The pytest fixtures `gql_url`, `gql_transport` and `gql`, and the
|
|
58
|
+
`--gql-url` flag. The schema loads once per session. Each test gets its own
|
|
59
|
+
client, which is closed after the test, whether it passed or failed.
|
|
60
|
+
- Packaging skeleton: `pyproject.toml` with a hatchling backend, PEP 621
|
|
61
|
+
metadata and a `src/` layout, the `pytest_graphql` package with `__version__`
|
|
62
|
+
and `py.typed`, and the `pytest11` entry point.
|
|
63
|
+
- Tooling configuration: ruff lint and format, `mypy --strict` on `src/`, and
|
|
64
|
+
pytest defaults.
|
|
65
|
+
- `scripts/check_core_purity.py`, which fails when any module outside the
|
|
66
|
+
pytest plugin package imports pytest.
|
|
67
|
+
- The `test` workflow, running the representative CI matrix on Linux, the test
|
|
68
|
+
suite on macOS and Windows at the newest supported Python, the core purity
|
|
69
|
+
check and the no-pytest install job.
|
|
70
|
+
- The `release` workflow, which builds one artifact set, records a digest for
|
|
71
|
+
every file, runs the artifact checks, and verifies the release back from
|
|
72
|
+
TestPyPI before any upload to PyPI. It publishes nothing until the first
|
|
73
|
+
release gate.
|
|
74
|
+
- `CONTRIBUTING.md` with the development setup and the release checklist.
|
|
75
|
+
- `requirements/build.in` and a pinned `requirements/build.txt` covering the
|
|
76
|
+
build backend and its dependencies, used both as build constraints for the
|
|
77
|
+
release build and as the environment for the sdist install-back.
|
|
78
|
+
|
|
79
|
+
[Unreleased]: https://github.com/skhomenko/pytest-graphql/compare/v0.1.0a1...HEAD
|
|
80
|
+
[0.1.0a1]: https://github.com/skhomenko/pytest-graphql/releases/tag/v0.1.0a1
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
## Development setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
git clone git@github.com:skhomenko/pytest-graphql.git
|
|
7
|
+
cd pytest-graphql
|
|
8
|
+
uv sync --all-extras
|
|
9
|
+
git config core.hooksPath .githooks
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
The hooks are tracked in `.githooks/` and do nothing until that last command
|
|
13
|
+
runs. A linked worktree needs the same setting of its own.
|
|
14
|
+
|
|
15
|
+
## Checks
|
|
16
|
+
|
|
17
|
+
Run all of these before you open a pull request. CI runs the same set.
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
uv run ruff check .
|
|
21
|
+
uv run ruff format --check .
|
|
22
|
+
uv run mypy --strict src/
|
|
23
|
+
uv run pytest -q
|
|
24
|
+
python3 scripts/check_core_purity.py
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`scripts/` holds contributor tooling that runs on the standard library alone, so
|
|
28
|
+
those scripts work before the project environment exists. Each one has a
|
|
29
|
+
`--self-test` mode, and the test suite runs it.
|
|
30
|
+
|
|
31
|
+
Text intended for publication is scanned separately:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
python3 scripts/check_publication_hygiene.py README.md CHANGELOG.md
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Layout rules
|
|
38
|
+
|
|
39
|
+
- Library code lives in `src/pytest_graphql/`.
|
|
40
|
+
- The pytest layer is confined to `src/pytest_graphql/plugin/`. No module
|
|
41
|
+
outside that package may import pytest. `scripts/check_core_purity.py`
|
|
42
|
+
enforces this, and CI fails when it reports a finding.
|
|
43
|
+
- Tests live in `tests/`. A unit test never opens a non-loopback socket.
|
|
44
|
+
|
|
45
|
+
## Branches and commits
|
|
46
|
+
|
|
47
|
+
Branch names use a type prefix and a short hyphenated description: `feat/`,
|
|
48
|
+
`fix/`, `docs/`, `chore/`, `refactor/`, `test/` or `security/`.
|
|
49
|
+
|
|
50
|
+
Commit subjects use conventional-commits prefixes and stay at or under 72
|
|
51
|
+
characters. Body lines wrap at 72. The commit-message hook enforces both, and
|
|
52
|
+
`docs/reference/COMMIT_MESSAGE_RULES.md` states exactly how a line is measured.
|
|
53
|
+
Never bypass a hook.
|
|
54
|
+
|
|
55
|
+
## Supported versions
|
|
56
|
+
|
|
57
|
+
The supported set is Python 3.10 through 3.14 with pytest 7.4 or newer. That
|
|
58
|
+
range is the compatibility promise and it is what the dependency metadata
|
|
59
|
+
declares.
|
|
60
|
+
|
|
61
|
+
CI does not run the whole cross product. It runs one job per row of the
|
|
62
|
+
representative matrix in the compatibility section of
|
|
63
|
+
`docs/reference/DESIGN_DECISIONS.md`. Those rows are a sample of the supported
|
|
64
|
+
range, never a narrower supported set. Adding or removing a row is one change
|
|
65
|
+
that edits that table and `.github/workflows/test.yml` together.
|
|
66
|
+
|
|
67
|
+
Linux, macOS and Windows are supported. The matrix rows run on Linux. Two more
|
|
68
|
+
jobs run the test suite on macOS and on Windows at the newest supported Python.
|
|
69
|
+
The same section states that rule.
|
|
70
|
+
|
|
71
|
+
`requires-python` declares both ends of the range, `>=3.10,<3.15`. Raising the
|
|
72
|
+
ceiling means editing that section, `pyproject.toml` and the matrix together,
|
|
73
|
+
then running `uv lock`.
|
|
74
|
+
|
|
75
|
+
## Pinned build tooling
|
|
76
|
+
|
|
77
|
+
Two programs run during a release build, and both are pinned so the reviewed
|
|
78
|
+
tree selects them.
|
|
79
|
+
|
|
80
|
+
- The uv version lives in the `UV_VERSION` variable at the top of each workflow.
|
|
81
|
+
Dependabot moves action SHAs but not this value, so bump it by commit.
|
|
82
|
+
- `requirements/build.txt` pins the build backend and its own dependencies.
|
|
83
|
+
`requirements/build.in` holds the direct requirement. Regenerate the pinned
|
|
84
|
+
file with:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
uv pip compile --universal --python-version 3.10 requirements/build.in \
|
|
88
|
+
-o requirements/build.txt
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The release build passes that file to `uv build --build-constraints`, and the
|
|
92
|
+
sdist install-back job installs it before building with isolation disabled.
|
|
93
|
+
|
|
94
|
+
## Release checklist
|
|
95
|
+
|
|
96
|
+
Publication happens at three gates. The release machinery exists from the first
|
|
97
|
+
milestone and publishes nothing before the alpha gate.
|
|
98
|
+
|
|
99
|
+
| Gate | Version | Requires |
|
|
100
|
+
|---|---|---|
|
|
101
|
+
| Alpha | `0.1.0a1` | Working client, transport, response model and one fixture |
|
|
102
|
+
| Beta | `0.1.0b1` | Complete pytest plugin |
|
|
103
|
+
| Stable | `0.1.0` | Complete documentation and release acceptance |
|
|
104
|
+
|
|
105
|
+
Every gate runs the same steps. Steps 1 to 6 are the contributor's. Steps 7 and
|
|
106
|
+
8 are the maintainer's, and no agent performs them.
|
|
107
|
+
|
|
108
|
+
1. Confirm the branch is green.
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
uv run ruff check . && uv run ruff format --check . \
|
|
112
|
+
&& uv run mypy --strict src/ && uv run pytest -q
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
2. Set the version in one place and check it.
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
$EDITOR src/pytest_graphql/__init__.py
|
|
119
|
+
uv run python -c "import pytest_graphql; print(pytest_graphql.__version__)"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
3. Move the `Unreleased` entries into a dated section for that version in
|
|
123
|
+
`CHANGELOG.md`, and scan the text that will be published.
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
python3 scripts/check_publication_hygiene.py README.md CHANGELOG.md
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
4. Merge the release branch, then tag the merge commit. The tag is `v` followed
|
|
130
|
+
by the exact version. The release workflow refuses a tag that disagrees with
|
|
131
|
+
`__version__`.
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
git tag "v$(uv run python -c 'import pytest_graphql; print(pytest_graphql.__version__)')"
|
|
135
|
+
git push origin --tags
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
5. Watch the `release` workflow. It builds one artifact set, records a digest
|
|
139
|
+
for every file, and runs the artifact checks: `twine check`, PEP 621
|
|
140
|
+
metadata completeness, long-description rendering, wheel and sdist contents,
|
|
141
|
+
and `__version__` agreeing with the tag.
|
|
142
|
+
|
|
143
|
+
6. Before the first gate the workflow stops there, leaving the artifact set
|
|
144
|
+
built, checked and retained. The upload jobs are gated on the repository
|
|
145
|
+
variable `RELEASE_PUBLISH`, which is unset until the maintainer opens the
|
|
146
|
+
alpha gate. From that point the run continues into the upload jobs, which
|
|
147
|
+
wait for review in the protected `pypi` environment.
|
|
148
|
+
|
|
149
|
+
7. Approve the TestPyPI upload. The workflow then enumerates that release
|
|
150
|
+
through the TestPyPI index, compares the complete remote file set with the
|
|
151
|
+
build manifest in both directions, fetches each file by its index URL,
|
|
152
|
+
rechecks every digest, and installs and tests the wheel and the sdist in
|
|
153
|
+
separate clean environments.
|
|
154
|
+
|
|
155
|
+
8. Approve the PyPI upload. It uploads the same files that TestPyPI verified.
|
|
156
|
+
Nothing is rebuilt between the two indexes, because a rebuild is a different
|
|
157
|
+
artifact.
|
|
158
|
+
|
|
159
|
+
Two properties of the indexes shape this checklist. A version can be uploaded
|
|
160
|
+
once per index and cannot be replaced, only yanked, so a failed check burns that
|
|
161
|
+
version number and the next attempt increments it. Before `0.1.0` exists, no
|
|
162
|
+
stable version satisfies `pytest-graphql`, so an ordinary unpinned install can
|
|
163
|
+
select `0.1.0a1`. Publishing the alpha to PyPI therefore exposes it to ordinary
|
|
164
|
+
installs, and the maintainer accepts that exposure at the gate. The alternative
|
|
165
|
+
is to keep the alpha on TestPyPI until a stable version exists.
|
|
166
|
+
|
|
167
|
+
Trusted publishing is configured as a pending publisher on PyPI and on TestPyPI,
|
|
168
|
+
so no upload token is stored. The token exchange is first exercised at the alpha
|
|
169
|
+
gate, because a pending publisher cannot be tested without a real upload.
|
|
170
|
+
|
|
171
|
+
### Repository configuration
|
|
172
|
+
|
|
173
|
+
These settings live in GitHub and on the two indexes, not in the repository, so
|
|
174
|
+
the maintainer applies them once. The release workflow assumes all of them.
|
|
175
|
+
|
|
176
|
+
| Where | Setting |
|
|
177
|
+
|---|---|
|
|
178
|
+
| PyPI | A pending publisher for `pytest-graphql`, owner `skhomenko`, repository `pytest-graphql`, workflow `release.yml`, environment `pypi` |
|
|
179
|
+
| TestPyPI | The same pending publisher, with the same values |
|
|
180
|
+
| GitHub environment `pypi` | Protected, with a required reviewer. Both upload jobs run in it |
|
|
181
|
+
| GitHub variable `RELEASE_PUBLISH` | Unset until the alpha gate. Set it to `true` to let the upload jobs run |
|
|
182
|
+
|
|
183
|
+
No upload token is stored anywhere. The install-back job runs outside the
|
|
184
|
+
environment and holds no publishing credential of any kind.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sergii Khomenko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: pytest-graphql
|
|
3
|
+
Version: 0.1.0a1
|
|
4
|
+
Summary: Schema-aware GraphQL API testing for pytest: a GraphQL client, an httpx transport and a pytest fixture.
|
|
5
|
+
Project-URL: Documentation, https://skhomenko.github.io/pytest-graphql/
|
|
6
|
+
Project-URL: Source, https://github.com/skhomenko/pytest-graphql
|
|
7
|
+
Project-URL: Changelog, https://github.com/skhomenko/pytest-graphql/blob/main/CHANGELOG.md
|
|
8
|
+
Project-URL: Issues, https://github.com/skhomenko/pytest-graphql/issues
|
|
9
|
+
Author: Sergii Khomenko
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: api,graphql,integration,pytest,testing
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Framework :: Pytest
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
|
+
Classifier: Topic :: Software Development :: Testing
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: <3.15,>=3.10
|
|
26
|
+
Requires-Dist: certifi
|
|
27
|
+
Requires-Dist: graphql-core<3.3,>=3.2
|
|
28
|
+
Requires-Dist: httpx<1,>=0.27
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: coverage[toml]>=7.4; extra == 'dev'
|
|
31
|
+
Requires-Dist: hypothesis>=6.100; extra == 'dev'
|
|
32
|
+
Requires-Dist: mypy>=1.11; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest>=7.4; extra == 'dev'
|
|
34
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
35
|
+
Provides-Extra: pytest
|
|
36
|
+
Requires-Dist: pytest>=7.4; extra == 'pytest'
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
|
|
39
|
+
# pytest-graphql
|
|
40
|
+
|
|
41
|
+
Schema-aware GraphQL API testing for pytest.
|
|
42
|
+
|
|
43
|
+
## Status
|
|
44
|
+
|
|
45
|
+
Alpha. This release contains a working client, an `httpx` transport, a response
|
|
46
|
+
model and one pytest fixture. The API may still change before `0.1.0`.
|
|
47
|
+
|
|
48
|
+
What `0.1.0a1` contains:
|
|
49
|
+
|
|
50
|
+
- `GraphQLClient` and `build_client()`. The client reads your schema and builds
|
|
51
|
+
the selection set for an operation. By default it checks the operation
|
|
52
|
+
against the schema before it sends anything, and `validate=False` turns that
|
|
53
|
+
check off. Arguments and fields are snake_case in Python and use the schema's
|
|
54
|
+
own names on the wire.
|
|
55
|
+
- An `httpx` transport with explicit timeout, retry and response size limits.
|
|
56
|
+
With this transport, tests share one connection pool and each client keeps
|
|
57
|
+
its own cookie jar. A transport you supply manages its own connections and
|
|
58
|
+
cookies.
|
|
59
|
+
- A response model. Failures carry a redacted summary of the request.
|
|
60
|
+
`RequestInfo.as_curl()`, available to middleware, renders a `curl` command
|
|
61
|
+
that reproduces a request, with credentials replaced by placeholders.
|
|
62
|
+
- Bearer and header auth, and request middleware.
|
|
63
|
+
- The pytest fixtures `gql`, `gql_url` and `gql_transport`, and the
|
|
64
|
+
`--gql-url` flag. The schema loads once per session, and each test gets its
|
|
65
|
+
own client.
|
|
66
|
+
|
|
67
|
+
Not in this release yet: ini options, environment variables and hooks, response
|
|
68
|
+
matching, fake data, error assertions and polling.
|
|
69
|
+
|
|
70
|
+
The changelog records what each release contains:
|
|
71
|
+
https://github.com/skhomenko/pytest-graphql/blob/main/CHANGELOG.md
|
|
72
|
+
|
|
73
|
+
## Usage
|
|
74
|
+
|
|
75
|
+
With pytest, pass the endpoint on the command line:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
pytest --gql-url=http://localhost:8000/graphql
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
def test_user_has_a_name(gql):
|
|
83
|
+
user = gql.query("user", id="123")
|
|
84
|
+
assert user.name
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
For a URL known only at run time, override the `gql_url` fixture in your
|
|
88
|
+
`conftest.py`. The `--gql-url` flag still wins when both are given.
|
|
89
|
+
|
|
90
|
+
Without pytest, use `build_client()`, and close the client when you are done:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from pytest_graphql import build_client
|
|
94
|
+
|
|
95
|
+
with build_client(url="http://localhost:8000/graphql") as gql:
|
|
96
|
+
user = gql.query("user", id="123")
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Install
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
pip install pytest-graphql
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The required dependencies are `graphql-core`, `httpx`, and `certifi`. `pytest`
|
|
106
|
+
is optional, so the client can be used outside a test suite:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
pip install "pytest-graphql[pytest]"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Supported versions
|
|
113
|
+
|
|
114
|
+
Python 3.10 through 3.14, with pytest 7.4 or newer when the pytest extra is
|
|
115
|
+
installed. CI tests a representative sample of that range rather than the whole
|
|
116
|
+
cross product.
|
|
117
|
+
|
|
118
|
+
## License
|
|
119
|
+
|
|
120
|
+
MIT. See https://github.com/skhomenko/pytest-graphql/blob/main/LICENSE
|