hbutils.model.clazz
Class modeling utilities for declarative Python objects.
This module provides decorators and helper functions that simplify the creation of lightweight data-centric classes. It focuses on generating commonly needed behaviors such as automatic field access, visual representations, constructor generation, hash/equality support, and property accessors, all while supporting name-mangled private attributes.
The module contains the following main public components:
get_field()- Retrieve attributes with support for private name manglingasitems()- Declare class-level field namesvisual()- Generate a human-friendly__repr__implementationconstructor()- Generate an__init__constructor from field specshasheq()- Generate__hash__,__eq__, and__ne__methodsaccessor()- Generate property accessors for private fields
Example:
>>> @accessor(readonly=True)
>>> @visual()
>>> @constructor(['x', ('y', 2)])
>>> class Point:
... pass
>>> p = Point(1)
>>> p
<Point x: 1, y: 2>
>>> p.x
1
Note
These decorators are designed to cooperate. For example, using
asitems() enables automatic field discovery by constructor(),
visual(), and hasheq().
__all__
- hbutils.model.clazz.__all__ = ['get_field', 'asitems', 'visual', 'constructor', 'hasheq', 'accessor']
Built-in mutable sequence.
If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.
CLASS_WRAPPER_UPDATES
- hbutils.model.clazz.CLASS_WRAPPER_UPDATES = ()
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable’s items.
If the argument is a tuple, the return value is the same object.
get_field
- hbutils.model.clazz.get_field(obj: ~typing.Any, name: str, default: ~typing.Any = <SingletonMark 'no_default_value'>) Any[source]
Get field from object with support for private attributes.
This function resolves name-mangled private attributes and uses
getattrto fetch the field. When adefaultis provided, it will be returned instead of raisingAttributeError.- Parameters:
obj (object) – The given object.
name (str) – Field to be retrieved.
default (Any, optional) – Default value to return if the field does not exist. If not provided, the absence of the field raises
AttributeError.
- Returns:
Field value for the requested field.
- Return type:
Any
- Raises:
AttributeError – If the field does not exist and no default is provided.
Example:
>>> class MyClass: ... def __init__(self): ... self.__private_field = 42 >>> obj = MyClass() >>> get_field(obj, '__private_field') 42 >>> get_field(obj, 'nonexistent', default='default_value') 'default_value'
asitems
- hbutils.model.clazz.asitems(items: Iterable[str]) Callable[[Type[Any]], Type[Any]][source]
Define fields in the class level.
This decorator assigns the provided field names to
__items__, which can be consumed by other decorators such asconstructor(),visual(),hasheq(), andaccessor().- Parameters:
items (Iterable[str]) – Field name items.
- Returns:
Decorator to decorate the given class.
- Return type:
Callable
Example:
>>> @visual() >>> @constructor(doc=''' ... Overview: ... This is the constructor of class :class:`T`. ... ''') >>> @asitems(['x', 'y']) >>> class T: ... @property ... def x(self): ... return self.__first ... ... @property ... def y(self): ... return self.__second
Note
This decorator sets
__items__on the class, which is used by other decorators to determine which fields to process.
visual
- hbutils.model.clazz.visual(items: Iterable[str | Tuple[str, Callable[[Any], str]]] | None = None, show_id: bool = False) Callable[[Type[Any]], Type[Any]][source]
Decorate class to be visible by
repr.- Parameters:
items (Optional[Iterable[Union[str, Tuple[str, Callable[[Any], str]]]]]) – Items to be displayed. Default is None, which means automatically find the private fields and display them. Items can be strings (field names) or
(name, repr_func)pairs.show_id (bool) – Show hex id in representation string or not. Defaults to False.
- Returns:
Decorator to decorate the given class.
- Return type:
Callable
Example:
>>> @visual() >>> class T: ... def __init__(self, x, y): ... self.__first = x ... self.__second = y >>> repr(T(1, 2)) '<T first: 1, second: 2>' >>> @visual(show_id=True) >>> class T2: ... def __init__(self, x): ... self.__x = x >>> repr(T2(42)) '<T2 0x... x: 42>'
Note
This decorator generates a
__repr__method that displays the specified fields or all private fields if none are specified.
constructor
- hbutils.model.clazz.constructor(params: Iterable[str | Tuple[str, Any]] | None = None, doc: str | None = None) Callable[[Type[Any]], Type[Any]][source]
Decorate class to create an init function.
- Parameters:
params (Optional[Iterable[Union[str, Tuple[str, Any]]]]) – Parameters of constructor. Each item should be a string (argument name) or a tuple of
(name, default_value). Default is None, which means no arguments (unless__items__is defined on the class).doc (Optional[str]) – Documentation of constructor function. Defaults to None.
- Returns:
Decorator to decorate the given class.
- Return type:
Callable
Example:
>>> @constructor(['x', ('y', 2)], ''' ... Overview: ... This is the constructor of class :class:`T`. ... ''') >>> class T: ... # the same as: ... # def __init__(self, x, y=2): ... # self.__x = x ... # self.__y = y ... ... @property ... def x(self): ... return self.__x ... ... @property ... def y(self): ... return self.__y >>> t = T(1) >>> t.x, t.y (1, 2)
Note
This decorator generates an
__init__method that stores argument values into private attributes using name mangling.
hasheq
- hbutils.model.clazz.hasheq(items: Iterable[str] | None = None) Callable[[Type[Any]], Type[Any]][source]
Decorate class to support hashing and equality comparison.
- Parameters:
items (Optional[Iterable[str]]) – Items to be hashed and compared. Default is None, which means automatically find the private fields and use them.
- Returns:
Decorator to decorate the given class.
- Return type:
Callable
Example:
>>> @hasheq(['x', 'y']) >>> class T: ... def __init__(self, x, y): ... self.__first = x ... self.__second = y >>> t1 = T(1, 2) >>> t2 = T(1, 2) >>> t1 == t2 True >>> hash(t1) == hash(t2) True Using with :func:`asitems`:: >>> @hasheq() >>> @constructor() >>> @asitems(['x', 'y']) >>> class T1: ... pass >>> t1 = T1(1, 2) >>> t2 = T1(1, 2) >>> t1 == t2 True
Note
This decorator generates
__hash__,__eq__, and__ne__methods for the class based on the specified fields.
accessor
- hbutils.model.clazz.accessor(items: Iterable[str | Tuple[str, str]] | None = None, readonly: bool = False) Callable[[Type[Any]], Type[Any]][source]
Decorate class to be accessible by property accessors.
- Parameters:
items (Optional[Iterable[Union[str, Tuple[str, str]]]]) – Items to be accessed. Default is None, which means automatically find the private fields and create accessors for them. Each item can be a string (field name) or a
(name, access_mode)tuple.readonly (bool) – Default readonly or not. Default is False, which means make the accessor writable when
rwoption is not given.
- Returns:
Decorator to decorate the given class.
- Return type:
Callable
Example:
>>> @accessor(readonly=True) >>> @asitems(['x', 'y']) >>> class T: ... def __init__(self, x, y): ... self.__x = x ... self.__y = y >>> t = T(2, 100) >>> t.x # 2 2 >>> t.y # 100 100 With writable access:: >>> @accessor(readonly=False) >>> @asitems(['x', 'y']) >>> class T2: ... def __init__(self, x, y): ... self.__x = x ... self.__y = y >>> t = T2(2, 100) >>> t.x = 42 >>> t.x 42 With mixed access control:: >>> @accessor([('x', 'ro'), ('y', 'rw')]) >>> class T3: ... def __init__(self, x, y): ... self.__x = x ... self.__y = y >>> t = T3(1, 2) >>> t.y = 42 # OK >>> # t.x = 10 # This would raise AttributeError
Note
This decorator automatically generates property accessors for the specified fields. Access modes:
'r'/'ro'/'readonly'for read-only,'w'/'rw'/'writable'for read-write.