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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

arxiv_title-0.1.0.tar.gz (19.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

arxiv_title-0.1.0-py3-none-any.whl (15.6 kB view details)

Uploaded Python 3

File details

Details for the file arxiv_title-0.1.0.tar.gz.

File metadata

  • Download URL: arxiv_title-0.1.0.tar.gz
  • Upload date:
  • Size: 19.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for arxiv_title-0.1.0.tar.gz
Algorithm Hash digest
SHA256 5b2e869536e532586ab1a6bd520d8ddb235cfad9410a195a3c014b306dd8a70b
MD5 4ecd0ce34b905a68ce03591bc6133095
BLAKE2b-256 87ca2718fc64e9afccb6e9c79254e744ba2be3bf2087bb0b84337eb571410cda

See more details on using hashes here.

Provenance

The following attestation bundles were made for arxiv_title-0.1.0.tar.gz:

Publisher: release.yml on cms-pm/arxiv-title

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file arxiv_title-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: arxiv_title-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 15.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for arxiv_title-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2a5948bdbba15f11fc5124d5cebc25aaec0a0cf080008675cfacf219240a2d5a
MD5 a4cac74c1aa31dd46bc09f95f07b3784
BLAKE2b-256 7f922de6f07cc9f4cd4f62618d2c35fbd996a51f1716027edc94092620f1ac85

See more details on using hashes here.

Provenance

The following attestation bundles were made for arxiv_title-0.1.0-py3-none-any.whl:

Publisher: release.yml on cms-pm/arxiv-title

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page