Core utilities for the Lythonic library.
This module provides foundational types and utilities used throughout Lythonic:
GlobalRef / GRef: Reference any Python object by its module path (e.g., "mymodule:MyClass").
Useful for configuration files and lazy loading.
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"
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
GRef = Annotated[GlobalRef, PlainSerializer(str, return_type=str), AfterValidator(GlobalRef), WithJsonSchema({'type': 'string'}, mode='serialization')]
module-attribute
GlobalRef
>>> 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'
Source code in src/lythonic/__init__.py
| class GlobalRef:
"""
>>> 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'
"""
module: str
name: str
def __init__(self, s: Any) -> None:
if isinstance(s, GlobalRef):
self.module, self.name = s.module, s.name
elif ismodule(s):
self.module, self.name = s.__name__, ""
elif isclass(s) or isfunction(s):
self.module, self.name = s.__module__, s.__name__
else:
split = s.split(":")
if len(split) == 1:
assert bool(split[0]), f"is {repr(s)} empty?"
split.append("")
else:
assert len(split) == 2, f"too many ':' in: {repr(s)}"
self.module, self.name = split
@override
def __str__(self):
return f"{self.module}:{self.name}"
@override
def __repr__(self):
return f"{self.__class__.__name__}({repr(str(self))})"
@override
def __eq__(self, other: Any) -> bool:
return str(self) == str(other)
@override
def __hash__(self) -> int:
return hash(str(self))
@override
def __ne__(self, other: Any) -> bool:
return not self == other
def get_module(self) -> ModuleType:
return __import__(self.module, fromlist=[""])
def is_module(self) -> bool:
return not (self.name)
def is_class(self) -> bool:
return not (self.is_module()) and isclass(self.get_instance())
def is_function(self) -> bool:
return not (self.is_module()) and isfunction(self.get_instance())
def is_async(self) -> bool:
if self.is_module():
return False
if self.is_class():
return iscoroutinefunction(self.get_instance().__call__)
return iscoroutinefunction(self.get_instance())
def get_instance(self) -> Any:
assert not self.is_module(), f"{repr(self)}.get_module() only"
attr = getattr(self.get_module(), self.name)
return attr
@classmethod
def __get_pydantic_core_schema__(
cls, source_type: Any, handler: GetCoreSchemaHandler
) -> CoreSchema:
return core_schema.no_info_after_validator_function(cls, handler(str))
|
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
|