Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add is_safe to rust UUID #70

Merged
merged 18 commits into from
Nov 21, 2024
3 changes: 3 additions & 0 deletions python/uuid_utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from uuid import SafeUUID

from ._uuid_utils import (
NAMESPACE_DNS,
NAMESPACE_OID,
Expand Down Expand Up @@ -29,6 +31,7 @@
"RESERVED_NCS",
"RFC_4122",
"UUID",
"SafeUUID",
"__version__",
"getnode",
"uuid1",
Expand Down
29 changes: 23 additions & 6 deletions python/uuid_utils/__init__.pyi
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import builtins
import sys
from enum import Enum
from uuid import SafeUUID

from _typeshed import Unused
from typing_extensions import TypeAlias
Expand All @@ -10,11 +10,6 @@ _FieldsType: TypeAlias = tuple[int, int, int, int, int, int]

__version__: str

class SafeUUID(Enum):
safe: int
unsafe: int
unknown: None

class UUID:
"""Instances of the UUID class represent UUIDs as specified in RFC 4122.
UUID objects are immutable, hashable, and usable as dictionary keys.
Expand Down Expand Up @@ -188,3 +183,25 @@ RESERVED_NCS: str
RFC_4122: str
RESERVED_MICROSOFT: str
RESERVED_FUTURE: str

__all__ = [
"NAMESPACE_DNS",
"NAMESPACE_OID",
"NAMESPACE_URL",
"NAMESPACE_X500",
"RESERVED_FUTURE",
"RESERVED_MICROSOFT",
"RESERVED_NCS",
"RFC_4122",
"UUID",
"SafeUUID",
"__version__",
"getnode",
"uuid1",
"uuid3",
"uuid4",
"uuid5",
"uuid6",
"uuid7",
"uuid8",
]
29 changes: 29 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use mac_address::get_mac_address;
use pyo3::{
exceptions::{PyTypeError, PyValueError},
ffi,
prelude::*,
pyclass::CompareOp,
types::{PyBytes, PyDict},
Expand Down Expand Up @@ -306,6 +307,18 @@ impl UUID {
uuid: Uuid::from_u128(int),
})
}

#[getter]
fn is_safe<'py>(&self, py: Python<'py>) -> Bound<'py, PyAny> {
unsafe {
match SAFE_UUID {
Some(safe_uuid) => Py::<PyAny>::from_owned_ptr(py, safe_uuid)
.bind(py)
.clone(),
None => panic!("SafeUUID not found"),
}
}
}
}

#[pyfunction]
Expand Down Expand Up @@ -429,13 +442,29 @@ fn _getnode() -> u64 {
node
}

static mut SAFE_UUID: Option<*mut ffi::PyObject> = None;

#[pyfunction]
fn getnode() -> PyResult<u64> {
Ok(_getnode())
}

#[pymodule]
fn _uuid_utils(m: &Bound<'_, PyModule>) -> PyResult<()> {
let x = Python::with_gil(|py| {
PyModule::import_bound(py, "uuid")
.unwrap()
.getattr("SafeUUID")
.unwrap()
.getattr("safe")
.unwrap()
.unbind()
});

unsafe {
SAFE_UUID = Some(x.as_ptr());
}

m.add("__version__", env!("CARGO_PKG_VERSION"))?;
m.add_class::<UUID>()?;
m.add_function(wrap_pyfunction!(uuid1, m)?)?;
Expand Down
7 changes: 6 additions & 1 deletion tests/test_uuid.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import pickle
import sys
from datetime import datetime
from uuid import UUID, getnode
from uuid import UUID, SafeUUID, getnode

import pytest
import uuid_utils
Expand Down Expand Up @@ -200,6 +200,11 @@ def test_copy() -> None:
assert copy.deepcopy(uuid) == uuid


def test_is_safe() -> None:
uuid = uuid_utils.uuid7()
assert uuid.is_safe is SafeUUID.safe


@pytest.mark.xfail(sys.platform == "linux", reason="Might fail in Github Actions")
def test_getnode() -> None:
assert uuid_utils.getnode() == getnode()
Loading