Skip to main content

pixls-preprints

Python Version License: MIT Code style: black

Access and store metadata from different APIs offering preprint publications.

pixls-preprints is an asynchronous command line harvester for preprint metadata. It queries bioRxiv, medRxiv and OSF for a range of dates and writes the results as JSON Lines: one document per line, one file per source.

$ python -m pixls_preprints --start 2024-07-14 --dest data --servers biorxiv osf
$ wc -l data/biorxiv/2024-07-14.json
49 data/biorxiv/2024-07-14.json

Why use it

  • Fast. Everything is asynchronous: all pages of a query are fetched concurrently, and so are the sources. You get as much speed as your rate limit allows, and an OSF token raises that ceiling.
  • Several sources, one command. bioRxiv, medRxiv and OSF sit behind a single uniform CLI, each writing into its own output file.
  • Polite by default. Every source has its own rate limit (requests per time window) and concurrency cap, so you stay within what the upstream API grants you.
  • Survives flaky APIs. 429, 502, 503, 504 and dropped connections are retried with a back-off, honouring Retry-After. Whatever still fails is logged, counted and reported at the end of the run, not fatal.
  • Streams to disk. Each page is written as soon as it arrives, so a long harvest does not accumulate in memory and partial results survive an interruption.
  • JSON Lines output. Results can be appended, read line by line without loading a whole file, and fed straight into a downstream indexing pipeline.
  • Layered configuration. Config file, then environment variables, then defaults. Tokens are read only from the environment, never from the config file.
  • Easy to extend. A new preprint server means one new subclass of Source. The HTTP client, rate limiting, retries and file writing are inherited.

Requirements

  • Python 3.11 or newer (the project is developed against 3.14, see .python-version)
  • uv for dependency management
  • An OSF API token, which is optional but raises the rate limit OSF grants you

Installation

git clone https://codeberg.org/pixls/pixls-preprints.git
cd pixls-preprints
uv sync

Then create the two local files. Both are optional and both are ignored by git, so every clone needs its own copy:

cp config.toml.example config.toml
cp .env.example .env          # then put your OSF token in it

Without config.toml the tool falls back to the defaults shipped inside the package, which hold the same values as config.toml.example. .env is loaded automatically at startup, so there is no need to source it, and variables already set in your shell take precedence over it.

Usage

Run the package as a module:

uv run python -m pixls_preprints -d data -srv biorxiv osf

Installing the package instead provides a pixls-preprints command, which takes the same options and needs no config file to start:

uv pip install pixls-preprints
pixls-preprints -d data -srv biorxiv osf

Without a date, yesterday is harvested. The destination directory gets one subdirectory per source, and the output file is named after the requested range.

A single day from bioRxiv:

uv run python -m pixls_preprints -s 2024-07-14 -d data -srv biorxiv
# -> data/biorxiv/2024-07-14.json

A whole month from two sources, into one file each:

uv run python -m pixls_preprints -s 2024-07-01 -e 2024-07-31 -d data -srv medrxiv osf
# -> data/medrxiv/2024-07-01_-_2024-07-31.json
# -> data/osf/2024-07-01_-_2024-07-31.json

The same month, but one file per day, overwriting what is already there:

uv run python -m pixls_preprints -s 2024-07-01 -e 2024-07-31 -S -F -d data -srv biorxiv
# -> data/biorxiv/2024-07-01.json … data/biorxiv/2024-07-31.json

A custom file name and a config file from somewhere else:

uv run python -m pixls_preprints -s 2024-07-14 -d data -f july.json -c /etc/pixls/config.toml

Existing output files are never silently overwritten: the source is skipped with a note unless you pass --force. Log records are appended to pixls_preprints_cli.log in the directory you ran the command from.

If requests are given up on after their retries, the output file is short. The run still finishes and still exits 0, but prints one warning per source saying how many requests were lost:

$ uv run python -m pixls_preprints -s 2024-07-14 -d data -srv biorxiv osf
WARNING: biorxiv: 3 requests failed permanently, output may be incomplete

Options

Option Description
-s, --start Start date (YYYY-MM-DD), defaults to yesterday
-e, --end End date (YYYY-MM-DD), defaults to the start date
-d, --dest Required. Destination directory, gets one subdirectory per source
-srv, --servers Required. Sources to fetch from: biorxiv, medrxiv, osf (one or more)
-f, --file Output file name, defaults to a name built from the dates
-S, --split-daily Write one output file per day instead of one for the whole range
-F, --force Overwrite already existing output files
-c, --config Path to the config file, defaults to config.toml in the directory you run from

An end date without a start date is an error. Note that bioRxiv and medRxiv select by publication date, while OSF selects by modification date.

Configuration

Per-source settings are resolved from three places, in this order of precedence:

  1. the TOML config file
  2. environment variables named PIXLS_PREPRINTS_<SOURCE>_<SETTING>
  3. the defaults shipped with the package, in pixls_preprints/config_defaults.toml

The config file is the one given with -c, or config.toml in the directory you run from. A path given with -c has to exist, otherwise the run stops with Config file not found. Without a config file the run uses the packaged defaults, and says so in the log.

# config.toml
[biorxiv]
max_rate = 1          # requests allowed per time_period
time_period = 0.4     # length of the rate limit window, in seconds
max_concurrency = 7   # requests in flight at most

[osf]
max_rate = 1
time_period = 1.5
max_concurrency = 10
page_size = 50        # documents requested per page

Tokens are the exception: they are read only from the environment. A token entry in the config file is ignored and produces a warning.

# .env
export PIXLS_PREPRINTS_OSF_TOKEN=your-token-here

See config.toml.example and .env.example for the full set of keys.

Output format

One JSON document per line, in whatever shape the upstream API returns it. bioRxiv and medRxiv records look like this (abridged):

{"doi": "10.1101/001891", "title": "Population genomics of …", "authors": "Carlotta De Filippo;Monica Di Paola;…", "date": "2014-01-17", "version": "1", "type": "New Results", "license": "cc_by_nc_nd", "category": "Evolutionary Biology", "abstract": "…", "server": "biorxiv"}

OSF records follow the JSON:API shape of the OSF v2 API, with bibliographic contributors and license embedded so no extra request per preprint is needed.

Development

The Makefile wraps the common tasks:

make test              # run the test suite, skipping tests that need network access
make test-online       # run only the tests that talk to the real APIs
make check-formatting  # black, in check mode
make formatting        # black, rewriting files
make check-code        # flake8
make check-coverage    # pytest with coverage
make audit             # formatting + lint + tests, the pre-merge gate

Tests are marked with medium, large and online (see pytest.ini), so you can deselect the slow or network-dependent ones, for example uv run pytest -m "not online" tests/.

Project layout

pixls_preprints/
├── cli.py            # argument parsing, date handling, task orchestration
├── config.py         # config file + environment + defaults
├── fetcher.py        # rate-limited async HTTP client with retries
└── sources/
    ├── source.py     # abstract base class shared by all sources
    ├── biorxiv.py    # bioRxiv and medRxiv (cursor paging)
    └── osf.py        # OSF (page-number paging, optional token)

To add a source, subclass Source, implement url, fetch() and fetch_preprints(), and wire it into _gather_tasks() and the --servers choices in pixls_preprints/cli.py.

Getting help

Contributing

Contributions are welcome. Please read CONTRIBUTING.md for the workflow, coding conventions and what make audit expects before you open a pull request.

Maintainers

Developed and maintained by Benjamin Wolff (wolff@zbmed.de) at ZB MED – Information Centre for Life Sciences, as part of the PIXLS project.

Funding

Funded by the Deutsche Forschungsgemeinschaft (DFG)

Developed in PIXLS – Preprint Information eXtraction for Life Sciences, funded by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation).

License

Source code is licensed under the MIT License. Documentation and other content are licensed under CC BY 4.0, and configuration and generated files under CC0 1.0. See LICENSING.md for details.

Metadata

Release files for pixls-preprints 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pixls-preprints 1.0.0
File Size Uploaded Provenance Actions
pixls_preprints-1.0.0.tar.gz 234.7 kB Without provenance Details for pixls_preprints-1.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pixls-preprints 1.0.0
File Interpreter ABI Platform Actions
pixls_preprints-1.0.0-py3-none-any.whl Python 3 none any Details for pixls_preprints-1.0.0-py3-none-any.whl

Total release size: 260.9 kB

Release files / pixls_preprints-1.0.0.tar.gz

Download URL pixls_preprints-1.0.0.tar.gz
Size 234.7 kB
Tags Source
SHA-256 checksum
How to use checksums
ec39ef4c4c8e9ed2e1a02f8b19aa4f0f180f03ed078178f3d8ce6c5c09bbc718
BLAKE2b-256 checksum
How to use checksums
d48eb252b9e8c75c69537e477da3b9ccc9321d56de4d6a59e0c2043a5acc5799
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / pixls_preprints-1.0.0-py3-none-any.whl

Download URL pixls_preprints-1.0.0-py3-none-any.whl
Size 26.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8de09c9a6bcf60277a4380ada83dd4f92bb5f64e5e5c6413e5c403b9d953b477
BLAKE2b-256 checksum
How to use checksums
0d894367d48f6e3093f5b9e9c4575e59bea133afd0d4d7dfae557013266ea959
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for pixls-preprints 1.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page