All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Chain re-raised exceptions with
raise ... frominclient.py,server.py, anddatestamp.pyso tracebacks show the original cause (RuffB904/ PEP 3134). - Build the published wheel inside the project's Nix flake devShell
(
publish.yml). Pure-Python source semantics unchanged; published artifact bytes may differ across releases due to build-toolchain provenance. - Centralise CI cache wiring behind composite Actions in
.github/actions/;testandbuildnow also cache~/.cache/uv.
- Python 3.14 support. Added to the
pyproject.tomltrove classifiers and to the CI matrix; the test suite runs green on CPython 3.10 – 3.14.
- GitHub Actions in
ci.ymlandpublish.ymlpinned to full commit SHAs instead of mutable tags.
- Embed
README.mdas the project's long description on PyPI. The PEP 621readmefield was missing frompyproject.toml, so theoaipmh 3.0.0page on PyPI showed an empty body. No code or API changes; this is a packaging-metadata-only fix.
First release under the oaipmh distribution name on PyPI. This release marks the
maintenance fork from infrae/pyoai and brings the
codebase onto modern Python packaging and tooling. The public API and the
from oaipmh import ... import path are unchanged.
- Renamed PyPI distribution from
pyoaitooaipmh. Existing consumers must update their dependency declarations; no application code changes are required. - Minimum supported Python version raised to 3.10. Python 2 and Python 3.9 and earlier are no longer supported.
- Removed the
sixdependency; the package now relies exclusively on native Python 3 APIs.
- PEP 621 metadata in
pyproject.tomlwith Hatchling as the build backend. uv.lockfor reproducible dependency resolution.uv-based GitHub Actions CI covering Python 3.10 – 3.13.- GitHub Actions workflow (
publish.yml) for automated PyPI publishing via Trusted Publishing (OIDC; no long-lived tokens stored in the repository). - Reproducible development environment via a Nix flake and
direnvintegration. pytestconfiguration replacing the legacyruntests.shentry point.CONTRIBUTING.mdwith development setup, commit conventions, and the release process.CHANGELOG.md(this file), supersedingHISTORY.txt.ETH Library — Data Science and Research Support <dsr@library.ethz.ch>maintainer entry alongside the existing Jaime Cardozo entry.
- Build backend migrated from legacy
setup.py/setup.cfgto Hatchling viapyproject.toml. - Development status classifier raised from
4 - Betato5 - Production/Stable. - Version jumped from
2.5.2preto3.0.0to reflect the breaking distribution rename and the Python version floor. - README rewritten and expanded; converted from reStructuredText (
README.rst) to Markdown (README.md). - License file renamed from
LICENSE.txttoLICENSEand prepended with an ETH Zurich copyright notice alongside the original Infrae notice. - Wheel and sdist contents scoped via explicit
tool.hatch.buildinclude/exclude lists, so consumers no longer receive test fixtures or local development files. - Bare imports inside the package converted to relative imports.
- Replaced deprecated
datetime.utcnow()with timezone-awaredatetime.now(timezone.utc)equivalents (Python 3.12+ deprecation). - Replaced
lxml.etree.XPath.evaluate()calls with direct callable syntax for compatibility withlxml5.x. - Replaced
unicode()withstr()for Python 3 compatibility. - Replaced
pkg_resourceswithimportlib.metadatafor distribution version lookup. - Replaced removed unittest assertion aliases dropped in Python 3.12.
- Removed the
unittest.makeSuitehelper, which was dropped in Python 3.13. - Renamed the internal test helper
TestErrortoFakeRequestErrorto avoid pytest'sPytestCollectionWarningon classes prefixed withTest.
- Python 2 compatibility shims across the package and tests.
sixdependency.- Legacy packaging files:
setup.py,setup.cfg,tox.ini,MANIFEST.in, and.travis.yml. runtests.sh(replaced bypytest).- Non-functional Python 2 data generation scripts.
- Outdated
doc/directory. - Legacy Mercurial files.
HISTORY.txt(content migrated to this file).
- Customizable client retry policy.
- Python 3.8 compatibility.
- Do not resume
ListRecordrequests when no result was returned.
- Python 3 compatibility.
- Travis CI support and badges.
- Client switch to force harvesting using HTTP GET.
- Unofficial
GetMetadataverb in server and client.GetMetadatais identical toGetRecordbut returns only the first element below theoai:metadataelement, without the OAI envelope.
- Updated contact info.
- Migrated code from Subversion to Mercurial.
- Convert
lxml.etree._ElementUnicodeResultandElementStringResultto normalstrandunicodeobjects to prevent errors when these objects are pickled.
oai_dcanddcnamespace declarations are now declared on the child of the metadata element rather than the document root, per the OAI-PMH specification.
- When a date (not a datetime) is specified for the
untilparameter, default to23:59:59instead of00:00:00.
- Support for description elements in OAI
Identifyheaders, with atoolkitdescription included by default.
- Raise the correct error when
fromanduntilparameters have different granularities.
- Use
buildoutto create the testrunner and environment, replacing thetest.pyscript.
- Handle invalid
dateTimeformats correctly: the server now responds with aBadArgumentXML error instead of a Python traceback.
- XML declaration to server output.
- Pretty-printed XML output.
- Server resumption tokens now work with POST requests.
- Compatibility with
lxml2.0. - Handle
503responses from the server correctly in client code.
BatchingServer, implementing theIBatchingOAIinterface. Similar toIOAIbut withcursorandbatch_sizearguments on each method, enabling efficient batching OAI servers on top of relational databases.- Ability to explicitly pass
Noneas thefromoruntilparameter for an OAI-PMH client. - Extra
nsmapargument onServerandBatchingServerto customise the namespace prefix to URI mappings used in server output.
- Output encoding bug: output is now correctly encoded as UTF-8.
- Compatibility with
lxml1.1.
- Distribute as an egg.
- Infrastructure to handle non-XML-compliant OAI-PMH feeds; an
XMLSyntaxErroris now raised in those cases. tolerant_datestamp_to_datetime, a more permissive alternative todatestamp_to_datetimefor handling malformed datestamps.
- Split datestamp handling into a separate
datestampmodule.
- Support for day-only granularity (
YYYY-MM-DD) in the client. CallingupdateGranularitychecks with the server (viaidentify()) which granularity it supports; if the server only supports day-level granularity, the client restricts outgoing timestamps toYYYY-MM-DD.
- Framework for implementing OAI-PMH-compliant servers.
- Extended testing infrastructure.
- Package structure is now an
oaipmhnamespace package; client functionality moved tooaipmh.client. - Refactored
oaipmh.pyto share code between the client and server. - Switched from the
libxml2Python wrappers to thelxmlbinding. listRecords,listIdentifiers, andlistSetsnow return iterators instead of lists (previously hacked via__getitem__). Existing call sites can wrap the result inlist()if needed.
- Typo in
oaipmh.py.
encodingparameter to theserializecall, fixing a Unicode bug.
- Harvested records with
<header status="deleted">are no longer stored in the catalog. Previously they could be treated as normal records even though they merely indicate that the metadata set is no longer on the OAI service.
Initial public release.