util.attribute module

Inheritance diagram of RestrictionTypes, Restriction, Attribute, AttributedObject

  1. Objects are either TYPES or INDIVIDUALS

  1. A TYPE T is identified by T->ISTYPE->Type, an INDIVIDUAL I is identified by I->ISINSTANCE->Type

  2. A TYPE T can be marked as ABSTRACT, meaning A->ISINSTANCE->T is disallowd (eg: ISINSTANCE<:ISA:>ISTYPE)

  1. A<-ISTYPE<-X->ISINSTANCE->B is illegal

  2. ISA: TOP->ISA->TOP, ISTYPE: [TYPE<:TOP]->(ISTYPE<:ISA)->[TYPE], ISINSTANCE: [IND<:TOP]->(ISINSTANCE<:ISA)->[TYPE] seems hopelessly circular if 1.1

TYPE-ATTRIBUtES’ values can only be modified by TYPES (eg: fill-color) but the value is inherited by INDIVIDUALS

Individual-attributes are only non-TYPE-ATTRIBUTES because TYPES are also individuals (eg: name)

ROLE is an Attribute type that is covarient

non-ROLE Attribute types are invarient

Some VALUES are inherited (eg: color) and others are not (eg: name)

Created on Oct 10, 2024

Code author: Rob Kremer <robkremer@me.com>


class util.attribute.RestrictionTypes(*values)

Bases: Flag

Restrictions on how an attribute is inherited, by individuals or by subtypes (see Restriction):

  • NOINHERIT: the key is inherited, but the value isn’t (a slot that must be filled locally).

  • NOOVERRIDE: the inherited value can’t be overridden.

  • PRIVATE: the key isn’t inherited at all; the attribute is invisible. It subsumes the other bits.

UNRESTRICTED = 0
NOINHERIT = 1
NOOVERRIDE = 2
ILLEGAL = 3
PRIVATE = 4
static _generate_next_value_(name, start, count, last_values)

Generate the next value when not given.

name: the name of the member start: the initial start value or None count: the number of existing members last_values: the last value assigned or None

_boundary_ = 'strict'
_flag_mask_ = 7
_singles_mask_ = 7
_all_bits_ = 7
_inverted_ = None
util.attribute.restrictionTypesToString(r: RestrictionTypes | None) → str
Returns:

The flag’s name; a combination is “|”-separated (eg: “NOINHERIT|PRIVATE”), or “None” for None.

Parameters:

r (RestrictionTypes | None)

util.attribute.restrictionTypesFromString(s: str) → RestrictionTypes | None

The inverse of restrictionTypesToString().

Parameters:

s (str)

Returns:

Return type:

RestrictionTypes | None

class util.attribute.Restriction(individual: RestrictionTypes | None, type: RestrictionTypes | None)

Bases: object

How an attribute may be inherited: one RestrictionTypes for individuals that inherit it (individual) and one for subtypes (type); None means no restriction.

individual: RestrictionTypes | None

The restriction on individuals inheriting the attribute.

type: RestrictionTypes | None

The restriction on subtypes inheriting the attribute.

hides(isIndividual: bool) → bool
Returns:

True iff an inheriting individual (or type, if isIndividual is False) can’t see the attribute at all.

Parameters:

isIndividual (bool)

legalityError() → str | None
Returns:

Why this restriction is illegal, or None if it’s legal.

classmethod fromstring(name: str) → Restriction
Parameters:

name (str)

Returns:

Return type:

Restriction

tostring() → str
Returns:

Return type:

str

__init__(individual: RestrictionTypes | None, type: RestrictionTypes | None) → None
util.attribute.VAR_DEFAULTED = Restriction(individual=<RestrictionTypes.UNRESTRICTED: 0>, type=<RestrictionTypes.UNRESTRICTED: 0>)

Restriction: Normal variable with a default. Eg: “degree” field with default “None”.

util.attribute.VAR = Restriction(individual=<RestrictionTypes.NOINHERIT: 1>, type=<RestrictionTypes.UNRESTRICTED: 0>)

Restriction: Normal variable, individuals must assign as value. Eg: name of an object.

util.attribute.CONST_TYPEOVERRIDE = Restriction(individual=<RestrictionTypes.NOOVERRIDE: 2>, type=<RestrictionTypes.UNRESTRICTED: 0>)

Restriction: Constant that types can change.

util.attribute.LOCAL = Restriction(individual=<RestrictionTypes.PRIVATE: 4>, type=<RestrictionTypes.PRIVATE: 4>)

Restriction: Visible only on the object that defines it. Eg: a relation’s “symmetric” tag.

util.attribute.TYPEONLY = Restriction(individual=<RestrictionTypes.PRIVATE: 4>, type=<RestrictionTypes.UNRESTRICTED: 0>)

Restriction: Subtypes inherit it, individuals can’t see it.

util.attribute.UNINHERITED = Restriction(individual=<RestrictionTypes.NOINHERIT: 1>, type=<RestrictionTypes.NOINHERIT: 1>)

Restriction: Everything below sees the key, but must supply its own value.

util.attribute.TYPENAME = Restriction(individual=<RestrictionTypes.NOOVERRIDE: 2>, type=<RestrictionTypes.NOINHERIT: 1>)

Restriction: Types must change but individuals can’t. Eg: name of a relation.

util.attribute.CONST = Restriction(individual=<RestrictionTypes.NOOVERRIDE: 2>, type=<RestrictionTypes.NOOVERRIDE: 2>)

Restriction: Constant

class util.attribute.NoValue

Bases: Serializable

A singleton null class (similar) to None that can be used in situations where you’d want None, but None is a legitimate value. Any call to the constructor returns the one NOVALUE object.

NOVALUE = NOVALUE
classmethod getInstantiationInfo() → InstantiationInfo
Returns:

A InstantiationInfo structure describing the constructor parameters and how to fill them (conArgs, conKWArgs), and a further description of any additional data to be filled after immediately after the constructor (postconSetters) and more after any contained objects have been fully constructed (finalSetters), both how to write them and read them.

Return type:

util.persistence.serialize.InstantiationInfo

util.attribute.isValidType(typ, value=None) → bool
Parameters:
  • typ – a type spec with may be subtype to Type or a string describing a app-specific type.

  • value – A value that is expected to be a legitimate instance the typ

Returns:

True iff the type typ argument is a valid type specification and value is None or a valid instance of typ.

A valid type is:

  • “choices[” <listOfStrings> “]”

  • a member of KNOWN_STRING_TYPES (“str”, “text”, “mtext”, “color”, “colour”)

  • a member of KNOWN_TYPES (“int”, “float”, “bool”, “str”, “text”, “mtext”, “color”, “colour”, “choices”, “list”, “dict”, “attrs”)

  • a subclass of Serializable or it’s fully-qualified string representation.

util.attribute.FALSE_STRINGS = ('false', 'no', 'off', 'f', 'n', '0', '')

What coerceValue() takes as a bool, as text (in any case).

util.attribute.coerceValue(typ: type | str | None, value: Any) → Any

value, made the type typ says, if it isn’t already and it can be without losing anything: eg: 30 or “30” for a float is 30.0; 3.0 or “3” for an int is 3 (but 3.5 isn’t an int); “yes” or 1 for a bool is True; anything for a string type (“str”, “color”, …) is its text; “ a “ for “choices[a, b]” is “a”. For use where values come from somewhere that doesn’t know the types (eg: typed text, or a reasoner’s conclusions).

Parameters:
  • typ (AttributeValueTypes | None) – A type, as for isValidType(): None for “anything”.

  • value (Any) – The value.

Returns:

The value, as typ.

Return type:

Any

Raises:

ValueError – If it can’t be made typ (eg: “abc” for an int, or a choice that isn’t one).

util.attribute.typeAsString(t: type | str, throw: bool = False) → type | str | None

Returns a either the string version of supported types or the the fully qualified class name of of any other types. If the non-supported type is in string form, it is converted to a type and back again to check it’s validity, thus it could change from a mere type name to a fully qualified class name.

Parameters:
  • t (AttributeValueTypes)

  • throw (bool)

Returns:

Return type:

AttributeValueTypes | None

util.attribute.typeAsCanonical(t: type | str, throw: bool = False) → type | str | None

Attempts to return the given type t as an actual class. Note that a string may also be returned in the case of the few supported “types” that do not correspond to actual classes, currently “mtext”, “color”, “colour”, “choices”.

Parameters:
  • t (AttributeValueTypes)

  • throw (bool)

Returns:

Return type:

AttributeValueTypes | None

class util.attribute.Attribute(value: Serializable | int | float | bool | str | list | dict | strdict | tuple | set | None | NoValue, typ: type | str | None, restriction: Restriction | tuple[int, int] | tuple[RestrictionTypes, RestrictionTypes] | None, note: str | None = None, inferred: bool = False)

Bases: Serializable, Dirtyable

An attribute’s value, with its type (a type, or a type name such as “color” or “choices[…]”), its restriction on how it’s inherited (see Restriction), and a note describing it (shown as a tooltip by the attribute editor).

__init__(value: Serializable | int | float | bool | str | list | dict | strdict | tuple | set | None | NoValue, typ: type | str | None, restriction: Restriction | tuple[int, int] | tuple[RestrictionTypes, RestrictionTypes] | None, note: str | None = None, inferred: bool = False)
Parameters:
_value: Serializable | int | float | bool | str | list | dict | strdict | tuple | set | None | NoValue
_type: type | str | None
_restriction: Restriction | None
userNote: bool

Whether the note was written by the user (eg: in the attribute editor), not by the program: such a note is saved (see getInstantiationInfo()), and AttributedObject.get() doesn’t replace it with the program’s own.

inferred: bool

Whether the value was concluded (eg: by a reasoner), not given: such an attribute isn’t saved with its object (see AttributedObject.getInstantiationInfo()), and the attribute editor shows it greyed out, with an “assert” button that makes it an ordinary (given) one.

property value: Serializable | int | float | bool | str | list | dict | strdict | tuple | set | None | NoValue
Returns:

Return type:

SerializableType | NoValue

property type: type | str | None
Returns:

Return type:

AttributeValueTypes | None

property restriction: Restriction | None
Returns:

Return type:

Restriction | None

isComplete() → bool
classmethod getInstantiationInfo() → InstantiationInfo
Returns:

A InstantiationInfo structure describing the constructor parameters and how to fill them (conArgs, conKWArgs), and a further description of any additional data to be filled after immediately after the constructor (postconSetters) and more after any contained objects have been fully constructed (finalSetters), both how to write them and read them.

Return type:

util.persistence.serialize.InstantiationInfo

__str__() → str
Returns:

Return type:

str

class util.attribute.AttributedObject

Bases: Serializable, Dirtyable, strdict, Subject

An object with named Attribute objects, which inherits more from its supertypes (getSupers(), which subclasses must define), as their Restriction objects allow. get() finds a key’s effective value – the object’s own, or else the one it inherits; getLocal() and getInh() find only one or the other.

classmethod getInstantiationInfo() → InstantiationInfo
Returns:

A InstantiationInfo structure describing the constructor parameters and how to fill them (conArgs, conKWArgs), and a further description of any additional data to be filled after immediately after the constructor (postconSetters) and more after any contained objects have been fully constructed (finalSetters), both how to write them and read them.

Return type:

util.persistence.serialize.InstantiationInfo

__init__()
setDirty(dirty: bool = True) → None

An object is dirty if it has been modified and should probably be saved on exit. This should be called from all methods that modify the state of this object.

If dirty is False, resets all the contained Attributes to False.

Parameters:

dirty (bool) – (default True) The dirty to set dirty to.

isDirty() → bool

Returns True iff the object (or an of it’s contained Attributes) have been modified and should probably be saved on exit.

Returns:

Return type:

bool

get(key: str, default: Any = NOVALUE, storeDefault: Any = NOVALUE, storeType: type | str | None = None, note: str | None = None) → Serializable | int | float | bool | str | list | dict | strdict | tuple | set | None | NoValue

Return the value of the attribute at the key. If it isn’t found locally, search the inheritance lattice.

Parameters:
  • key (str) – The index string to retrieve.

  • default (Any) – The value to return if index doesn’t exist in the dictionary. Ignored if storeDefault is not None.

  • storeDefault (Any) – Same as default, but the value is ALSO stored in the dictionary if the value is not None. Useful for applications like preferences. If storeDefault is present, default is ignored.

  • storeType (AttributeValueTypes|None=None) – Any legal Attribute value type. Saved as the type of storeDefault. Ignored if if key is found or storeDefault is None.

  • note (str | None)

Returns:

  • if the key is found, the value (NOT the Attribute record) associated with the key, or

  • if storeDefault is specified, the value of storeDefault, or

  • if default is specified, the value of default, or

  • None.

getLocal(key: str, default: Any = NOVALUE) → Serializable | int | float | bool | str | list | dict | strdict | tuple | set | None | Any

Return the LOCAL (not inherited) value of the attribute at the key.

Parameters:
  • key (str) – The key to access.

  • default (Any) – The value to return if key is not found. Default is NoValue.

Returns:

The value field of the Attribute object at key if found.

Return type:

SerializeableType|NoValue

getLocalAttr(key: str) → Attribute | None

Return the LOCAL (not inherited) Attribute of the attribute at the key.

Parameters:
  • key (str) – The key to access.

  • default (Any) – The value to return if key is not found. Default is NoValue.

Returns:

The value field of the Attribute object at key if found.

Return type:

Attribute

getInh(key: str, default: Any = NOVALUE) → Serializable | int | float | bool | str | list | dict | strdict | tuple | set | None | Any

Return the INHERITED (not local) value of the attribute at the key.

Parameters:
  • key (str) – The key to access.

  • default (Any) – The value to return if key is not found. Default is NoValue.

Returns:

The value field of the Attribute object at key if found.

Return type:

SerializeableType|NoValue

getInhAttr(key: str) → Attribute | None

Return the INHERITED (not local) Attribute of the attribute at the key.

Parameters:
  • key (str) – The key to access.

  • default (Any) – The value to return if key is not found. Default is NoValue.

Returns:

The value field of the Attribute object at key if found.

Return type:

Attribute

getAttr(key: str) → Attribute | None

Return the Attribute object at the key. If it isn’t found locally, search the inheritance lattice.

Parameters:

key (str) – The key to access.

Returns:

The Attribute object at key or None if it isn’t found.

Return type:

Attribute|None

__getitem__(key: str) → Serializable | int | float | bool | str | list | dict | strdict | tuple | set | None

The override for the indici access method.

Parameters:

key (str) – The attribute name.

Returns:

The value associated with key, which could be NOVALUE if the the key exists, but here is not value associated with it (ie: the value was not inherited via the NOINHERIT restriction.

Return type:

SerializableType

Raises:

KeyError – if the key doesn’t exist.

Calls self.getAttr() and returns the value it finds (if any) – or, if this object has a value of its own, that, at once: getAttr() would give that value too (whatever it inherits, and whatever its restriction), but first looks up what it inherits (eg: for the note), which is slow for something with many ancestors, asked often (eg: a name, for a label).

__setitem__(key: str, value: Serializable | int | float | bool | str | list | dict | strdict | tuple | set | None) → None
Parameters:
  • key (str) – The attribute name.

  • value (SerializableType) – The value to record under key.

Raises:

Can do one of 3 things:

  • if there is already a local attribute, its value is updated

  • if there is no local attribute but there is a super attribute, create a value-only attribute and associate that with key.

  • if there is no local attribute and no super attribute, create a complete (default) local attribute.

The value is first made the attribute’s type, if it can be (see coerceValue()). In all cases, this method will throw if the value does not pass validation checks.

keys() → KeysView
Returns:

A live, set-algebra-capable KeysView over this object’s LOCAL and INHERITED attribute keys.

Return type:

KeysView

Unlike plain dict.keys() (which reads the underlying storage directly and so would silently ignore inheritance), this is backed by __iter__()/__contains__()/__len__(), so it stays consistent with iter(self), key in self and len(self). As with a real dict.keys(), the view is live: it reflects later changes to this object (or its supers) rather than being a frozen snapshot, and supports set operations (&, |, -, ^) against other key sets/views.

values() → ValuesView
Returns:

A live ValuesView over this object’s LOCAL and INHERITED attribute values – each one fully resolved through the inheritance lattice (i.e. via __getitem__()/getAttr(), not the raw stored Attribute record).

Return type:

ValuesView

items() → ItemsView
Returns:

A live ItemsView of (key, value) pairs, value fully resolved through inheritance (as with values()).

Return type:

ItemsView

setAttr(key: str, attr: Attribute) → Attribute
Parameters:
  • key (str) – The attribute name.

  • attr (Attribute) – The candate attribute to associate with key.

Returns:

The parameter attr

Return type:

Attribute

Raises:

Set a local attribute if it passes validation rules. Throws if the rules are violated. A value-only attr (one that inherits its type) has its value made that type first, if it can be (see coerceValue()).

abstractmethod getSupers() → list[T]
Returns:

A list of all super types to this object in mro order.

Return type:

list[AttributedObject]

Concrete subclasses must override to return a list of super types to this object.

abstractmethod isIndividual() → bool
Returns:

True iff this object is an individual.

Return type:

bool

Concrete subclasses must override to return True if this object is a individual or False if this obejct is a type.

isType() → bool
Returns:

True iff this object is a type.

Return type:

bool

isValueEditable(key: str) → bool
Parameters:

key (str) – The key for which to check.

Returns:

True iff the value for that key is editable.

Return type:

bool

isTypeEditable(key: str) → bool
Parameters:

key (str) – The key for which to check.

Returns:

True iff the type for that key is editable.

Return type:

bool

isQualifierEditable(key: str) → bool
Parameters:

key (str) – The key for which to check.

Returns:

True iff the restrictions for that key is editable.

Return type:

bool

classmethod _validateOverride(key: str, isIndividual: bool, attr: Attribute, superAttr: Attribute | None)
Parameters:
  • key (str) – The attribute name.

  • attr (Attribute) – The candate attribute to validate against the inherited attribute.

Raises:
  • ValueError – If the value is of the wrong type.

  • TypeError – If the type field is incorrect.

  • PermissionError – If the inheritance restrictions are incorrect.

Validates the attr against the inherited attribute. If attr is not legal against the inherited attribute, an exception will be raised.

Parameters:
  • isIndividual (bool)

  • superAttr (Optional[Attribute])

classmethod _getRestriction(isIndividual: bool, superRestriction: Restriction | None, thisRestriction: Restriction | None) → tuple[RestrictionTypes, bool]

Resolve the actual restriction on the object with respect to it being an individual/type and its inheritance.

Parameters:
Returns:

A typle pair of the RestrictionTypes and a bool indicating whether of not it is an override (True) or original (False).

Return type:

tuple[RestrictionTypes, bool]

_getSuperAttr(key: str) → Attribute | None
Parameters:
  • key (str) – The attribute name.

  • default (None) – (default: None) The value returned if they items isn’t found.

Returns:

The Attribute object from the first parent it’s found in

Return type:

Optional[Attribute]