jangada.mixin.Taggable#

class jangada.mixin.Taggable#

Bases: object

Mixin that adds a symbolic tag for namespace access.

Provides a validated tag attribute that must be a valid Python identifier (but not a keyword). Tags are intended for programmatic, attribute-style access in namespaces or registries, similar to how pandas DataFrames expose columns.

Unlike names, tags have strict validation rules to ensure they can be used as Python identifiers. They are mutable, allowing dynamic reorganization.

Attributes:
tagstr or None

A symbolic identifier string. Must be a valid Python identifier (alphanumeric and underscore, not starting with digit) and not a Python keyword. Can be None.

See also

Identifiable

Globally unique identifier

Nameable

Human-readable display name

Notes

Validation Rules
  • Must be a valid Python identifier: str.isidentifier()

  • Cannot be a Python keyword (if, for, class, etc.)

  • Leading/trailing whitespace is stripped before validation

  • Empty string (or whitespace-only) is invalid

Uniqueness

Tags are not globally unique. Uniqueness should be enforced at the container level (e.g., within a specific namespace or system).

Mutability

Tags are mutable to allow dynamic reorganization. Containers that index by tag must handle tag changes appropriately.

Use Cases
  • Component identification in hierarchical systems

  • Attribute-style namespace access

  • Symbolic references in configuration files

  • Human-readable identifiers in logs and debugging

Examples

Valid tags:

obj = Taggable()
obj.tag = "sensor_a"
obj.tag = "temp_sensor_01"
obj.tag = "_private"

Invalid tags (will raise ValueError):

obj.tag = "123invalid"      # Starts with digit
obj.tag = "invalid-tag"     # Contains hyphen
obj.tag = "invalid tag"     # Contains space
obj.tag = "if"              # Python keyword

Namespace-style access (intended use case):

class System:
    def __init__(self):
        self._components = {}

    def add(self, component):
        self._components[component.tag] = component

    def __getattr__(self, tag):
        return self._components.get(tag)

system = System()

sensor = Taggable()
sensor.tag = "temp_sensor"
system.add(sensor)

# Attribute-style access
assert system.temp_sensor is sensor

Mutability:

obj = Taggable()
obj.tag = "first_tag"
obj.tag = "second_tag"  # Can change
obj.tag = None          # Can reset
__init__(*args, **kwargs)#

Methods

__delattr__(name, /)

Implement delattr(self, name).

__dir__(/)

Default dir() implementation.

__eq__(value, /)

Return self==value.

__format__(format_spec, /)

Default object formatter.

__ge__(value, /)

Return self>=value.

__getattribute__(name, /)

Return getattr(self, name).

__getstate__(/)

Helper for pickle.

__gt__(value, /)

Return self>value.

__hash__(/)

Return hash(self).

__init__(*args, **kwargs)

__init_subclass__

This method is called when a class is subclassed.

__le__(value, /)

Return self<=value.

__lt__(value, /)

Return self<value.

__ne__(value, /)

Return self!=value.

__reduce__(/)

Helper for pickle.

__reduce_ex__(protocol, /)

Helper for pickle.

__repr__(/)

Return repr(self).

__sizeof__(/)

Size of object in memory, in bytes.

__str__(/)

Return str(self).

__subclasshook__

Abstract classes can override this to customize issubclass().

Attributes

__annotations__

tag

Symbolic identifier for namespace-style access.