1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use pyo3::exceptions::{PyException, PyTypeError};
use pyo3::prelude::*;
use pyo3::pyclass::CompareOp;
use pyo3::types::PyType;
use std::str::FromStr;
use crate::errors::AlmanacResult;
use super::{Almanac, MetaAlmanac, MetaAlmanacError, MetaFile};
// Python only methods
#[cfg(feature = "python")]
#[cfg_attr(feature = "python", pymethods)]
impl MetaAlmanac {
/// Loads the provided path as a Dhall file. If no path is provided, creates an empty MetaAlmanac that can store MetaFiles.
#[new]
#[pyo3(signature=(maybe_path=None))]
pub fn py_new(maybe_path: Option<String>) -> Result<Self, MetaAlmanacError> {
match maybe_path {
Some(path) => Self::new(&path),
None => Ok(Self { files: Vec::new() }),
}
}
/// Loads the provided string as a Dhall configuration to build a MetaAlmanac
///
/// :type s: str
/// :rtype: MetaAlmanac
#[classmethod]
fn loads(_cls: &Bound<'_, PyType>, s: String) -> Result<Self, MetaAlmanacError> {
Self::from_str(&s)
}
/// Returns an Almanac loaded from the latest NAIF data via the `default` MetaAlmanac.
/// The MetaAlmanac will download the DE440s.bsp file, the PCK0008.PCA, the full Moon Principal Axis BPC (moon_pa_de440_200625) and the latest high precision Earth kernel from JPL.
///
/// # File list
/// - <http://public-data.nyxspace.com/anise/de440s.bsp>
/// - <http://public-data.nyxspace.com/anise/v0.5/pck08.pca>
/// - <http://public-data.nyxspace.com/anise/moon_pa_de440_200625.bpc>
/// - <https://naif.jpl.nasa.gov/pub/naif/generic_kernels/pck/earth_latest_high_prec.bpc>
///
/// # Reproducibility
///
/// Note that the `earth_latest_high_prec.bpc` file is regularly updated daily (or so). As such,
/// if queried at some future time, the Earth rotation parameters may have changed between two queries.
///
/// Set `autodelete` to true to delete lock file if a dead lock is detected after 10 seconds.
///
/// :type autodelete: bool, optional
/// :rtype: Almanac
#[classmethod]
#[pyo3(name = "latest")]
#[pyo3(signature=(autodelete=None))]
fn py_latest(
_cls: &Bound<'_, PyType>,
py: Python,
autodelete: Option<bool>,
) -> AlmanacResult<Almanac> {
let mut meta = Self::default();
py.detach(|| match meta.process(autodelete.unwrap_or(false)) {
Ok(almanac) => Ok(almanac),
Err(e) => Err(e),
})
}
/// Fetch all of the URIs and return a loaded Almanac.
/// When downloading the data, ANISE will create a temporarily lock file to prevent race conditions
/// where multiple processes download the data at the same time. Set `autodelete` to true to delete
/// this lock file if a dead lock is detected after 10 seconds. Set this flag to false if you have
/// more than ten processes which may attempt to download files in parallel.
///
/// :type autodelete: bool, optional
/// :rtype: Almanac
#[pyo3(name = "process")]
#[pyo3(signature=(autodelete=None))]
pub fn py_process(&mut self, py: Python, autodelete: Option<bool>) -> AlmanacResult<Almanac> {
py.detach(|| self.process(autodelete.unwrap_or(true)))
}
/// Serializes the configurated Meta Almanac into a Dhall string. Equivalent to dumps().
///
/// :rtype: str
#[pyo3(name = "to_dhall")]
fn py_to_dhall(&self) -> Result<String, PyErr> {
self.to_dhall()
.map_err(|e| PyException::new_err(e.to_string()))
}
/// Loads this Meta Almanac from its Dhall string representation
///
/// :type repr: str
/// :rtype: MetaAlmanac
#[classmethod]
#[pyo3(name = "from_dhall")]
fn py_from_dhall(_cls: Bound<'_, PyType>, repr: &str) -> Result<Self, PyErr> {
Self::from_dhall(repr).map_err(|e| PyException::new_err(e.to_string()))
}
fn __str__(&self) -> String {
format!("{self:?}")
}
fn __repr__(&self) -> String {
format!("{self:?} (@{self:p})")
}
fn __richcmp__(&self, other: &Self, op: CompareOp) -> Result<bool, PyErr> {
match op {
CompareOp::Eq => Ok(self == other),
CompareOp::Ne => Ok(self != other),
_ => Err(PyErr::new::<PyTypeError, _>(format!(
"{op:?} not available"
))),
}
}
/// :rtype: typing.List
#[getter]
fn get_files(&self) -> PyResult<Vec<MetaFile>> {
Ok(self.files.clone())
}
/// :type files: typing.List
#[setter]
fn set_files(&mut self, files: Vec<MetaFile>) -> PyResult<()> {
self.files = files;
Ok(())
}
}