adsfolio.pdf.registry

Root-scoped views over the central PDF catalog.

class adsfolio.pdf.registry.CentralPdfRegistry(directory)[source]

Bases: object

Root-scoped view over the user-wide PdfCatalog.

Parameters:

directory (Path)

change_token()[source]

Return this root and the catalog change token.

Return type:

tuple[str, tuple[int, …]]

close()[source]

Close the central catalog connection.

Return type:

None

count_ads_documents()[source]

Return the number of shared cached ADS documents.

Return type:

int

count_files()[source]

Return the number of current locations in this root.

Return type:

int

count_files_matching(**filters)[source]

Count current locations matching supported catalog filters.

Counts in SQL when the filters allow it. The source filter reads metadata JSON. Identification groups also read current identity evidence. duplicates_only compares digests and paper records across the filtered rows, so those still load the records.

Parameters:

filters (Any)

Return type:

int

delete_files_by_ids(file_ids)[source]

Delete selected current locations and orphaned attachments.

Parameters:

file_ids (list[int])

Return type:

int

export_payload()[source]

Return this root as a sidecar-shaped export.

Return type:

dict[str, Any]

find_ads_document_by_bibcode(bibcode)[source]

Return a cached ADS document by Bibcode.

Parameters:

bibcode (str)

Return type:

dict[str, Any] | None

find_ads_documents_by_bibcodes(bibcodes)[source]

Return cached documents by Bibcode.

Parameters:

bibcodes (list[str])

Return type:

dict[str, dict[str, Any]]

find_ads_documents_by_doi(doi)[source]

Return cached documents by normalized DOI.

Parameters:

doi (str)

Return type:

list[dict[str, Any]]

find_ads_documents_by_dois(dois)[source]

Return cached documents keyed by normalized DOI.

Parameters:

dois (list[str])

Return type:

dict[str, list[dict[str, Any]]]

find_file_by_current_path(root, current_path)[source]

Return the current location at current_path.

Parameters:
Return type:

dict[str, Any] | None

find_file_by_id(file_id)[source]

Return a current location for one attachment identifier.

Parameters:

file_id (int)

Return type:

dict[str, Any] | None

find_file_by_relative_path(root, relative_path)[source]

Return the current location at a root-relative path.

Parameters:
Return type:

dict[str, Any] | None

find_file_by_sha256(sha256)[source]

Return the first current location matching a digest.

Parameters:

sha256 (str)

Return type:

dict[str, Any] | None

find_files_by_bibcode(root, bibcode)[source]

Return unchanged current locations carrying one Bibcode.

Parameters:
Return type:

list[dict[str, Any]]

find_files_by_sha256(sha256_values)[source]

Return current locations matching any supplied digest.

Parameters:

sha256_values (list[str])

Return type:

list[dict[str, Any]]

find_location_by_id(location_id)[source]

Return a current location for one location identifier.

Parameters:

location_id (int)

Return type:

dict[str, Any] | None

get_meta(key)[source]

Return root-specific catalog metadata, falling back to global metadata.

Parameters:

key (str)

Return type:

str | None

iter_files(status=None, *, include_missing=False)[source]

Yield locations in this root, optionally including missing history.

Parameters:
  • status (str | None)

  • include_missing (bool)

Return type:

collections.abc.Iterator[dict[str, Any]]

query_files(*, order_by='relative_path', descending=False, secondary_order_by=None, tertiary_order_by=None, limit=None, offset=0, **filters)[source]

Return sorted and paged current locations for this root.

Parameters:
  • order_by (str)

  • descending (bool)

  • secondary_order_by (str | None)

  • tertiary_order_by (str | None)

  • limit (int | None)

  • offset (int)

  • filters (Any)

Return type:

list[dict[str, Any]]

query_records(**filters)[source]

Return filtered current locations in catalog order, without sorting.

Catalog order is relative_path and then location identifier. query_files sorts this list.

Parameters:

filters (Any)

Return type:

list[dict[str, Any]]

reconcile_file_facts(root, *, recursive=True, cancelled=None)[source]

Refresh current filesystem facts without deleting locations.

Parameters:
Return type:

adsfolio.pdf.registry.FileReconciliation

record_facts()[source]

Return count facts for every current location in this root.

The result is cached until the catalog change token changes, so repeated view and status counts parse the metadata JSON once.

Return type:

tuple[adsfolio.pdf.registry.RecordFact, …]

record_rename(root, relative_path, current_path, new_relative_path=None)[source]

Record a location move while retaining attachment identity.

Parameters:
Return type:

bool

refresh_local_files(*, recursive=True, cancelled=None)[source]

Scan local PDFs, update changed facts, and retain missing history.

No ADS queries or file renames are performed. Files with changed facts are hashed before discovery updates those facts. Incomplete directory scans raise an error instead of marking unseen paths missing.

Parameters:
Return type:

adsfolio.pdf.registry.LibraryRefresh

replace_file_metadata(root, relative_path, metadata)[source]

Replace one attachment’s local metadata.

Parameters:
Return type:

bool

replace_file_metadata_if_unchanged(root, relative_path, metadata, expected_record, *, expected_document=<object object>, changed_fields=None, allow_reviewed_stale_recovery=False)[source]

Replace metadata if the catalog still matches the original record.

See PdfCatalog.replace_file_metadata_if_unchanged for the snapshot requirements and transaction behavior.

Parameters:
Return type:

bool

save()[source]

Commit pending catalog writes and return the central path.

Return type:

pathlib.Path

property schema_version: int[source]

Return the central catalog schema version.

search_documents()[source]

Return exact and folded search documents for current locations.

Each entry holds the location identifier and the outputs of record_search_document and fold_document. Do not change them.

Return type:

tuple[tuple[int, dict[str, str], dict[str, str]], …]

search_location_keys(search, *, exact=False, wildcards=False, fields=())[source]

Return (root, location_id) keys that match the query search.

The keys equal the result of the catalog search filter with the same options. fields names the fields that plain terms search. See adsfolio.pdf.search.document_matches for the rules. The last result is cached until the catalog change token changes.

Parameters:
Return type:

frozenset[tuple[str, int]]

set_ads_document_metrics(bibcode, metrics)[source]

Store cached citation metrics.

Parameters:
Return type:

bool

set_meta(key, value)[source]

Set root-specific catalog metadata.

Parameters:
Return type:

None

sort_records(records, *, order_by='relative_path', descending=False, secondary_order_by=None, tertiary_order_by=None)[source]

Sort records in place with the query_files order rules.

Empty values sort last for each key, in both directions.

Parameters:
Return type:

None

update_file_status(root, relative_path, status)[source]

Update one attachment’s local status.

Parameters:
Return type:

bool

upsert_ads_document(document, *, source)[source]

Cache one ADS document in the central catalog.

Parameters:
Return type:

None

upsert_ads_documents(documents, *, source)[source]

Cache ADS documents atomically in the central catalog.

Parameters:
Return type:

None

upsert_file(*, root, relative_path, current_path, sha256, size_bytes, mtime_ns, status, metadata=None)[source]

Register one current root-relative file location.

Parameters:
Return type:

int

class adsfolio.pdf.registry.CentralPdfRegistryState(registry)[source]

Bases: object

State adapter exposing current catalog locations to CLI workflows.

Parameters:

registry (CentralPdfRegistry)

close()[source]

Close the central catalog.

Return type:

None

duplicates_by_sha256()[source]

Return duplicate current locations grouped by digest.

Return type:

dict[str, list[str]]

property files: dict[str, dict[str, Any]][source]

Return current location metadata keyed by relative path.

find_by_current_filename(filename)[source]

Find a current location by root-relative path.

Parameters:

filename (str)

Return type:

tuple[str, dict[str, Any]] | None

find_by_sha256(sha256)[source]

Find a current location by digest.

Parameters:

sha256 (str)

Return type:

tuple[str, dict[str, Any]] | None

get_file(relative_path)[source]

Return one current location in sidecar-shaped form.

Parameters:

relative_path (str)

Return type:

dict[str, Any] | None

property identify_profile: dict[str, Any] | None[source]

Return the saved identify profile.

property identify_settings: adsfolio.pdf.identify_settings.IdentifySettings | None[source]

Return root-specific reusable Identify settings.

property rename_settings: RenameSettings | None[source]

Return root-specific reusable Rename settings.

save()[source]

Commit pending catalog writes.

Return type:

pathlib.Path

set_current_filename(relative_path, current_filename)[source]

Record a move between current root-relative locations.

Parameters:
  • relative_path (str)

  • current_filename (str)

Return type:

bool

set_identify_profile(profile)[source]

Set identify profile metadata and report whether it changed.

Parameters:

profile (collections.abc.Mapping[str, Any] | None)

Return type:

bool

set_identify_settings(settings)[source]

Set root-specific reusable Identify settings.

Parameters:

settings (adsfolio.pdf.identify_settings.IdentifySettings | None)

Return type:

bool

set_rename_settings(settings)[source]

Set root-specific reusable Rename settings.

Parameters:

settings (RenameSettings | None)

Return type:

bool

upsert_file(relative_path, metadata)[source]

Register one current location through the central catalog.

Parameters:
Return type:

dict[str, Any]

class adsfolio.pdf.registry.FileReconciliation(scanned, updated, missing)[source]

Bases: object

Summary of filesystem facts reconciled against one catalog root.

Parameters:
missing: int
scanned: int
updated: int
class adsfolio.pdf.registry.LibraryRefresh(scanned, added, updated, moved, restored, missing)[source]

Bases: object

Count local file changes while retaining missing-location history.

Parameters:
added: int
missing: int
moved: int
restored: int
scanned: int
updated: int
adsfolio.pdf.registry.PdfRegistry

alias of adsfolio.pdf.registry.CentralPdfRegistry

adsfolio.pdf.registry.PdfRegistryState

alias of adsfolio.pdf.registry.CentralPdfRegistryState

class adsfolio.pdf.registry.RecordFact(root, location_id, group, source, sha256, document_id=None, edition='')[source]

Bases: NamedTuple

Hold the record values that view and status counts need.

The fields are the canonical library root, the catalog location identifier, the value of identification_group(record), the saved metadata source, and the current content digest. A missing source or digest is an empty string.

Parameters:
  • root (str)

  • location_id (int)

  • group (str)

  • source (str)

  • sha256 (str)

  • document_id (int | None)

  • edition (str)

document_id: int | None

Alias for field number 5

edition: str

Alias for field number 6

group: str

Alias for field number 2

location_id: int

Alias for field number 1

root: str

Alias for field number 0

sha256: str

Alias for field number 4

source: str

Alias for field number 3

adsfolio.pdf.registry.duplicate_kinds(keys)[source]

Return the duplicate kind of each PDF, or "" for a single copy.

Parameters:

keys (collections.abc.Sequence[tuple[str, int | None, str]]) – (sha256, document_id, edition) of each PDF, with the edition from pdf_edition. An empty digest or a None document does not group.

Returns:

DUPLICATE_SAME_FILE when another PDF has the same bytes. Otherwise DUPLICATE_SAME_PAPER when another PDF links to the same paper record and is the same edition. An unknown edition matches either edition. A preprint and its published edition are not duplicates.

Return type:

list of str

adsfolio.pdf.registry.mark_duplicates(records)[source]

Return the duplicate records with duplicate_kind and duplicate_group.

Copies of one paper share a group, including copies with the same bytes. When ADS links a preprint and its published edition to one record, each edition forms its own group. Copies without a paper record group by bytes.

Parameters:

records (list[dict[str, Any]])

Return type:

list[dict[str, Any]]

adsfolio.pdf.registry.merge_ads_metadata(existing, document)[source]

Merge nonempty ADS values while retaining locally locked fields.

Parameters:
Returns:

Merged metadata.

Return type:

dict[str, Any]

adsfolio.pdf.registry.migrate_sidecar(json_path, registry)[source]

Import legacy root data without modifying its source files.

Parameters:
Return type:

int

adsfolio.pdf.registry.open_registry_state(directory)[source]

Open a central catalog state view for one library root.

Parameters:

directory (pathlib.Path)

Return type:

adsfolio.pdf.registry.CentralPdfRegistryState

adsfolio.pdf.registry.order_duplicate_groups(records)[source]

Keep each duplicate group together and number the groups, in place.

The first copy of each group keeps its place in the current sort. The other copies of that group follow it. Groups are numbered from 1 in that order, in duplicate_group_number.

Parameters:

records (list[dict[str, Any]])

Return type:

None

adsfolio.pdf.registry.pdf_edition(record)[source]

Return "preprint", "published", or "" from the PDF’s own IDs.

The identity proof lists the identifiers that the PDF states. A journal DOI marks the published edition. An arXiv ID or arXiv DOI alone marks the preprint. ADS can link both editions to one paper record.

Parameters:

record (collections.abc.Mapping[str, Any])

Return type:

str

adsfolio.pdf.registry.stored_count(record, key)[source]

Return a saved non-negative count from a catalog record, or None.

The record’s own field is read first, then its metadata mapping. Whole numbers (int) and strings of decimal digits are accepted. Booleans, negative numbers, floats, and other text, including malformed digit strings, are treated as unknown, so a missing value is never reported as zero. The count is the value saved at the last ADS lookup, refresh, or manual edit, not a live ADS value.

Parameters:
  • record (Mapping[str, Any]) – Catalog record from PdfRegistry.query_files().

  • key (str) – Metadata key, such as “author_count” or “citation_count”.

Returns:

The saved count, or None when no valid count is saved.

Return type:

int or None

PdfRegistry is the compatibility alias of CentralPdfRegistry; PdfRegistryState aliases CentralPdfRegistryState. REGISTRY_FILENAME names the legacy per-root database. Use adsfolio.pdf.catalog.CATALOG_FILENAME for the central catalog filename.