# Typesystem¶

This page describes the data types introduced in pSeven and type conversion rules.

Sections

## Introduction¶

pSeven typesystem distinguishes between Boolean, integer, real (floating point) and string values.
These values can be scalar, vector, or matrix. As a result of taking all possible combinations, there are 12 base types: *BoolScalar*, *IntScalar*, *RealScalar*, *StringScalar* and so on for vectors and matrices (for example, *RealVector*, *StringMatrix*).

Special types are *File* (file object), *Blob* (arbitrary binary data), *List*, and *Dict* (pSeven implementation of heterogeneous list and associative array types).
*List* and *Dict* are heterogeneous containers — they allow mixing elements of different types and can hold elements of any base or special type.

Lastly, there is the *Undefined* type (which actually is a special value, like `None` in Python). *Undefined* cannot be an element of a *List* or a *Dict*.

In total, there are 17 typenames (12 base, 4 special, and *Undefined*). Detailed information on individual types (including their standard string representations used here) can be found in the *pSeven Data Types* reference. This page describes pSeven typesystem concepts and type conversion rules in general.

## Base Types¶

Base pSeven data types can represent:

- A single Boolean value (
*BoolScalar*). - A single numeric value, integer or floating point (
*IntScalar*,*RealScalar*). - A text string (
*StringScalar*). - Ordered sets of Boolean values (
*BoolVector*,*BoolMatrix*), integers (*IntVector*,*IntMatrix*), strings (*StringVector*,*StringMatrix*). - Vector coordinates (
*RealVector*). - Rectangular matrices (
*RealMatrix*).

Boolean values are either `True` or `False`, other representations are not supported.

Integer values are 32-bit signed integers, floating point numbers are double precision floats, represented by numeric literals.

String literals are always enclosed in double quotes.

Vectors and matrices are homogeneous: all elements are of the same type.
All indices are zero-based.
Matrices are indexed in row major order. String form also follows this order: for example, in the `((11, 12), (21, 22))` matrix, `(11, 12)` and `(21, 22)` are matrix rows.

## Special Types¶

Special data types can be used to represent:

- A mixed data collection (
*List*). - A set of named values of different types (
*Dict*). - An existing file, or a file that has to be created in a specified place, or a temporary file (
*File*). - Arbitrary byte sequence, binary data (
*Blob*).

*List* is an heterogeneous ordered sequence: elements may have different types and are addressed by index.
An element may have any base or special type (only *Undefined* is not allowed).
Indices are zero-based.

*Dict* is an heterogeneous associative (unordered) array containing key-value pairs.
Values may have different types and are addressed by keys.
A value may have any base or special type (only *Undefined* is not allowed).
Keys may be strings only.

*File* is an advanced type for file handling (a file-like object). It is used to pass control over files between blocks. For details on *File* properties, see the *File* block page.

*Blob* is a binary array. This type is introduced to support Python bytearray type.

## Conversion Rules¶

Two cases have to be considered to understand data type conversion in pSeven. The first is when data is converted between pSeven types — for example, it travels through a link connecting two block ports with different types. The second is conversion between a pSeven type and a native Python type. It occurs, for example, in blocks that support Python scripting. When a value received to port is assigned to a script variable, it is converted from a pSeven type to a Python type. When the block reads a value of a script variable in order to output it to a port, this value is converted from a Python type to a pSeven type.

### pSeven Types Conversion¶

pSeven allows conversion of base data types to each other, if it does not lead to data loss:

- Scalars can be converted to vectors and matrices (naturally, the result contains a single element).
- Vectors can be converted to single-row matrices. Also, a vector can be converted to a scalar, but only if the vector contains a single element.
- Matrices can be converted to vectors if they contain a single row or a single column, and to scalars if they contain a single element.
- “Inner” type conversion is possible according to the following order: Boolean, integer, real, string.

For example, a single-element *IntMatrix* can be converted to a *RealScalar* (`((42))` to `42.0`), but not to a *BoolMatrix* because the value of 42 will be lost. A single-column *RealMatrix* can be converted to a *StringVector* (`((1.0), (2.0), (3.0))` to `("1.0", "2.0", "3.0")`) or *RealVector*, but not to a *StringScalar* because it cannot describe the structure.

Warning

Converting floating point numbers to strings reduces precision.

In some situations there are two or more possible conversions.
For example, a link may connect an output port of *IntVector* type with an input port that accepts both *IntMatrix* and *RealVector*.
In such cases the preferred conversion is selected in the following order: *BoolScalar*, *BoolVector*, *BoolMatrix*, *IntScalar*, *IntVector*, *IntMatrix*, *RealScalar*, *RealVector*, *RealMatrix*, *StringScalar*, *StringVector*, *StringMatrix*. So the integer vector in the example above is converted to an integer matrix with a single row.

All base data types can also be converted to *List*. A scalar becomes a *List* with a single element, a vector becomes a *List* of scalars, and a matrix is split by rows and becomes a list of vectors.

A homogeneous flat *List* (a list containing only scalar values of the same type) can be converted to a vector — for example, `[1.0, 2.0, 3.0]` to *RealVector* `(1.0, 2.0, 3.0)`. Such lists can also be directly converted to single-row matrices.

Similarly, a *List* that contains only vectors of the same dimension (or *List* values that can be converted to such vectors) can be converted to a matrix. That is, if the *List* can be interpreted as a rectangular matrix, it can be converted to a matrix. For example, a *List* of integer vectors `[(1, 2), (3, 4)]` can be converted to *IntMatrix* `((1, 2), (3, 4))`, as can be a *List* of equally sized lists of integers `[[1, 2], [3, 4]]`.

*Dict*, *File*, and *Blob* can not be converted to or from any other type except their trivial conversion to *List*, which results in a *List* containing a single element.

pSeven type descriptions in the *pSeven Data Types* reference include allowed conversions between pSeven data types.

### Python to pSeven Types Conversion¶

pSeven supports bool, int and float Python types, `None` values, str, unicode, list, tuple and bytearray sequences, dict and numpy.ndarray.

When converting from Python to pSeven types, Boolean, numeric, and string values by default are converted to appropriate scalars: bool to *BoolScalar*, int to *IntScalar* (long is not supported), float to *RealScalar*, str and unicode to *StringScalar*. It is also possible to force converting them to a *vector* or *matrix* type.

Flat list or tuple is by default converted to an appropriate *vector* type, provided that:

- all elements are of the same type, and
- this type is bool, int, float, str, or unicode.

A list or tuple like this can also be forcibly converted to a single-row matrix.

Nested list or tuple is by default converted to a nested List, and can be forcibly converted to a matrix, provided that:

- the top level contains only lists and/or tuples,
- nesting level is 1,
- all nested lists (tuples) are of the same length,
- all elements of the nested lists (tuples) are of the same type, and
- this type is bool, int, float, str, or unicode.

Other tuples and lists (containing different types, or with various nesting levels) can be converted to *List* only. Contained types must be supported by pSeven (for example, a *List* of complex numbers is not possible).

When there are two or more possible conversions from a Python to a pSeven type, the rule is the same as for pSeven types (see section *pSeven Types Conversion*).
For example, if an int value has to be output to a port that allows *IntVector* and *RealScalar*, it is converted to *IntVector* with a single element because or the preferred conversion order (from *BoolScalar* to *StringMatrix*, see above). Note that the result of conversion is not *RealScalar* despite logically the original value is scalar.
In case a list or tuple is output to a port with multiple types, pSeven again tries preferred conversions or, if they all fail, tries converting to *List*. A few examples of list conversion are:

`[True, False, True]`to*BoolVector*`(true, false, true)`.`[[1, 2, 3], [3, 2, 1]]`to*IntMatrix*`((1, 2, 3), (3, 2, 1))`.`['string']`to*StringVector*`("string")`.`[1, [21, 22]]`to*List*`[1, [21, 22]]`(elements are*IntScalar*).`[True, 1.0]`to*List*`[true, 1.0]`(elements are*BoolScalar*and*RealScalar*).

Python bytearray is converted to *Blob* by default. The only other possible conversion is bytearray to *List* (resulting List will contain a single Blob element).

Dictionaries (dict) are converted to *Dict* if all keys are strings, otherwise it produces a type error.

`None` is always converted to *Undefined*.

An N-dimensional array (numpy.ndarray) of values of the same type is by default converted to vector if N = 1 and to matrix if N = 2 (1-dimensional array can be forcibly converted to a single-row matrix). Any other numpy.ndarray is converted to *List* (note that array elements must be of a supported type).

pSeven type descriptions in the *pSeven Data Types* reference include Python equivalents to pSeven types. For a Python type, being equivalent to a pSeven type means that this Python type is converted to this pSeven type by default (that is, if conversion is not restricted by a port type or other means).

### pSeven to Python Types Conversion¶

Rules of conversion from pSeven to Python types are the most strict compared to conversion between pSeven types or from Python to pSeven types. This conversion is controlled by pSeven, and there is no way to force convert some pSeven type to a non-default Python type.

*BoolScalar*,*IntScalar*,*RealScalar*, and*StringScalar*are converted to bool, int, float and unicode respectively.- A
*vector*type is converted to 1-dimensional numpy.ndarray. This array contains values converted from pSeven*scalar*type to Python type (see above). - A
*matrix*type is converted to 2-dimensional numpy.ndarray. This array contains values converted from pSeven*scalar*type to Python type (see above). *List*is converted to list.*List*elements are converted following the rules for their types.*Dict*is converted to dict.*Dict*keys are converted to unicode (as they are originally*StringScalar*).*Dict*values are converted following the rules for their types.*Blob*is converted to bytearray.*File*cannot be converted to a Python file-like object or another type directly.*Undefined*is converted to`None`.

pSeven type descriptions in the *pSeven Data Types* reference include Python equivalents to pSeven types. Considering pSeven to Python types conversion, the Python equivalent is the resulting type.