oaipmh 3.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.
@@ -0,0 +1,8 @@
1
+ __pycache__/
2
+ *.pyc
3
+ dist/
4
+ build/
5
+ *.egg-info/
6
+ .venv/
7
+ .direnv/
8
+ .pytest_cache/
@@ -0,0 +1,266 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [3.0.0] — 2026-04-15
9
+
10
+ First release under the `oaipmh` distribution name on PyPI. This release marks the
11
+ maintenance fork from [`infrae/pyoai`](https://github.com/infrae/pyoai) and brings the
12
+ codebase onto modern Python packaging and tooling. The public API and the
13
+ `from oaipmh import ...` import path are unchanged.
14
+
15
+ ### Breaking Changes
16
+
17
+ - Renamed PyPI distribution from `pyoai` to `oaipmh`. Existing consumers must update
18
+ their dependency declarations; no application code changes are required.
19
+ - Minimum supported Python version raised to 3.10. Python 2 and Python 3.9 and earlier
20
+ are no longer supported.
21
+ - Removed the `six` dependency; the package now relies exclusively on native Python 3
22
+ APIs.
23
+
24
+ ### Added
25
+
26
+ - PEP 621 metadata in `pyproject.toml` with [Hatchling](https://hatch.pypa.io/) as the
27
+ build backend.
28
+ - `uv.lock` for reproducible dependency resolution.
29
+ - [`uv`](https://docs.astral.sh/uv/)-based GitHub Actions CI covering Python 3.10 – 3.13.
30
+ - GitHub Actions workflow (`publish.yml`) for automated PyPI publishing via
31
+ [Trusted Publishing](https://docs.pypi.org/trusted-publishers/) (OIDC; no
32
+ long-lived tokens stored in the repository).
33
+ - Reproducible development environment via a [Nix](https://nixos.org/) flake and
34
+ [`direnv`](https://direnv.net/) integration.
35
+ - `pytest` configuration replacing the legacy `runtests.sh` entry point.
36
+ - `CONTRIBUTING.md` with development setup, commit conventions, and the release process.
37
+ - `CHANGELOG.md` (this file), superseding `HISTORY.txt`.
38
+ - `ETH Library — Data Science and Research Support <dsr@library.ethz.ch>` maintainer
39
+ entry alongside the existing Jaime Cardozo entry.
40
+
41
+ ### Changed
42
+
43
+ - Build backend migrated from legacy `setup.py` / `setup.cfg` to Hatchling via
44
+ `pyproject.toml`.
45
+ - Development status classifier raised from `4 - Beta` to `5 - Production/Stable`.
46
+ - Version jumped from `2.5.2pre` to `3.0.0` to reflect the breaking distribution rename
47
+ and the Python version floor.
48
+ - README rewritten and expanded; converted from reStructuredText (`README.rst`) to
49
+ Markdown (`README.md`).
50
+ - License file renamed from `LICENSE.txt` to `LICENSE` and prepended with an ETH Zurich
51
+ copyright notice alongside the original Infrae notice.
52
+ - Wheel and sdist contents scoped via explicit `tool.hatch.build` include/exclude
53
+ lists, so consumers no longer receive test fixtures or local development files.
54
+ - Bare imports inside the package converted to relative imports.
55
+
56
+ ### Fixed
57
+
58
+ - Replaced deprecated `datetime.utcnow()` with timezone-aware
59
+ `datetime.now(timezone.utc)` equivalents (Python 3.12+ deprecation).
60
+ - Replaced `lxml.etree.XPath.evaluate()` calls with direct callable syntax for
61
+ compatibility with `lxml` 5.x.
62
+ - Replaced `unicode()` with `str()` for Python 3 compatibility.
63
+ - Replaced `pkg_resources` with `importlib.metadata` for distribution version lookup.
64
+ - Replaced removed unittest assertion aliases dropped in Python 3.12.
65
+ - Removed the `unittest.makeSuite` helper, which was dropped in Python 3.13.
66
+ - Renamed the internal test helper `TestError` to `FakeRequestError` to avoid pytest's
67
+ `PytestCollectionWarning` on classes prefixed with `Test`.
68
+
69
+ ### Removed
70
+
71
+ - Python 2 compatibility shims across the package and tests.
72
+ - `six` dependency.
73
+ - Legacy packaging files: `setup.py`, `setup.cfg`, `tox.ini`, `MANIFEST.in`, and
74
+ `.travis.yml`.
75
+ - `runtests.sh` (replaced by `pytest`).
76
+ - Non-functional Python 2 data generation scripts.
77
+ - Outdated `doc/` directory.
78
+ - Legacy Mercurial files.
79
+ - `HISTORY.txt` (content migrated to this file).
80
+
81
+ ---
82
+
83
+ ## [2.5.1] — 2022-03-08
84
+
85
+ ### Added
86
+
87
+ - Customizable client retry policy.
88
+ - Python 3.8 compatibility.
89
+
90
+ ### Fixed
91
+
92
+ - Do not resume `ListRecord` requests when no result was returned.
93
+
94
+ ## [2.5.0] — 2017-07-03
95
+
96
+ ### Added
97
+
98
+ - Python 3 compatibility.
99
+ - Travis CI support and badges.
100
+
101
+ ## [2.4.5] — 2015-12-23
102
+
103
+ ### Added
104
+
105
+ - Client switch to force harvesting using HTTP GET.
106
+ - Unofficial `GetMetadata` verb in server and client. `GetMetadata` is identical to
107
+ `GetRecord` but returns only the first element below the `oai:metadata` element,
108
+ without the OAI envelope.
109
+
110
+ ## [2.4.4] — 2010-09-30
111
+
112
+ ### Changed
113
+
114
+ - Updated contact info.
115
+ - Migrated code from Subversion to Mercurial.
116
+
117
+ ## [2.4.3] — 2010-08-19
118
+
119
+ ### Fixed
120
+
121
+ - Convert `lxml.etree._ElementUnicodeResult` and `ElementStringResult` to normal `str`
122
+ and `unicode` objects to prevent errors when these objects are pickled.
123
+
124
+ ## [2.4.2] — 2010-05-03
125
+
126
+ ### Fixed
127
+
128
+ - `oai_dc` and `dc` namespace declarations are now declared on the child of the
129
+ metadata element rather than the document root, per the OAI-PMH specification.
130
+
131
+ ## [2.4.1] — 2009-11-16
132
+
133
+ ### Fixed
134
+
135
+ - When a date (not a datetime) is specified for the `until` parameter, default to
136
+ `23:59:59` instead of `00:00:00`.
137
+
138
+ ## [2.4] — 2009-05-04
139
+
140
+ ### Added
141
+
142
+ - Support for description elements in OAI `Identify` headers, with a `toolkit`
143
+ description included by default.
144
+
145
+ ## [2.3.1] — 2009-04-24
146
+
147
+ ### Fixed
148
+
149
+ - Raise the correct error when `from` and `until` parameters have different
150
+ granularities.
151
+
152
+ ## [2.3] — 2009-04-23
153
+
154
+ ### Changed
155
+
156
+ - Use `buildout` to create the testrunner and environment, replacing the `test.py`
157
+ script.
158
+
159
+ ### Fixed
160
+
161
+ - Handle invalid `dateTime` formats correctly: the server now responds with a
162
+ `BadArgument` XML error instead of a Python traceback.
163
+
164
+ ## [2.2.1] — 2008-04-04
165
+
166
+ ### Added
167
+
168
+ - XML declaration to server output.
169
+ - Pretty-printed XML output.
170
+ - Server resumption tokens now work with POST requests.
171
+
172
+ ### Fixed
173
+
174
+ - Compatibility with `lxml` 2.0.
175
+ - Handle `503` responses from the server correctly in client code.
176
+
177
+ ## [2.2] — 2006-11-20
178
+
179
+ ### Added
180
+
181
+ - `BatchingServer`, implementing the `IBatchingOAI` interface. Similar to `IOAI` but
182
+ with `cursor` and `batch_size` arguments on each method, enabling efficient batching
183
+ OAI servers on top of relational databases.
184
+ - Ability to explicitly pass `None` as the `from` or `until` parameter for an OAI-PMH
185
+ client.
186
+ - Extra `nsmap` argument on `Server` and `BatchingServer` to customise the namespace
187
+ prefix to URI mappings used in server output.
188
+
189
+ ### Fixed
190
+
191
+ - Output encoding bug: output is now correctly encoded as UTF-8.
192
+
193
+ ## [2.1.5] — 2006-09-18
194
+
195
+ ### Fixed
196
+
197
+ - Compatibility with `lxml` 1.1.
198
+
199
+ ## [2.1.4] — 2006-06-16
200
+
201
+ ### Changed
202
+
203
+ - Distribute as an egg.
204
+
205
+ ## [2.1.3] — 2006-05-01
206
+
207
+ ### Added
208
+
209
+ - Infrastructure to handle non-XML-compliant OAI-PMH feeds; an `XMLSyntaxError` is now
210
+ raised in those cases.
211
+ - `tolerant_datestamp_to_datetime`, a more permissive alternative to
212
+ `datestamp_to_datetime` for handling malformed datestamps.
213
+
214
+ ### Changed
215
+
216
+ - Split datestamp handling into a separate `datestamp` module.
217
+
218
+ ## [2.0] — 2006-01-26
219
+
220
+ ### Added
221
+
222
+ - Support for day-only granularity (`YYYY-MM-DD`) in the client. Calling
223
+ `updateGranularity` checks with the server (via `identify()`) which granularity it
224
+ supports; if the server only supports day-level granularity, the client restricts
225
+ outgoing timestamps to `YYYY-MM-DD`.
226
+
227
+ ## [2.0b1] — 2005-11-21
228
+
229
+ ### Added
230
+
231
+ - Framework for implementing OAI-PMH-compliant servers.
232
+ - Extended testing infrastructure.
233
+
234
+ ### Changed
235
+
236
+ - Package structure is now an `oaipmh` namespace package; client functionality moved
237
+ to `oaipmh.client`.
238
+ - Refactored `oaipmh.py` to share code between the client and server.
239
+ - Switched from the `libxml2` Python wrappers to the `lxml` binding.
240
+ - `listRecords`, `listIdentifiers`, and `listSets` now return iterators instead of
241
+ lists (previously hacked via `__getitem__`). Existing call sites can wrap the result
242
+ in `list()` if needed.
243
+
244
+ ## [1.0.1]
245
+
246
+ ### Fixed
247
+
248
+ - Typo in `oaipmh.py`.
249
+
250
+ ## [1.0]
251
+
252
+ ### Added
253
+
254
+ - `encoding` parameter to the `serialize` call, fixing a Unicode bug.
255
+
256
+ ## [0.7.4]
257
+
258
+ ### Fixed
259
+
260
+ - Harvested records with `<header status="deleted">` are no longer stored in the
261
+ catalog. Previously they could be treated as normal records even though they merely
262
+ indicate that the metadata set is no longer on the OAI service.
263
+
264
+ ## [0.7]
265
+
266
+ Initial public release.
@@ -0,0 +1,113 @@
1
+ # Contributing
2
+
3
+ Thank you for your interest in contributing to `oaipmh`. Bug reports, feature proposals, and pull requests are welcome.
4
+
5
+ ## Local development
6
+
7
+ Three setup paths are supported, in order of preference.
8
+
9
+ ### Option A — Nix flake with direnv (recommended)
10
+
11
+ The repository ships a reproducible [Nix](https://nixos.org/) flake with [direnv](https://direnv.net/) integration. This provisions the correct Python, [`uv`](https://docs.astral.sh/uv/), and system dependencies automatically.
12
+
13
+ Activate the environment the first time you enter the repository:
14
+
15
+ ```bash
16
+ direnv allow
17
+ ```
18
+
19
+ Run the test suite:
20
+
21
+ ```bash
22
+ uv run pytest
23
+ ```
24
+
25
+ ### Option B — `uv` only
26
+
27
+ If you have [`uv`](https://docs.astral.sh/uv/) installed directly and prefer not to use Nix.
28
+
29
+ Synchronise dependencies from `uv.lock`:
30
+
31
+ ```bash
32
+ uv sync
33
+ ```
34
+
35
+ Run the test suite:
36
+
37
+ ```bash
38
+ uv run pytest
39
+ ```
40
+
41
+ ### Option C — plain `pip` and `venv`
42
+
43
+ Standard Python tooling works with no additional prerequisites beyond a Python 3.10+ interpreter.
44
+
45
+ Create and activate a virtual environment:
46
+
47
+ ```bash
48
+ python3 -m venv .venv
49
+ ```
50
+
51
+ ```bash
52
+ source .venv/bin/activate
53
+ ```
54
+
55
+ Install the package in editable mode together with the test dependencies:
56
+
57
+ ```bash
58
+ pip install -e ".[test]"
59
+ ```
60
+
61
+ Run the test suite:
62
+
63
+ ```bash
64
+ pytest
65
+ ```
66
+
67
+ ## Commit conventions
68
+
69
+ This project uses [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). Common prefixes used in this repository:
70
+
71
+ - `feat:` — a new feature.
72
+ - `fix:` — a bug fix.
73
+ - `docs:` — documentation-only changes.
74
+ - `refactor:` — a code change that neither fixes a bug nor adds a feature.
75
+ - `test:` — adding or correcting tests.
76
+ - `build:` — changes to the build system or packaging.
77
+ - `ci:` — changes to CI configuration.
78
+ - `chore:` — maintenance tasks that don't fit the categories above.
79
+
80
+ Keep commits atomic: one logical change per commit, with a clear message that explains the *why* rather than restating the diff.
81
+
82
+ ## Branching strategy
83
+
84
+ This project follows a [trunk-based development](https://trunkbaseddevelopment.com/) model. All work lands on `main` through short-lived topic branches (typically merged within a few days). Long-lived branches — including release branches — are avoided because they drift from `main`, accumulate merge conflicts, and fragment CI signal.
85
+
86
+ Use a short, purpose-driven prefix that matches the commit type: `feat/`, `fix/`, `docs/`, `chore/`, `ci/`.
87
+
88
+ A `release/<version>` branch is only appropriate for exceptional, coordinated releases that cannot land as a single short-lived branch (for example, the initial `release/v3.0.0` that carried the fork takeover from `pyoai` to `oaipmh`). The default path for a release is a tag on `main`, not a release branch.
89
+
90
+ The [Releases](#releases) section below picks up from here and walks through the tag-and-publish flow.
91
+
92
+ ## Pull requests
93
+
94
+ External contributors should [fork](https://docs.github.com/en/get-started/quickstart/fork-a-repo) `eth-library/oaipmh` on GitHub, push changes to a branch on their fork, and open a pull request from that branch. Maintainers with push access to `eth-library/oaipmh` may open branches directly on the repository.
95
+
96
+ - Target the `main` branch of `eth-library/oaipmh`.
97
+ - Keep the PR focused on a single topic; open separate PRs for unrelated changes.
98
+ - Ensure the test suite passes locally (`uv run pytest`) before opening the PR.
99
+ - CI must be green before a PR can be merged.
100
+ - Provide enough context in the description for a reviewer to understand the motivation, the approach, and any trade-offs.
101
+
102
+ ## Releases
103
+
104
+ Releases follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
105
+
106
+ The release process is:
107
+
108
+ 1. Merge release-bound changes into `main` as individual short-lived topic branches. Do not open a long-lived release branch; cut the release from `main` once the desired commits have landed.
109
+ 2. Tag the merge commit with `vX.Y.Z` and push the tag.
110
+ 3. Create a draft GitHub Release against the tag, using the relevant `CHANGELOG.md` section as the release notes.
111
+ 4. Review the draft release; when publishing it, the `publish.yml` workflow uploads the distribution to PyPI through [Trusted Publishing](https://docs.pypi.org/trusted-publishers/) (OIDC — no tokens stored in the repository).
112
+
113
+ The fork jumped directly from `2.5.2pre` (an unreleased development version under the upstream `pyoai` distribution name) to `3.0.0` because the PyPI distribution was renamed from `pyoai` to `oaipmh` and the minimum supported Python version was raised to 3.10 — both of which are breaking changes under SemVer.
oaipmh-3.0.0/LICENSE ADDED
@@ -0,0 +1,31 @@
1
+ Copyright © 2026 ETH Zurich, Jaime Cardozo; ETH Library.
2
+
3
+ Copyright (c) 2003-2006 Infrae. All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are
7
+ met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright
13
+ notice, this list of conditions and the following disclaimer in
14
+ the documentation and/or other materials provided with the
15
+ distribution.
16
+
17
+ 3. Neither the name of Infrae nor the names of its contributors may
18
+ be used to endorse or promote products derived from this software
19
+ without specific prior written permission.
20
+
21
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INFRAE OR
25
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
oaipmh-3.0.0/PKG-INFO ADDED
@@ -0,0 +1,26 @@
1
+ Metadata-Version: 2.4
2
+ Name: oaipmh
3
+ Version: 3.0.0
4
+ Summary: Python implementation of the Open Archives Initiative Protocol for Metadata Harvesting (OAI-PMH)
5
+ Project-URL: Repository, https://github.com/eth-library/oaipmh
6
+ Project-URL: Original-Repository, https://github.com/infrae/pyoai
7
+ Project-URL: Changelog, https://github.com/eth-library/oaipmh/blob/main/CHANGELOG.md
8
+ Project-URL: Issues, https://github.com/eth-library/oaipmh/issues
9
+ Author-email: Infrae <info@infrae.com>
10
+ Maintainer-email: Jaime Cardozo <jaime.cardozo@library.ethz.ch>, ETH Library — Data Science and Research Support <dsr@library.ethz.ch>
11
+ License-Expression: BSD-3-Clause
12
+ License-File: LICENSE
13
+ Keywords: OAI-PMH,archive,harvesting,metadata,xml
14
+ Classifier: Development Status :: 5 - Production/Stable
15
+ Classifier: Environment :: Web Environment
16
+ Classifier: License :: OSI Approved :: BSD License
17
+ Classifier: Programming Language :: Python
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: Topic :: Software Development :: Libraries :: Python Modules
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: lxml
25
+ Provides-Extra: test
26
+ Requires-Dist: pytest; extra == 'test'
oaipmh-3.0.0/README.md ADDED
@@ -0,0 +1,83 @@
1
+ # oaipmh
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/oaipmh)](https://pypi.org/project/oaipmh/)
4
+ [![Python versions](https://img.shields.io/pypi/pyversions/oaipmh)](https://pypi.org/project/oaipmh/)
5
+ [![CI](https://github.com/eth-library/oaipmh/actions/workflows/ci.yml/badge.svg)](https://github.com/eth-library/oaipmh/actions/workflows/ci.yml)
6
+ [![License](https://img.shields.io/badge/license-BSD--3--Clause-blue)](./LICENSE)
7
+
8
+ A Python library for working with [OAI-PMH version 2](https://www.openarchives.org/OAI/openarchivesprotocol.html) — harvest metadata from existing repositories using the client, or expose your own repository using the server. This is a maintained fork of [`infrae/pyoai`](https://github.com/infrae/pyoai).
9
+
10
+ ## Installation
11
+
12
+ Install the latest release from PyPI:
13
+
14
+ ```bash
15
+ pip install oaipmh
16
+ ```
17
+
18
+ Requires Python 3.10 or newer.
19
+
20
+ ## Quickstart
21
+
22
+ A minimal client that lists records from an OAI-PMH endpoint using the Dublin Core metadata prefix:
23
+
24
+ ```python
25
+ from oaipmh.client import Client
26
+ from oaipmh.metadata import MetadataRegistry, oai_dc_reader
27
+
28
+ URL = "http://uni.edu/ir/oaipmh"
29
+
30
+ registry = MetadataRegistry()
31
+ registry.registerReader("oai_dc", oai_dc_reader)
32
+ client = Client(URL, registry)
33
+
34
+ for record in client.listRecords(metadataPrefix="oai_dc"):
35
+ print(record)
36
+ ```
37
+
38
+ ## Migrating from pyoai
39
+
40
+ If you already depend on `pyoai`, migration is a dependency swap:
41
+
42
+ - Replace `pyoai` with `oaipmh` in your requirements (`pip install oaipmh`).
43
+ - Import paths are unchanged — `from oaipmh import ...` continues to work.
44
+ - The minimum supported Python version is 3.10.
45
+
46
+ No application code changes are required beyond the dependency rename. See [Why this fork](#why-this-fork) for background.
47
+
48
+ ## Why this fork
49
+
50
+ `oaipmh` is a maintained fork of [`infrae/pyoai`](https://github.com/infrae/pyoai), which has received no substantive changes since March 2022. The public API and import path are unchanged; only the PyPI distribution name has changed, from `pyoai` to `oaipmh`, to distinguish the maintained release from the abandoned upstream package.
51
+
52
+ Maintenance since the fork has focused on bringing the codebase onto current Python infrastructure while preserving behaviour for existing consumers:
53
+
54
+ - Python 3.10+ baseline; legacy Python 2 compatibility code removed.
55
+ - Deprecated `datetime.utcnow()` replaced with timezone-aware alternatives.
56
+ - Modern packaging using [PEP 621](https://peps.python.org/pep-0621/) metadata and the [Hatchling](https://hatch.pypa.io/) build backend.
57
+ - CI pipeline rebuilt on [`uv`](https://docs.astral.sh/uv/), replacing the legacy `tox` configuration.
58
+ - Reproducible development environment via a [Nix](https://nixos.org/) flake and [direnv](https://direnv.net/).
59
+ - Test suite modernised and running green across Python 3.10 – 3.13.
60
+
61
+ ## Scope
62
+
63
+ `oaipmh` is a maintained fork. Bug fixes and compatibility work are the primary focus; well-scoped feature proposals are welcome via GitHub Issues and Pull Requests. See [`CONTRIBUTING.md`](./CONTRIBUTING.md) for guidelines.
64
+
65
+ ## Contributing
66
+
67
+ Issues and pull requests are welcome. See [`CONTRIBUTING.md`](./CONTRIBUTING.md) for local development setup, branch naming, commit conventions, and the release process.
68
+
69
+ ## Support
70
+
71
+ Bug reports and questions are accepted via [GitHub Issues](https://github.com/eth-library/oaipmh/issues). Maintenance is best-effort with no formal SLA.
72
+
73
+ ## Acknowledgements
74
+
75
+ We are grateful to the original [`infrae/pyoai`](https://github.com/infrae/pyoai) authors at Infrae and to the many community contributors who built and maintained this library over two decades; this fork would not exist without their work.
76
+
77
+ ## License
78
+
79
+ Distributed under the BSD-3-Clause License.
80
+ Copyright © 2026 ETH Zurich, Jaime Cardozo; ETH Library.
81
+ Based on [`infrae/pyoai`](https://github.com/infrae/pyoai) by Infrae and community contributors.
82
+
83
+ See [`LICENSE`](./LICENSE) for the full license terms and [`CHANGELOG.md`](./CHANGELOG.md) for the release history.
@@ -0,0 +1,61 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "oaipmh"
7
+ version = "3.0.0"
8
+ description = "Python implementation of the Open Archives Initiative Protocol for Metadata Harvesting (OAI-PMH)"
9
+ requires-python = ">=3.10"
10
+ license = "BSD-3-Clause"
11
+ authors = [
12
+ { name = "Infrae", email = "info@infrae.com" },
13
+ ]
14
+ maintainers = [
15
+ { name = "Jaime Cardozo", email = "jaime.cardozo@library.ethz.ch" },
16
+ { name = "ETH Library — Data Science and Research Support", email = "dsr@library.ethz.ch" },
17
+ ]
18
+ dependencies = ["lxml"]
19
+ classifiers = [
20
+ "Development Status :: 5 - Production/Stable",
21
+ "Programming Language :: Python",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "License :: OSI Approved :: BSD License",
27
+ "Topic :: Software Development :: Libraries :: Python Modules",
28
+ "Environment :: Web Environment",
29
+ ]
30
+ keywords = ["OAI-PMH", "xml", "archive", "metadata", "harvesting"]
31
+
32
+ [project.urls]
33
+ Repository = "https://github.com/eth-library/oaipmh"
34
+ Original-Repository = "https://github.com/infrae/pyoai"
35
+ Changelog = "https://github.com/eth-library/oaipmh/blob/main/CHANGELOG.md"
36
+ Issues = "https://github.com/eth-library/oaipmh/issues"
37
+
38
+ [project.optional-dependencies]
39
+ test = ["pytest"]
40
+
41
+ [tool.pytest.ini_options]
42
+ testpaths = ["src/oaipmh/tests"]
43
+
44
+ [tool.hatch.build.targets.wheel]
45
+ packages = ["src/oaipmh"]
46
+ exclude = [
47
+ "src/oaipmh/tests",
48
+ ]
49
+
50
+ [tool.hatch.build.targets.sdist]
51
+ include = [
52
+ "src/oaipmh",
53
+ "pyproject.toml",
54
+ "README.md",
55
+ "LICENSE",
56
+ "CHANGELOG.md",
57
+ "CONTRIBUTING.md",
58
+ ]
59
+ exclude = [
60
+ "src/oaipmh/tests",
61
+ ]
@@ -0,0 +1 @@
1
+ #