pypi-sdk 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. pypi_sdk-1.0.0/.github/workflows/ci.yml +40 -0
  2. pypi_sdk-1.0.0/.github/workflows/publish.yml +64 -0
  3. pypi_sdk-1.0.0/AGENTS.MD +39 -0
  4. pypi_sdk-1.0.0/CHANGELOG.md +23 -0
  5. pypi_sdk-1.0.0/CLAUDE.md +14 -0
  6. pypi_sdk-1.0.0/CODE_OF_CONDUCT.md +14 -0
  7. pypi_sdk-1.0.0/CONTRIBUTING.md +77 -0
  8. pypi_sdk-1.0.0/LICENSE.md +21 -0
  9. pypi_sdk-1.0.0/PKG-INFO +190 -0
  10. pypi_sdk-1.0.0/README.md +167 -0
  11. pypi_sdk-1.0.0/SECURITY.md +27 -0
  12. pypi_sdk-1.0.0/benchmarks/benchcore_cases.py +51 -0
  13. pypi_sdk-1.0.0/benchmarks/test_models.py +41 -0
  14. pypi_sdk-1.0.0/docs/api.md +52 -0
  15. pypi_sdk-1.0.0/docs/architecture.md +24 -0
  16. pypi_sdk-1.0.0/docs/changelog.md +4 -0
  17. pypi_sdk-1.0.0/docs/compatibility.md +31 -0
  18. pypi_sdk-1.0.0/docs/configuration.md +25 -0
  19. pypi_sdk-1.0.0/docs/development.md +41 -0
  20. pypi_sdk-1.0.0/docs/errors.md +20 -0
  21. pypi_sdk-1.0.0/docs/index.md +27 -0
  22. pypi_sdk-1.0.0/docs/publishing.md +67 -0
  23. pypi_sdk-1.0.0/docs/quickstart.md +64 -0
  24. pypi_sdk-1.0.0/docs/releasing.md +26 -0
  25. pypi_sdk-1.0.0/docs/roadmap.md +21 -0
  26. pypi_sdk-1.0.0/examples/publish.yml +47 -0
  27. pypi_sdk-1.0.0/mkdocs.yml +38 -0
  28. pypi_sdk-1.0.0/pyproject.toml +106 -0
  29. pypi_sdk-1.0.0/pyproject.toml.orig +94 -0
  30. pypi_sdk-1.0.0/src/pypi_sdk/__init__.py +62 -0
  31. pypi_sdk-1.0.0/src/pypi_sdk/cli.py +48 -0
  32. pypi_sdk-1.0.0/src/pypi_sdk/client.py +151 -0
  33. pypi_sdk-1.0.0/src/pypi_sdk/config.py +42 -0
  34. pypi_sdk-1.0.0/src/pypi_sdk/constants.py +7 -0
  35. pypi_sdk-1.0.0/src/pypi_sdk/errors.py +50 -0
  36. pypi_sdk-1.0.0/src/pypi_sdk/models.py +97 -0
  37. pypi_sdk-1.0.0/src/pypi_sdk/publish.py +79 -0
  38. pypi_sdk-1.0.0/src/pypi_sdk/py.typed +0 -0
  39. pypi_sdk-1.0.0/src/pypi_sdk/services.py +143 -0
  40. pypi_sdk-1.0.0/tests/test_api.py +299 -0
  41. pypi_sdk-1.0.0/tests/test_cli.py +70 -0
  42. pypi_sdk-1.0.0/tests/test_publish.py +62 -0
@@ -0,0 +1,40 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ checks:
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ - uses: actions/setup-python@v5
20
+ with:
21
+ python-version: ${{ matrix.python-version }}
22
+ - uses: astral-sh/setup-uv@v6
23
+ with:
24
+ enable-cache: true
25
+ - name: Install locked development dependencies
26
+ run: uv sync --locked --group dev --group docs
27
+ - name: Check formatting and lint
28
+ run: |
29
+ uv run ruff check .
30
+ uv run ruff format --check .
31
+ - name: Check types
32
+ run: |
33
+ uv run mypy src
34
+ uv run basedpyright
35
+ - name: Run tests
36
+ run: uv run pytest
37
+ - name: Build documentation
38
+ run: uv run mkdocs build --strict
39
+ - name: Build distributions
40
+ run: uv build
@@ -0,0 +1,64 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ build:
13
+ if: startsWith(github.ref, 'refs/tags/v')
14
+ name: Build and validate distributions
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v7
18
+ - uses: actions/setup-python@v7
19
+ with:
20
+ python-version: "3.12"
21
+ - uses: astral-sh/setup-uv@v6
22
+ with:
23
+ enable-cache: true
24
+ - name: Build distributions
25
+ run: uv build
26
+ - name: Validate built wheel
27
+ run: |
28
+ python -m pip install dist/*.whl
29
+ python - <<'PY'
30
+ import os
31
+ from importlib.metadata import version
32
+
33
+ import pypi_sdk
34
+
35
+ package_version = version("pypi-sdk")
36
+ tag_version = os.environ["GITHUB_REF_NAME"].removeprefix("v")
37
+ assert pypi_sdk.__version__ == package_version == tag_version
38
+ print(package_version)
39
+ PY
40
+ - name: Store distributions
41
+ uses: actions/upload-artifact@v7
42
+ with:
43
+ name: python-package-distributions
44
+ path: dist/
45
+ if-no-files-found: error
46
+
47
+ publish:
48
+ if: startsWith(github.ref, 'refs/tags/v')
49
+ name: Publish distribution to PyPI
50
+ needs: build
51
+ runs-on: ubuntu-latest
52
+ environment:
53
+ name: pypi
54
+ url: https://pypi.org/project/pypi-sdk/
55
+ permissions:
56
+ id-token: write
57
+ steps:
58
+ - name: Download distributions
59
+ uses: actions/download-artifact@v8
60
+ with:
61
+ name: python-package-distributions
62
+ path: dist/
63
+ - name: Publish to PyPI
64
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,39 @@
1
+ # Repository Instructions for Coding Agents
2
+
3
+ ## Project
4
+
5
+ This repository builds `pypi-sdk`, an unofficial typed Python client for PyPI's
6
+ documented APIs. Python imports use `pypi_sdk`. Code, docs, examples, benchmark
7
+ names, and commit messages are in English; communicate with the user in their
8
+ preferred language.
9
+
10
+ ## Boundaries
11
+
12
+ - Keep the client synchronous and use the shared HTTPX client.
13
+ - Model documented API responses with Pydantic v2, preserving additive fields.
14
+ - Do not add account-management endpoints PyPI does not document as public APIs.
15
+ - Do not wrap deprecated XML-RPC, partner-only secret reporting, or BigQuery as
16
+ PyPI HTTP endpoints.
17
+ - Publishing uploads built artifacts through Twine. Do not rebuild its upload
18
+ protocol or claim that an existing release can be overwritten.
19
+ - Keep credentials explicit, out of logs/arguments, and scoped to upload.
20
+ - Avoid automatic retries, redirects, or network access in normal tests.
21
+
22
+ ## Validation
23
+
24
+ Use the workspace `.venv` and locked uv dependencies. Before committing, run:
25
+
26
+ ```console
27
+ uv run ruff check .
28
+ uv run ruff format --check .
29
+ uv run mypy src
30
+ uv run basedpyright
31
+ uv run pytest
32
+ uv run --group docs mkdocs build --strict
33
+ uv build
34
+ ```
35
+
36
+ BenchCore is optional and requires Python 3.12+. Never commit benchmark output.
37
+ Read `CONTRIBUTING.md`, `SECURITY.md`, and the `docs/` pages for release and
38
+ security requirements. Preserve unrelated work and do not claim remote
39
+ publication when only local commits or tags exist.
@@ -0,0 +1,23 @@
1
+ # Changelog
2
+
3
+ User-visible changes are recorded here. This project follows semantic
4
+ versioning; compatibility changes are called out explicitly.
5
+
6
+ ## 1.0.0
7
+
8
+ ### Added
9
+
10
+ - Typed synchronous clients for PyPI project/release JSON, the PEP 691 JSON
11
+ Simple Index, PEP 740 provenance, storage statistics, and RSS feeds.
12
+ - Optional Twine-backed publishing to PyPI or TestPyPI, plus a GitHub Actions
13
+ Trusted Publishing example.
14
+ - Python 3.11+ support, strict BasedPyright and Mypy checks, coverage-enforced
15
+ tests, pytest-benchmark, and optional BenchCore measurements.
16
+ - English API, publishing, development, compatibility, security, and release
17
+ documentation.
18
+
19
+ ### Changed
20
+
21
+ - Preserve the JSON and RSS fields returned by PyPI while typing stable fields.
22
+ - Keep account administration, the partner-only secret API, BigQuery, and
23
+ deprecated XML-RPC outside the HTTP SDK surface.
@@ -0,0 +1,14 @@
1
+ # Claude Repository Guide
2
+
3
+ Read and follow [AGENTS.MD](AGENTS.MD), the canonical repository instructions.
4
+ Keep shared project rules there so this guide does not drift.
5
+
6
+ The distribution is `pypi-sdk`; the import package is `pypi_sdk`. This is an
7
+ unofficial synchronous client for PyPI's documented public APIs. The supported
8
+ surface and release boundaries are documented in `docs/api.md` and
9
+ `docs/compatibility.md`.
10
+
11
+ Use the workspace `.venv` and locked uv dependencies. Run the validation commands
12
+ from `AGENTS.MD`. Optional BenchCore runs only on Python 3.12+. Keep source,
13
+ documentation, and commit messages in English; answer the user in their preferred
14
+ language. Report only checks and releases actually completed.
@@ -0,0 +1,14 @@
1
+ # Code of Conduct
2
+
3
+ We welcome contributors with different backgrounds and experience levels. Be
4
+ respectful, explain technical disagreements constructively, and give others
5
+ room to learn.
6
+
7
+ Harassment, threats, discrimination, unwanted personal attention, and
8
+ publication of private information are not acceptable in project issues,
9
+ pull requests, reviews, or other project spaces.
10
+
11
+ Report concerns privately to the maintainer at
12
+ ramirez.ruiz.eliezer.reuven@gmail.com. Reports will be handled with care for the
13
+ privacy of those involved. The maintainer may remove harmful content or limit
14
+ participation to protect the community.
@@ -0,0 +1,77 @@
1
+ # Contributing
2
+
3
+ Thanks for helping improve this unofficial PyPI SDK. Keep source code,
4
+ documentation, examples, and commit messages in English.
5
+
6
+ ## Development setup
7
+
8
+ Install Python 3.11+ and uv, then create the locked development environment:
9
+
10
+ ```console
11
+ uv sync --locked --group dev --group docs
12
+ ```
13
+
14
+ Runtime dependencies belong in `[project.dependencies]`. Keep test, docs,
15
+ benchmark, and publishing tools in their corresponding optional groups. Update
16
+ `uv.lock` with uv; do not edit it by hand.
17
+
18
+ ## Validation
19
+
20
+ Run the full offline checks before committing:
21
+
22
+ ```console
23
+ uv run ruff check .
24
+ uv run ruff format --check .
25
+ uv run mypy src
26
+ uv run basedpyright
27
+ uv run pytest
28
+ uv run --group docs mkdocs build --strict
29
+ uv build
30
+ ```
31
+
32
+ Tests use HTTPX `MockTransport`; normal test runs do not contact PyPI or upload
33
+ files. Never test a write against production. Keep tests focused on observable
34
+ behavior and cover credential-sensitive code without real credentials.
35
+
36
+ Optional performance checks are opt-in:
37
+
38
+ ```console
39
+ uv run --group benchmark pytest benchmarks --no-cov --benchmark-only
40
+ ```
41
+
42
+ BenchCore requires Python 3.12+:
43
+
44
+ ```console
45
+ uv run --group benchcore pytest benchmarks/benchcore_cases.py --no-cov --benchcore-save=.benchcore
46
+ ```
47
+
48
+ Benchmark results are local artifacts and should not be committed.
49
+
50
+ ## Changes and commits
51
+
52
+ Keep changes cohesive, preserve unrelated work, and use Conventional Commits,
53
+ for example:
54
+
55
+ ```text
56
+ feat(api): add release metadata lookup
57
+ fix(publish): reject missing distributions
58
+ docs(publishing): explain Trusted Publishing
59
+ chore(release): prepare 1.0.0
60
+ ```
61
+
62
+ Update the changelog and directly related docs for user-visible changes. Do not
63
+ create a version tag until the version in `pyproject.toml`, package constants,
64
+ and release notes agree and the validation above passes. Tags are release
65
+ markers, not placeholders for future versions.
66
+
67
+ Commits created by Copilot include this trailer:
68
+
69
+ ```text
70
+ Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
71
+ ```
72
+
73
+ ## Publishing
74
+
75
+ Use the repository release workflow and PyPI Trusted Publishing once a remote
76
+ and trusted publisher are configured. Do not put long-lived PyPI tokens in
77
+ workflow files or command-line arguments. Test releases on TestPyPI first.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eli-ezer Reuven Ramirez Ruiz
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,190 @@
1
+ Metadata-Version: 2.4
2
+ Name: pypi-sdk
3
+ Version: 1.0.0
4
+ Summary: Typed Python client for PyPI's public APIs and package publishing
5
+ Keywords: pypi,python-packaging,sdk,publishing
6
+ Author: Eli-ezer Reuven Ramirez Ruiz
7
+ Author-email: Eli-ezer Reuven Ramirez Ruiz <ramirez.ruiz.eliezer.reuven@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE.md
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Typing :: Typed
17
+ Requires-Dist: httpx>=0.28.1
18
+ Requires-Dist: pydantic>=2.12.0,<3
19
+ Requires-Dist: twine>=6.0 ; extra == 'publish'
20
+ Requires-Python: >=3.11
21
+ Provides-Extra: publish
22
+ Description-Content-Type: text/markdown
23
+
24
+ # PyPI SDK
25
+
26
+ An unofficial, typed Python SDK for PyPI's documented public APIs. It provides
27
+ one synchronous client for package metadata, the PEP 691 index, provenance,
28
+ statistics, RSS feeds, and a Twine-backed distribution publisher.
29
+
30
+ The SDK requires Python 3.11 or later. It is not affiliated with or endorsed by
31
+ the Python Software Foundation or the PyPI maintainers.
32
+
33
+ ## What this SDK covers
34
+
35
+ | PyPI feature | SDK interface |
36
+ | --- | --- |
37
+ | Project and release JSON | `client.projects.get()` / `get_release()` |
38
+ | PEP 691 JSON Simple Index | `client.index.list_projects()` / `get_project()` |
39
+ | PEP 740 file provenance | `client.integrity.get_provenance()` |
40
+ | Package storage statistics | `client.stats.get()` |
41
+ | New package and release RSS feeds | `client.feeds` |
42
+ | Legacy upload endpoint | `client.publisher.upload()` via Twine |
43
+
44
+ It intentionally does not wrap the deprecated XML-RPC API, the partner-only
45
+ secret reporting API, or Google BigQuery datasets as if they were normal PyPI
46
+ HTTP endpoints. PyPI also does not provide a public general-purpose REST API to
47
+ manage accounts, collaborators, or edit an existing release. Add a new version
48
+ to publish an update; an existing release cannot be overwritten.
49
+
50
+ ## Installation
51
+
52
+ Python 3.11 or later is required. From this checkout:
53
+
54
+ ```console
55
+ uv sync --group dev --group docs
56
+ ```
57
+
58
+ After publishing, install the SDK from PyPI:
59
+
60
+ ```console
61
+ python -m pip install pypi-sdk
62
+ ```
63
+
64
+ For uploads, install the optional Twine dependency:
65
+
66
+ ```console
67
+ python -m pip install "pypi-sdk[publish]"
68
+ ```
69
+
70
+ ## Quick start
71
+
72
+ ```python
73
+ from pypi_sdk import PypiClient
74
+
75
+ with PypiClient() as client:
76
+ project = client.projects.get("sampleproject")
77
+ release = client.projects.get_release("sampleproject", project.info.version)
78
+ files = client.index.get_project("sampleproject").files
79
+ print(project.info.summary, len(files), len(release.urls))
80
+ ```
81
+
82
+ Responses are Pydantic models that preserve additional fields returned by PyPI.
83
+ The client uses anonymous GET requests by default, follows no redirects, and
84
+ does not retry automatically.
85
+
86
+ ## Publish built distributions
87
+
88
+ Build and validate artifacts with the standard Python packaging tools, then
89
+ explicitly choose TestPyPI or PyPI. TestPyPI is a separate service, useful for
90
+ testing the release process before publishing to production.
91
+
92
+ ```python
93
+ from pathlib import Path
94
+
95
+ from pypi_sdk import PypiClient
96
+
97
+ artifacts = Path("dist").glob("*")
98
+ with PypiClient() as client:
99
+ result = client.publisher.upload(artifacts, repository="testpypi")
100
+ print(result.files)
101
+ ```
102
+
103
+ Twine reads `TWINE_USERNAME` and `TWINE_PASSWORD` from the environment, or can
104
+ receive a token explicitly without placing it in process arguments:
105
+
106
+ ```python
107
+ import os
108
+ from pathlib import Path
109
+
110
+ from pypi_sdk import PypiClient
111
+
112
+ token = os.environ["PYPI_API_TOKEN"]
113
+ with PypiClient() as client:
114
+ client.publisher.upload(
115
+ Path("dist").glob("*"),
116
+ repository="pypi",
117
+ token=token,
118
+ )
119
+ ```
120
+
121
+ The equivalent CLI command is:
122
+
123
+ ```console
124
+ pypi-sdk upload --repository testpypi dist\your_package-1.0.0-py3-none-any.whl
125
+ ```
126
+
127
+ The publisher delegates metadata handling and the upload protocol to Twine.
128
+ It does not build distributions; use `python -m build` or your project's
129
+ existing build backend first.
130
+
131
+ ## Automated publishing with Trusted Publishing
132
+
133
+ For CI, prefer PyPI Trusted Publishing over long-lived API tokens. Configure
134
+ the GitHub repository and workflow as a trusted publisher in the PyPI project
135
+ settings using the GitHub repository owner, repository name, `publish.yml`, and
136
+ the `pypi` environment. Configure the matching GitHub Environment (add
137
+ protection rules if desired), then copy
138
+ [`examples/publish.yml`](examples/publish.yml) to
139
+ `.github/workflows/publish.yml` in the package being released. The workflow
140
+ builds and validates distributions, then publishes them through PyPI's official
141
+ GitHub Action using OIDC.
142
+ See the [Trusted Publishing guide](https://docs.pypi.org/trusted-publishers/).
143
+
144
+ ## API policies and boundaries
145
+
146
+ - The SDK identifies itself with a `User-Agent` and honors PyPI's JSON
147
+ representations. The Simple Index HTML representation is not wrapped; the
148
+ docs recommend its JSON form for new integrations.
149
+ - If polling for updates, prefer RSS feeds and avoid bursts of thousands of
150
+ requests. The current client does not yet expose conditional ETag requests.
151
+ - Use the Simple Index for distribution files and verify their advertised
152
+ hashes after downloading.
153
+ - File upload creates releases one file at a time. The first file for a
154
+ version creates that release and fixes its metadata. To correct a release,
155
+ publish a new version.
156
+ - Project administration and Trusted Publisher setup happen in PyPI's web
157
+ interface; this SDK does not claim unsupported account-management endpoints.
158
+
159
+ See the [PyPI API documentation](https://docs.pypi.org/api/) and the
160
+ [Python Packaging User Guide](https://packaging.python.org/).
161
+
162
+ ## Development
163
+
164
+ ```console
165
+ uv sync --group dev --group docs
166
+ uv run ruff check .
167
+ uv run ruff format --check .
168
+ uv run mypy src
169
+ uv run basedpyright
170
+ uv run pytest
171
+ uv run --group docs mkdocs build --strict
172
+ uv build
173
+ ```
174
+
175
+ Tests use mocked HTTP and do not upload packages or contact PyPI. Optional CPU
176
+ benchmarks are available with pytest-benchmark:
177
+
178
+ ```console
179
+ uv run --group benchmark pytest benchmarks --no-cov --benchmark-only
180
+ ```
181
+
182
+ BenchCore measurements require Python 3.12 or later:
183
+
184
+ ```console
185
+ uv run --group benchcore pytest benchmarks/benchcore_cases.py --no-cov --benchcore-save=.benchcore
186
+ ```
187
+
188
+ See [Getting started](docs/quickstart.md), [API reference](docs/api.md),
189
+ [publishing guide](docs/publishing.md), [development guide](docs/development.md),
190
+ [contributing](CONTRIBUTING.md), and the [changelog](CHANGELOG.md).
@@ -0,0 +1,167 @@
1
+ # PyPI SDK
2
+
3
+ An unofficial, typed Python SDK for PyPI's documented public APIs. It provides
4
+ one synchronous client for package metadata, the PEP 691 index, provenance,
5
+ statistics, RSS feeds, and a Twine-backed distribution publisher.
6
+
7
+ The SDK requires Python 3.11 or later. It is not affiliated with or endorsed by
8
+ the Python Software Foundation or the PyPI maintainers.
9
+
10
+ ## What this SDK covers
11
+
12
+ | PyPI feature | SDK interface |
13
+ | --- | --- |
14
+ | Project and release JSON | `client.projects.get()` / `get_release()` |
15
+ | PEP 691 JSON Simple Index | `client.index.list_projects()` / `get_project()` |
16
+ | PEP 740 file provenance | `client.integrity.get_provenance()` |
17
+ | Package storage statistics | `client.stats.get()` |
18
+ | New package and release RSS feeds | `client.feeds` |
19
+ | Legacy upload endpoint | `client.publisher.upload()` via Twine |
20
+
21
+ It intentionally does not wrap the deprecated XML-RPC API, the partner-only
22
+ secret reporting API, or Google BigQuery datasets as if they were normal PyPI
23
+ HTTP endpoints. PyPI also does not provide a public general-purpose REST API to
24
+ manage accounts, collaborators, or edit an existing release. Add a new version
25
+ to publish an update; an existing release cannot be overwritten.
26
+
27
+ ## Installation
28
+
29
+ Python 3.11 or later is required. From this checkout:
30
+
31
+ ```console
32
+ uv sync --group dev --group docs
33
+ ```
34
+
35
+ After publishing, install the SDK from PyPI:
36
+
37
+ ```console
38
+ python -m pip install pypi-sdk
39
+ ```
40
+
41
+ For uploads, install the optional Twine dependency:
42
+
43
+ ```console
44
+ python -m pip install "pypi-sdk[publish]"
45
+ ```
46
+
47
+ ## Quick start
48
+
49
+ ```python
50
+ from pypi_sdk import PypiClient
51
+
52
+ with PypiClient() as client:
53
+ project = client.projects.get("sampleproject")
54
+ release = client.projects.get_release("sampleproject", project.info.version)
55
+ files = client.index.get_project("sampleproject").files
56
+ print(project.info.summary, len(files), len(release.urls))
57
+ ```
58
+
59
+ Responses are Pydantic models that preserve additional fields returned by PyPI.
60
+ The client uses anonymous GET requests by default, follows no redirects, and
61
+ does not retry automatically.
62
+
63
+ ## Publish built distributions
64
+
65
+ Build and validate artifacts with the standard Python packaging tools, then
66
+ explicitly choose TestPyPI or PyPI. TestPyPI is a separate service, useful for
67
+ testing the release process before publishing to production.
68
+
69
+ ```python
70
+ from pathlib import Path
71
+
72
+ from pypi_sdk import PypiClient
73
+
74
+ artifacts = Path("dist").glob("*")
75
+ with PypiClient() as client:
76
+ result = client.publisher.upload(artifacts, repository="testpypi")
77
+ print(result.files)
78
+ ```
79
+
80
+ Twine reads `TWINE_USERNAME` and `TWINE_PASSWORD` from the environment, or can
81
+ receive a token explicitly without placing it in process arguments:
82
+
83
+ ```python
84
+ import os
85
+ from pathlib import Path
86
+
87
+ from pypi_sdk import PypiClient
88
+
89
+ token = os.environ["PYPI_API_TOKEN"]
90
+ with PypiClient() as client:
91
+ client.publisher.upload(
92
+ Path("dist").glob("*"),
93
+ repository="pypi",
94
+ token=token,
95
+ )
96
+ ```
97
+
98
+ The equivalent CLI command is:
99
+
100
+ ```console
101
+ pypi-sdk upload --repository testpypi dist\your_package-1.0.0-py3-none-any.whl
102
+ ```
103
+
104
+ The publisher delegates metadata handling and the upload protocol to Twine.
105
+ It does not build distributions; use `python -m build` or your project's
106
+ existing build backend first.
107
+
108
+ ## Automated publishing with Trusted Publishing
109
+
110
+ For CI, prefer PyPI Trusted Publishing over long-lived API tokens. Configure
111
+ the GitHub repository and workflow as a trusted publisher in the PyPI project
112
+ settings using the GitHub repository owner, repository name, `publish.yml`, and
113
+ the `pypi` environment. Configure the matching GitHub Environment (add
114
+ protection rules if desired), then copy
115
+ [`examples/publish.yml`](examples/publish.yml) to
116
+ `.github/workflows/publish.yml` in the package being released. The workflow
117
+ builds and validates distributions, then publishes them through PyPI's official
118
+ GitHub Action using OIDC.
119
+ See the [Trusted Publishing guide](https://docs.pypi.org/trusted-publishers/).
120
+
121
+ ## API policies and boundaries
122
+
123
+ - The SDK identifies itself with a `User-Agent` and honors PyPI's JSON
124
+ representations. The Simple Index HTML representation is not wrapped; the
125
+ docs recommend its JSON form for new integrations.
126
+ - If polling for updates, prefer RSS feeds and avoid bursts of thousands of
127
+ requests. The current client does not yet expose conditional ETag requests.
128
+ - Use the Simple Index for distribution files and verify their advertised
129
+ hashes after downloading.
130
+ - File upload creates releases one file at a time. The first file for a
131
+ version creates that release and fixes its metadata. To correct a release,
132
+ publish a new version.
133
+ - Project administration and Trusted Publisher setup happen in PyPI's web
134
+ interface; this SDK does not claim unsupported account-management endpoints.
135
+
136
+ See the [PyPI API documentation](https://docs.pypi.org/api/) and the
137
+ [Python Packaging User Guide](https://packaging.python.org/).
138
+
139
+ ## Development
140
+
141
+ ```console
142
+ uv sync --group dev --group docs
143
+ uv run ruff check .
144
+ uv run ruff format --check .
145
+ uv run mypy src
146
+ uv run basedpyright
147
+ uv run pytest
148
+ uv run --group docs mkdocs build --strict
149
+ uv build
150
+ ```
151
+
152
+ Tests use mocked HTTP and do not upload packages or contact PyPI. Optional CPU
153
+ benchmarks are available with pytest-benchmark:
154
+
155
+ ```console
156
+ uv run --group benchmark pytest benchmarks --no-cov --benchmark-only
157
+ ```
158
+
159
+ BenchCore measurements require Python 3.12 or later:
160
+
161
+ ```console
162
+ uv run --group benchcore pytest benchmarks/benchcore_cases.py --no-cov --benchcore-save=.benchcore
163
+ ```
164
+
165
+ See [Getting started](docs/quickstart.md), [API reference](docs/api.md),
166
+ [publishing guide](docs/publishing.md), [development guide](docs/development.md),
167
+ [contributing](CONTRIBUTING.md), and the [changelog](CHANGELOG.md).
@@ -0,0 +1,27 @@
1
+ # Security Policy
2
+
3
+ ## Supported versions
4
+
5
+ Security fixes target the latest supported release. Before a stable release,
6
+ the project has no older supported release lines or service-level guarantees.
7
+
8
+ ## Reporting a vulnerability
9
+
10
+ Report suspected vulnerabilities privately to
11
+ ramirez.ruiz.eliezer@gmail.com. Include the affected version, impact,
12
+ and a minimal reproduction using synthetic credentials. Do not publish tokens,
13
+ personal data, or exploit details in public issues. No response-time commitment
14
+ is currently offered.
15
+
16
+ ## Publishing credentials
17
+
18
+ Prefer PyPI Trusted Publishing in CI. For local publishing, use a project-scoped
19
+ API token and pass it through the SDK's `token` parameter or Twine's
20
+ `TWINE_PASSWORD` environment variable. Never commit tokens, print them, or place
21
+ them in command-line arguments. Revoke exposed tokens in PyPI; deleting a token
22
+ from a later commit does not revoke it.
23
+
24
+ The SDK keeps upload credentials out of read requests and subprocess arguments.
25
+ It cannot protect secrets that an application logs or passes to unrelated
26
+ processes. Uploading is an external side effect; use TestPyPI to validate a
27
+ workflow before production.