nautilus_core/python/
mod.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Python bindings from `pyo3`.
17
18pub mod casing;
19pub mod datetime;
20pub mod serialization;
21pub mod uuid;
22pub mod version;
23
24use pyo3::{
25    exceptions::{PyRuntimeError, PyTypeError, PyValueError},
26    prelude::*,
27    types::PyString,
28    wrap_pyfunction,
29};
30
31use crate::{
32    consts::{NAUTILUS_VERSION, USER_AGENT},
33    datetime::{
34        MILLISECONDS_IN_SECOND, NANOSECONDS_IN_MICROSECOND, NANOSECONDS_IN_MILLISECOND,
35        NANOSECONDS_IN_SECOND,
36    },
37    UUID4,
38};
39
40/// Gets the type name for the given Python `obj`.
41///
42/// # Errors
43///
44/// Returns a error if accessing the type name fails.
45pub fn get_pytype_name<'py>(obj: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyString>> {
46    obj.get_type().name()
47}
48
49/// Converts any type that implements `Display` to a Python `ValueError`.
50///
51/// # Errors
52///
53/// Returns a Python error with the error string.
54pub fn to_pyvalue_err(e: impl std::fmt::Display) -> PyErr {
55    PyValueError::new_err(e.to_string())
56}
57
58/// Converts any type that implements `Display` to a Python `TypeError`.
59///
60/// # Errors
61///
62/// Returns a Python error with the error string.
63pub fn to_pytype_err(e: impl std::fmt::Display) -> PyErr {
64    PyTypeError::new_err(e.to_string())
65}
66
67/// Converts any type that implements `Display` to a Python `RuntimeError`.
68///
69/// # Errors
70///
71/// Returns a Python error with the error string.
72pub fn to_pyruntime_err(e: impl std::fmt::Display) -> PyErr {
73    PyRuntimeError::new_err(e.to_string())
74}
75
76/// Loaded as nautilus_pyo3.core
77///
78/// # Errors
79///
80/// Returns a `PyErr` if registering any module components fails.
81#[pymodule]
82#[rustfmt::skip]
83pub fn core(_: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
84    m.add(stringify!(NAUTILUS_VERSION), NAUTILUS_VERSION)?;
85    m.add(stringify!(USER_AGENT), USER_AGENT)?;
86    m.add(stringify!(MILLISECONDS_IN_SECOND), MILLISECONDS_IN_SECOND)?;
87    m.add(stringify!(NANOSECONDS_IN_SECOND), NANOSECONDS_IN_SECOND)?;
88    m.add(stringify!(NANOSECONDS_IN_MILLISECOND), NANOSECONDS_IN_MILLISECOND)?;
89    m.add(stringify!(NANOSECONDS_IN_MICROSECOND), NANOSECONDS_IN_MICROSECOND)?;
90    m.add_class::<UUID4>()?;
91    m.add_function(wrap_pyfunction!(casing::py_convert_to_snake_case, m)?)?;
92    m.add_function(wrap_pyfunction!(datetime::py_secs_to_nanos, m)?)?;
93    m.add_function(wrap_pyfunction!(datetime::py_secs_to_millis, m)?)?;
94    m.add_function(wrap_pyfunction!(datetime::py_millis_to_nanos, m)?)?;
95    m.add_function(wrap_pyfunction!(datetime::py_micros_to_nanos, m)?)?;
96    m.add_function(wrap_pyfunction!(datetime::py_nanos_to_secs, m)?)?;
97    m.add_function(wrap_pyfunction!(datetime::py_nanos_to_millis, m)?)?;
98    m.add_function(wrap_pyfunction!(datetime::py_nanos_to_micros, m)?)?;
99    m.add_function(wrap_pyfunction!(datetime::py_unix_nanos_to_iso8601, m)?)?;
100    m.add_function(wrap_pyfunction!(datetime::py_last_weekday_nanos, m)?)?;
101    m.add_function(wrap_pyfunction!(datetime::py_is_within_last_24_hours, m)?)?;
102    Ok(())
103}