types

Added in version 3.2.0.

This module contains the internal type definitions and utility functions for working with them.

Functions

coerce_value(value: Any, verify_type: bool = True) Any[source]

Take a native Python value and convert it to a value of a data type which can be represented by a Rule Engine DataType. This function is useful for converting native Python values at the engine boundaries such as when resolving a symbol from an object external to the engine.

Added in version 2.0.0.

Parameters:
  • value – The value to convert.

  • verify_type (bool) – Whether or not to verify the converted value’s type.

Returns:

The converted value.

is_integer_number(value: Any) bool[source]

Check whether value is an integer number (i.e. a whole, number). This can, for example, be used to check if a floating point number such as 3.0 can safely be converted to an integer without loss of information.

Added in version 2.1.0.

Parameters:

value – The value to check. This value is a native Python type.

Returns:

Whether or not the value is an integer number.

Return type:

bool

is_natural_number(value: Any) bool[source]

Check whether value is a natural number (i.e. a whole, non-negative number). This can, for example, be used to check if a floating point number such as 3.0 can safely be converted to an integer without loss of information.

Parameters:

value – The value to check. This value is a native Python type.

Returns:

Whether or not the value is a natural number.

Return type:

bool

is_numeric(value: Any) bool[source]

Check whether value is a numeric value (i.e. capable of being represented as a floating point value without loss of information).

Parameters:

value – The value to check. This value is a native Python type.

Returns:

Whether or not the value is numeric.

Return type:

bool

is_real_number(value: Any) bool[source]

Check whether value is a real number (i.e. capable of being represented as a floating point value without loss of information as well as being finite). Despite being able to be represented as a float, NaN is not considered a real number for the purposes of this function.

Parameters:

value – The value to check. This value is a native Python type.

Returns:

Whether or not the value is a natural number.

Return type:

bool

iterable_member_value_type(python_value: Any) _DataTypeDef[source]

Take a native python_value and return the corresponding data type of each of its members if the types are either the same or NULL. NULL is considered a special case to allow nullable-values. This by extension means that an iterable may not be defined as only capable of containing NULL values.

Returns:

The data type of the sequence members. This will never be NULL, because that is considered a special case. It will either be UNSPECIFIED or one of the other types.

Classes

class DataType[source]

Bases: object

A collection of constants representing the different supported data types. There are three ways to compare data types. All three are effectively the same when dealing with scalars.

Equality checking
dt == DataType.TYPE

This is the most explicit form of testing and when dealing with compound data types, it recursively checks that all of the member types are also equal.

Type checking
DataType.is_type(dt, DataType.TYPE)

This checks that the data type belongs to the same family as the given sentinel. For scalar types this is equivalent to an equality check; for compound types (e.g. ARRAY, MAPPING) it matches any parameterization of that type without inspecting member types. When used in an if branch mypy narrows the type of dt to the matching concrete class (e.g. after DataType.is_type(dt, DataType.NULLABLE) mypy knows dt is a _NullableDataTypeDef).

Compatibility checking
DataType.is_compatible(dt, DataType.TYPE)

This checks that the types are compatible without any kind of conversion. When dealing with compound data types, this ensures that the member types are either the same or UNDEFINED.

ARRAY(value_type_nullable: bool | None = None) _CollectionDataTypeDef
Parameters:
  • value_type – The type of the members.

  • value_type_nullable (bool) –

    Whether or not members are allowed to be NULL.

    Deprecated since version 5.0.0: Wrap nullable element types with DataType.NULLABLE() instead; this kwarg will be removed in v6.0.0.

BOOLEAN = <_DataTypeDef name=BOOLEAN python_type=bool >
BYTES = <_DataTypeDef name=BYTES python_type=bytes >
DATETIME = <_DataTypeDef name=DATETIME python_type=datetime >
FLOAT = <_DataTypeDef name=FLOAT python_type=Decimal >
FUNCTION(return_type: _DataTypeDef = UNDEFINED, argument_types: tuple[_DataTypeDef, ...] | _DataTypeDef = UNDEFINED, minimum_arguments: int | _DataTypeDef | None = None) _FunctionDataTypeDef

Added in version 4.0.0.

Parameters:
  • name (str) – The name of the function, e.g. “split”.

  • return_type – The data type of the functions return value.

  • argument_types (tuple) – The data types of the functions arguments.

  • minimum_arguments (int) – The minimum number of arguments the function requires.

If argument_types is specified and minimum_arguments is not, then minimum_arguments will default to the length of argument_types effectively meaning that every defined argument is required. If

MAPPING(value_type: _DataTypeDef = UNDEFINED, value_type_nullable: bool | None = None) _MappingDataTypeDef
Parameters:
  • key_type – The type of the mapping keys.

  • value_type – The type of the mapping values.

  • value_type_nullable (bool) –

    Whether or not mapping values are allowed to be NULL.

    Deprecated since version 5.0.0: Wrap nullable value types with DataType.NULLABLE() instead; this kwarg will be removed in v6.0.0.

NULL = <_DataTypeDef name=NULL python_type=NoneType >
NULLABLE() _NullableDataTypeDef
Parameters:

inner_type – The non-null data type this slot may hold. Passing an already-nullable type collapses (i.e. NULLABLE(NULLABLE(T)) is NULLABLE(T)); passing NULL or UNDEFINED raises EngineError.

Added in version 5.0.0.

OBJECT(attributes: Mapping[str, _DataTypeDef] | None = None, accessor: Callable[[Any, str], Any] | None = None) _ObjectDataTypeDef

Added in version 5.0.0.

Parameters:
  • name (str) – The name of the object schema.

  • attributes (dict) – A mapping of attribute names to their data type definitions. A reference() placeholder with the same name (or the self sentinel) resolves to the new type itself, enabling self-referential schemas.

  • accessor – A callable of the form accessor(value, attribute_name) used to fetch an attribute’s value at evaluation time. Defaults to getattr().

static OBJECT.from_dataclass(name, cls, *, accessor=None)

Build an OBJECT schema from a Python dataclass(). Each field of cls becomes an attribute in the resulting OBJECT schema, with its type derived from the field annotation via DataType.from_type(). Stringified annotations (e.g. from from __future__ import annotations) are resolved using typing.get_type_hints().

Fields annotated with typing.Optional (or the PEP 604 T | None form) are surfaced as NULLABLE wrappers around the non-None type; non-Optional fields are recorded unwrapped. See the NULLABLE section for how nullability propagates through the grammar and how to discharge it.

Fields whose annotation is itself a dataclass (or contains one inside a list/set/dict generic) produce nested OBJECT schemas. Self-references resolve to the enclosing schema via the self sentinel; references to a dataclass already on the build stack (mutual recursion) become unresolved reference() placeholders that the caller must resolve via the Context type_resolver.

Added in version 5.0.0.

Parameters:
  • name (str) – The name of the resulting OBJECT schema.

  • cls (type) – A class decorated with dataclass().

  • accessor – An optional accessor callable forwarded to the new schema. Defaults to getattr(), which matches normal dataclass attribute access.

  • strict (bool) – When True (the default), a field annotated with a type that cannot be mapped to a Rule Engine data type raises ValueError. When False, such fields fall back to DataType.UNDEFINED so the attribute remains selectable without parse-time type checking.

static OBJECT.from_sqlalchemy(name, cls, *, accessor=None)

Build an OBJECT schema from a SQLAlchemy ORM mapped class. Each mapped column of cls becomes an attribute in the resulting OBJECT schema, with its type derived from the column’s python_type() via DataType.from_type(). Columns with nullable set to True are surfaced as NULLABLE wrappers around the column type; scalar relationships whose local foreign-key columns are nullable are wrapped the same way.

By default (strict=True) a column whose python_type raises NotImplementedError (typically dialect-specific types such as PostgreSQL CIDR or INET) or resolves to a Python type Rule Engine cannot map raises ValueError; pass strict=False to record such columns as DataType.UNDEFINED so they remain selectable without parse-time type checking. Enum columns are surfaced as DataType.STRING unless the enum class is an int subclass, in which case they become DataType.FLOAT. JSON columns report dict as their python_type and therefore map to DataType.MAPPING with untyped keys and values; the nested values remain untyped.

Relationships declared on cls are expanded into nested OBJECT schemas. Collection relationships (uselist=True) are wrapped in DataType.ARRAY. Back-references to the enclosing class resolve to self; references to a class already on the build stack (mutual recursion across more than two classes) become unresolved reference() placeholders that the caller must resolve via the Context type_resolver.

SQLAlchemy is an optional dependency. The library imports cleanly without it; import sqlalchemy is deferred until this method is actually called and propagates ImportError if SQLAlchemy is not installed.

Added in version 5.0.0.

Parameters:
  • name (str) – The name of the resulting OBJECT schema.

  • cls (type) – A SQLAlchemy ORM mapped class.

  • accessor – An optional accessor callable forwarded to the new schema. Defaults to getattr(), which matches normal attribute access on a mapped instance.

  • strict (bool) – When True (the default), a column whose python_type raises NotImplementedError or cannot be mapped to a Rule Engine data type raises ValueError. When False, such columns fall back to DataType.UNDEFINED so the attribute remains selectable without parse-time type checking. This is useful for dialect- specific column types whose values can not be statically described.

static OBJECT.reference(name)

Construct a forward-reference placeholder for use inside an OBJECT schema. This is not itself a data type — it is a placeholder that resolves to an OBJECT either at construction time (for self references within the same schema) or at rule parse time (for cross-type references) via a Context’s type_resolver.

For self-references within a schema, prefer the self sentinel, which avoids repeating the enclosing schema’s name.

Added in version 5.0.0.

Parameters:

name (str) – The name of the referenced OBJECT schema.

OBJECT.self

Sentinel value for use inside an OBJECT attribute schema to denote “the enclosing OBJECT schema”, resolved automatically when the schema is constructed. Prefer this over reference() for self-references, since it avoids repeating the schema’s own name.

Added in version 5.0.0.

SET(value_type_nullable: bool | None = None) _CollectionDataTypeDef
Parameters:
  • value_type – The type of the members.

  • value_type_nullable (bool) –

    Whether or not members are allowed to be NULL.

    Deprecated since version 5.0.0: Wrap nullable element types with DataType.NULLABLE() instead; this kwarg will be removed in v6.0.0.

STRING = <_DataTypeDef name=STRING python_type=str >
TIMEDELTA = <_DataTypeDef name=TIMEDELTA python_type=timedelta >
UNDEFINED = UNDEFINED

Undefined values. This constant can be used to indicate that a particular symbol is valid, but it’s data type is currently unknown.

classmethod from_name(name: str) _DataTypeDef[source]

Get the data type from its name.

Added in version 2.0.0.

Parameters:

name (str) – The name of the data type to retrieve.

Returns:

One of the constants.

classmethod from_type(python_type: Any) _DataTypeDef[source]

Get the supported data type constant for the specified Python type/type hint. If the type or typehint can not be mapped to a supported data type, then a ValueError exception will be raised. This function will not return UNDEFINED.

Parameters:

python_type (type) – The native Python type or type hint to retrieve the corresponding type constant for.

Returns:

One of the constants.

Changed in version 4.1.0: Added support for typehints.

classmethod from_value(python_value: Any) _DataTypeDef[source]

Get the supported data type constant for the specified Python value. If the value can not be mapped to a supported data type, then a TypeError exception will be raised. This function will not return UNDEFINED.

Parameters:

python_value – The native Python value to retrieve the corresponding data type constant for.

Returns:

One of the constants.

classmethod is_compatible(dt1: _DataTypeDef, dt2: _DataTypeDef) bool[source]

Check if two data type definitions are compatible without any kind of conversion. This evaluates to True when one or both are UNDEFINED or both types are the same. In the case of compound data types (such as ARRAY) the member types are checked recursively in the same manner.

Added in version 2.1.0.

Parameters:
  • dt1 – The first data type to compare.

  • dt2 – The second data type to compare.

Returns:

Whether or not the two types are compatible.

Return type:

bool

classmethod is_definition(value: Any) bool[source]

Check if value is a data type definition.

Added in version 2.1.0.

Parameters:

value – The value to check.

Returns:

True if value is a data type definition.

Return type:

bool

classmethod is_type(dt: _DataTypeDef, kind: _ArrayDataTypeDef) TypeGuard[_ArrayDataTypeDef][source]
classmethod is_type(dt: _DataTypeDef, kind: _FunctionDataTypeDef) TypeGuard[_FunctionDataTypeDef]
classmethod is_type(dt: _DataTypeDef, kind: _MappingDataTypeDef) TypeGuard[_MappingDataTypeDef]
classmethod is_type(dt: _DataTypeDef, kind: _NullableDataTypeDef) TypeGuard[_NullableDataTypeDef]
classmethod is_type(dt: _DataTypeDef, kind: _ObjectDataTypeDef) TypeGuard[_ObjectDataTypeDef]
classmethod is_type(dt: _DataTypeDef, kind: _SetDataTypeDef) TypeGuard[_SetDataTypeDef]
classmethod is_type(dt: _DataTypeDef, kind: _DataTypeDef) bool

Check if dt is the same base type as kind, ignoring member types for compound types. This is the preferred replacement for isinstance(dt, DataType.TYPE.__class__).

For scalar types (e.g. STRING, BOOLEAN) kind is a singleton so this is equivalent to an equality check. For compound types (e.g. ARRAY, MAPPING, OBJECT) it checks the type family without inspecting member / key / value types — use is_compatible() when those matter.

Added in version 5.0.0.

Parameters:
  • dt – The data type to test.

  • kind – The base type to test against (e.g. DataType.ARRAY).

Returns:

True if dt belongs to the same type family as kind.

Return type:

bool