neopdf/
manage.rs

1use neopdf::manage::{ManageData, PdfSetFormat};
2use pyo3::exceptions::PyRuntimeError;
3use pyo3::prelude::*;
4
5/// Python wrapper for the `PdfSetFormat` enum.
6#[pyclass(name = "PdfSetFormat")]
7#[derive(Clone)]
8pub enum PyPdfSetFormat {
9    /// LHAPDF format (standard PDF set format used by LHAPDF).
10    Lhapdf,
11    /// NeoPDF format (native format for this library).
12    Neopdf,
13}
14
15impl From<PyPdfSetFormat> for PdfSetFormat {
16    fn from(fmt: PyPdfSetFormat) -> Self {
17        match fmt {
18            PyPdfSetFormat::Lhapdf => Self::Lhapdf,
19            PyPdfSetFormat::Neopdf => Self::Neopdf,
20        }
21    }
22}
23
24/// Python wrapper for the `ManageData` struct.
25#[pyclass(name = "ManageData")]
26pub struct PyManageData {
27    pub(crate) inner: ManageData,
28}
29
30#[pymethods]
31impl PyManageData {
32    /// Create a new ManageData instance.
33    #[new]
34    #[must_use]
35    pub fn new(set_name: &str, format: PyPdfSetFormat) -> Self {
36        Self {
37            inner: ManageData::new(set_name, format.into()),
38        }
39    }
40
41    /// Download the PDF set and extract it into the designated path.
42    ///
43    /// Attempts to download the PDF set and extract it to the appropriate directory.
44    ///
45    /// # Returns
46    ///
47    /// Returns `Ok(())` if the download and extraction succeed, or a `PyRuntimeError`
48    /// if the operation fails.
49    ///
50    /// # Errors
51    ///
52    /// Returns a `PyRuntimeError` if the download or extraction fails due to network
53    /// issues, missing files, or I/O errors.
54    pub fn download_pdf(&self) -> PyResult<()> {
55        self.inner
56            .download_pdf()
57            .map_err(|e| PyRuntimeError::new_err(format!("{e}")))
58    }
59
60    /// Check that the PDF set is installed in the correct path.
61    ///
62    /// Returns `true` if the PDF set is installed, `false` otherwise.
63    #[must_use]
64    pub fn is_pdf_installed(&self) -> bool {
65        self.inner.is_pdf_installed()
66    }
67
68    /// Ensure that the PDF set is installed, otherwise download it.
69    ///
70    /// Ensures the PDF set is present; if not, attempts to download and install it.
71    ///
72    /// # Returns
73    ///
74    /// Returns `Ok(())` if the set is installed or successfully downloaded, or a
75    /// `PyRuntimeError` if the operation fails.
76    ///
77    /// # Errors
78    ///
79    /// Returns a `PyRuntimeError` if the download or installation fails due to network
80    /// issues, missing files, or I/O errors.
81    pub fn ensure_pdf_installed(&self) -> PyResult<()> {
82        self.inner
83            .ensure_pdf_installed()
84            .map_err(|e| PyRuntimeError::new_err(format!("{e}")))
85    }
86
87    /// Get the name of the PDF set.
88    #[must_use]
89    pub fn set_name(&self) -> &str {
90        self.inner.set_name()
91    }
92
93    /// Get the path where PDF sets are stored.
94    #[must_use]
95    pub fn data_path(&self) -> String {
96        self.inner.data_path().to_string_lossy().to_string()
97    }
98
99    /// Get the full path to this specific PDF set.
100    #[must_use]
101    pub fn set_path(&self) -> String {
102        self.inner.set_path().to_string_lossy().to_string()
103    }
104}
105
106/// Registers the manage module with the parent Python module.
107///
108/// Adds the `manage` submodule to the parent Python module, exposing PDF set
109/// management utilities to Python.
110///
111/// # Errors
112///
113/// Returns a `PyErr` if the submodule cannot be created or added, or if any
114/// class registration fails.
115pub fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> {
116    let m = PyModule::new(parent_module.py(), "manage")?;
117    m.setattr(
118        pyo3::intern!(m.py(), "__doc__"),
119        "PDF set management utilities.",
120    )?;
121    pyo3::py_run!(
122        parent_module.py(),
123        m,
124        "import sys; sys.modules['neopdf.manage'] = m"
125    );
126    m.add_class::<PyPdfSetFormat>()?;
127    m.add_class::<PyManageData>()?;
128    parent_module.add_submodule(&m)
129}