Skip to content

lythonic

Core utilities: global references, Result type, and helpers.

Core utilities for the Lythonic library.

This module provides foundational types and utilities used throughout Lythonic:

  • GlobalRef: Reference any Python object by its module path (e.g., "mymodule:MyClass"). Useful for configuration files and lazy loading.
  • ModuleRef: Reference a Python module by its import path (e.g., "json").
  • Result[TOk, TErr]: A Rust-inspired Result type for explicit error handling without exceptions.
  • utc_now(): Get the current UTC datetime.
  • get_module(): Import a module by name.

GlobalRef Usage

from lythonic import GlobalRef

# Reference a class by string
ref = GlobalRef("json:dumps")
dumps_func = ref.get_instance()

# Reference from an object
ref = GlobalRef(MyClass)
print(ref)  # "mymodule:MyClass"

ModuleRef Usage

from lythonic import ModuleRef

# Reference a module by string
ref = ModuleRef("json")
mod = ref.import_module()

# Reference from a module object
ref = ModuleRef(json)
print(ref)  # "json"

Result Usage

from lythonic import Result

def divide(a: int, b: int) -> Result[float, str]:
    if b == 0:
        return Result.Err("division by zero")
    return Result.Ok(a / b)

result = divide(10, 2)
if result.is_ok():
    print(result.unwrap())  # 5.0

GlobalRef = GlobalRef module-attribute

A reference to a Python object identified by module path and name.

Accepts a string "module.path:name", a module, a class, a function, or another GlobalRef instance. Module-only references use an empty name.

The string representation is always "module.path:name" (or "module.path:" for module-only refs), matching NsRef format where scope is the module path parts.

>>> ref = GlobalRef('lythonic:GlobalRef')
>>> ref
GlobalRef('lythonic:GlobalRef')
>>> ref.get_instance().__name__
'GlobalRef'
>>> ref.is_module()
False
>>> ref.get_module().__name__
'lythonic'
>>> grgr = GlobalRef(GlobalRef)
>>> grgr
GlobalRef('lythonic:GlobalRef')
>>> grgr.get_instance()
<class 'lythonic.GlobalRef'>
>>> grgr.is_class()
True
>>> grgr.is_function()
False
>>> grgr.is_module()
False
>>> uref = GlobalRef('lythonic:')
>>> uref.is_module()
True
>>> uref.get_module().__name__
'lythonic'
>>> uref = GlobalRef('lythonic')
>>> uref.is_module()
True
>>> uref = GlobalRef(uref)
>>> uref.is_module()
True
>>> uref.get_module().__name__
'lythonic'
>>> uref = GlobalRef(uref.get_module())
>>> uref.is_module()
True
>>> uref.get_module().__name__
'lythonic'

Result

Bases: Generic[TOk, TErr]

A generic Result type inspired by Rust, representing either success (Ok) or failure (Err).

Source code in src/lythonic/__init__.py
@final
class Result(Generic[TOk, TErr]):
    """
    A generic Result type inspired by Rust, representing either success (Ok) or failure (Err).
    """

    _ok: TOk | None
    _err: TErr | None

    __slots__ = ("_ok", "_err")

    def __init__(self, ok: TOk | None = None, err: TErr | None = None) -> None:
        assert (ok is None and err is not None) or (ok is not None and err is None), (
            "Result can only have one of ok or err set."
        )
        self._ok = ok
        self._err = err

    @classmethod
    def Ok(cls, value: TOk) -> "Result[TOk, TErr]":
        return cls(ok=value)

    @classmethod
    def Err(cls, error: TErr) -> "Result[TOk, TErr]":
        return cls(err=error)

    def is_ok(self) -> bool:
        return self._ok is not None

    def is_err(self) -> bool:
        return self._err is not None

    def ok(self) -> TOk | None:
        return self._ok

    def err(self) -> TErr | None:
        return self._err

    def unwrap(self) -> TOk:
        if self._ok is not None:
            return self._ok
        raise ValueError(f"Called unwrap on Err: {self._err}")

    def unwrap_err(self) -> TErr:
        if self._err is not None:
            return self._err
        raise ValueError(f"Called unwrap_err on Ok: {self._ok}")

    @override
    def __repr__(self):
        if self.is_ok():
            return f"Ok({self._ok!r})"
        else:
            return f"Err({self._err!r})"

get_module(name)

>>> type(get_module('lythonic'))
<class 'module'>
>>> get_module('lythonic.c99')
Traceback (most recent call last):
...
ModuleNotFoundError: No module named 'lythonic.c99'
Source code in src/lythonic/__init__.py
def get_module(name: str) -> ModuleType:
    """
    >>> type(get_module('lythonic'))
    <class 'module'>
    >>> get_module('lythonic.c99')
    Traceback (most recent call last):
    ...
    ModuleNotFoundError: No module named 'lythonic.c99'
    """
    if name in sys.modules:
        return sys.modules[name]
    return __import__(name, fromlist=[""])

utc_now()

return the current time in UTC

utc_now().tzinfo datetime.timezone.utc

Source code in src/lythonic/__init__.py
def utc_now() -> datetime:
    """return the current time in UTC
    >>> utc_now().tzinfo
    datetime.timezone.utc
    """
    return datetime.now(UTC)

str_or_none(s)

>>> str_or_none(None)
>>> str_or_none(5)
'5'
>>> str_or_none('')
''
Source code in src/lythonic/__init__.py
def str_or_none(s: Any) -> str | None:
    """
    >>> str_or_none(None)
    >>> str_or_none(5)
    '5'
    >>> str_or_none('')
    ''
    """
    return str(s) if s is not None else None