mirror of
https://git.pumpin.online/funkpower/catena.git
synced 2026-10-23 03:07:13 +00:00
bindings: what a closed subject scheme says about a heading
book-pipeline held its own copy of the scheme operations bibclean already had. The scheme itself — which headings a collection uses, their aliases, their parents — stays with the collection, because that is the most collection-specific thing there is. What a scheme *means* is the same question everywhere, and this answers it: `canonical_subject`, `compose_subjects`, `needs_subject`. Checked against the Python over the library's 228 distinct tags and all 5,385 books: identical on every one.
This commit is contained in:
@@ -215,6 +215,30 @@ pub fn parse_identifier(text: &str) -> Option<idnorm::Identifier> {
|
||||
idnorm::parse(text)
|
||||
}
|
||||
|
||||
/// What a closed subject scheme says about a set of headings.
|
||||
///
|
||||
/// The scheme is supplied rather than built in — which subjects a collection
|
||||
/// uses is the most collection-specific thing there is. These take it as the
|
||||
/// record `bibclean` reads from a file.
|
||||
pub fn canonical_subject(scheme: &bibclean::scheme::Scheme, name: &str) -> Option<String> {
|
||||
scheme.canonical(name).map(str::to_string)
|
||||
}
|
||||
|
||||
/// The subjects a book should carry: the chosen ones, their parents, and
|
||||
/// nothing the title rules out.
|
||||
pub fn compose_subjects(
|
||||
scheme: &bibclean::scheme::Scheme,
|
||||
subjects: &[String],
|
||||
title: Option<&str>,
|
||||
) -> Vec<String> {
|
||||
scheme.compose(subjects, title)
|
||||
}
|
||||
|
||||
/// Whether a book has no heading the scheme recognises.
|
||||
pub fn needs_subject(scheme: &bibclean::scheme::Scheme, existing: &[String]) -> bool {
|
||||
scheme.needs_subject(existing)
|
||||
}
|
||||
|
||||
/// The best author a record's own title and front matter can offer.
|
||||
///
|
||||
/// `None` when neither says anything that reads as a person's name, which is
|
||||
|
||||
@@ -220,6 +220,29 @@ fn identify<'py>(py: Python<'py>, name: &str, data: &[u8]) -> PyResult<Bound<'py
|
||||
to_py(py, &crate::identify(name, data))
|
||||
}
|
||||
|
||||
/// The subject a heading means under a scheme, or `None`.
|
||||
#[pyfunction]
|
||||
fn canonical_subject(scheme: &Bound<'_, PyAny>, name: &str) -> PyResult<Option<String>> {
|
||||
Ok(crate::canonical_subject(&from_py(scheme)?, name))
|
||||
}
|
||||
|
||||
/// The subjects a book should carry under a scheme.
|
||||
#[pyfunction]
|
||||
#[pyo3(signature = (scheme, subjects, title = None))]
|
||||
fn compose_subjects(
|
||||
scheme: &Bound<'_, PyAny>,
|
||||
subjects: Vec<String>,
|
||||
title: Option<&str>,
|
||||
) -> PyResult<Vec<String>> {
|
||||
Ok(crate::compose_subjects(&from_py(scheme)?, &subjects, title))
|
||||
}
|
||||
|
||||
/// Whether a book carries no heading the scheme recognises.
|
||||
#[pyfunction]
|
||||
fn needs_subject(scheme: &Bound<'_, PyAny>, existing: Vec<String>) -> PyResult<bool> {
|
||||
Ok(crate::needs_subject(&from_py(scheme)?, &existing))
|
||||
}
|
||||
|
||||
/// The best author a record's own title and front matter can offer.
|
||||
///
|
||||
/// `None` when neither says anything that reads as a person's name.
|
||||
@@ -314,6 +337,9 @@ fn _catena(module: &Bound<'_, PyModule>) -> PyResult<()> {
|
||||
module.add_function(wrap_pyfunction!(find_citations, module)?)?;
|
||||
module.add_function(wrap_pyfunction!(looks_like_footnote_citations, module)?)?;
|
||||
module.add_function(wrap_pyfunction!(suggest_author, module)?)?;
|
||||
module.add_function(wrap_pyfunction!(needs_subject, module)?)?;
|
||||
module.add_function(wrap_pyfunction!(compose_subjects, module)?)?;
|
||||
module.add_function(wrap_pyfunction!(canonical_subject, module)?)?;
|
||||
module.add_function(wrap_pyfunction!(citation_prompt, module)?)?;
|
||||
module.add_function(wrap_pyfunction!(merge_citation_reply, module)?)?;
|
||||
module.add_function(wrap_pyfunction!(series_of, module)?)?;
|
||||
|
||||
Reference in New Issue
Block a user