Skip to main content

arxiv-title

Renames arXiv PDFs from opaque identifiers to descriptive, title-based filenames.

2101.05536v1.pdf
  -> 2101.05536v1_scaling_equilibrium_propagation_to_deep_convnets_by_drastically_reducing_its_gradient_estimator_bias.pdf

Install

python -m venv .venv
.venv/bin/pip install -e ".[dev]"

Use

arxiv-title artifacts/                 # rename every arXiv-named PDF in a directory
arxiv-title -n artifacts/              # --dry-run: preview, touch nothing
arxiv-title --offline artifacts/       # no network; use the PDFs alone
arxiv-title 2101.05536v1.pdf           # a single file
Flag Effect
-n, --dry-run Print the rename table and exit without changing anything
--offline Skip the arXiv API layer
-r, --recursive Descend into subdirectories
--force Accept titles that were only guessed from page layout
--no-id-prefix Emit how_frogs_croak.pdf instead of 2101.05536v1_how_frogs_croak.pdf
-v, --verbose Show which source supplied each title

Only files whose name starts with an arXiv identifier are considered when scanning a directory; anything else is left alone. Because the ID is kept as a prefix by default, a second run over an already-renamed directory is a clean no-op.

How the title is found

Three sources, tried in order and reported by --verbose:

  1. api — the arXiv Atom API, looked up by the identifier in the filename. Exact canonical titles, one batched HTTP request for the whole directory.
  2. metadata — the PDF's own /Title entry.
  3. layout — typography on page one: the first contiguous block of larger-than-body-text lines near the top of the page.

Layout results are treated as low-confidence and held back from renaming unless you pass --force.

Why the layout heuristic is not just "the largest text"

The obvious rule — take the biggest text on page one — gets 4 of the 10 sample papers right. Two problems dominate, both artifacts of how LaTeX sets titles:

  • Small caps and enlarged leading capitals. \textsc{} titles set the full capitals several points larger than the small capitals. A largest-glyph rule selects that one letter and reports a title of "M". Fixed by taking each line's character-count weighted dominant size, so twenty body letters outvote one oversized capital.
  • Split lines. Those same enlarged capitals sit higher on the page than the rest of the line, so grouping words by their top coordinate tears one visual line in two — yielding T D H : T M L followed by HE RAGON ATCHLING …. Fixed by clustering on the baseline, which the two sizes share to within a point.

Two smaller details matter as well: extract_words splits a run wherever the font size changes, so adjacent fragments must be rejoined without a space (otherwise The becomes T he), and titles routinely wrap across two or three lines that need rejoining.

With those in place the layout heuristic alone gets all 10 of the sample papers right.

Tests

.venv/bin/python -m pytest

The suite is self-contained: extraction runs against three small PDFs committed under tests/pdf/, and the API tests use a mocked transport. No network and no local corpus required.

Releasing

CI runs the suite on Python 3.10–3.13 for every push and PR.

Publishing to PyPI happens only when a GitHub Release is published — a tag push alone does nothing. The release job builds an sdist and wheel, runs twine check --strict, verifies the tag matches the version in pyproject.toml, and uploads via PyPI Trusted Publishing (OIDC), so no API token is stored anywhere.

One-time setup on PyPI, at https://pypi.org/manage/account/publishing/, add a pending publisher:

Field Value
PyPI project arxiv-title
Owner cms-pm
Repository arxiv-title
Workflow release.yml
Environment pypi

Then create a matching GitHub environment named pypi under Settings → Environments. Repeat with testpypi on test.pypi.org if you want the dry-run path.

To cut a release:

# bump version in pyproject.toml, commit, then
git tag v0.1.0 && git push origin v0.1.0
gh release create v0.1.0 --generate-notes

To rehearse without touching PyPI, run the Release workflow manually with the testpypi target.

Metadata

Release files for arxiv-title 0.1.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 arxiv-title 0.1.0
File Size Uploaded
arxiv_title-0.1.0.tar.gz 19.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for arxiv-title 0.1.0
File Interpreter ABI Platform
arxiv_title-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 35.0 kB

Release files / arxiv_title-0.1.0.tar.gz

Download URL arxiv_title-0.1.0.tar.gz
Size 19.3 kB
Tags Source
SHA-256 checksum
How to use checksums
5b2e869536e532586ab1a6bd520d8ddb235cfad9410a195a3c014b306dd8a70b
BLAKE2b-256 checksum
How to use checksums
87ca2718fc64e9afccb6e9c79254e744ba2be3bf2087bb0b84337eb571410cda
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 4, 2026.

Transparency log

Release files / arxiv_title-0.1.0-py3-none-any.whl

Download URL arxiv_title-0.1.0-py3-none-any.whl
Size 15.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2a5948bdbba15f11fc5124d5cebc25aaec0a0cf080008675cfacf219240a2d5a
BLAKE2b-256 checksum
How to use checksums
7f922de6f07cc9f4cd4f62618d2c35fbd996a51f1716027edc94092620f1ac85
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 4, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

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