Python functions are currently in a beta state and may not be available on all enrollments.
Below is the full list of currently supported functions API types and their corresponding Python type.
Functions API type | Corresponding Python type |
---|---|
Binary | bytes |
Boolean | bool |
Byte | int* |
Date | datetime.date |
Decimal | decimal.Decimal |
Double | float* |
Float | float |
Integer | int |
Long | int* |
Short | int* |
String | str |
Timestamp | datetime.datetime |
Optional | typing.Optional |
Array | list |
Map | dict |
Set | set |
Struct / custom type | dataclasses.dataclass (Example) |
TwoDimensionalAggregation | TwoDimensionalAggregation (Example) |
ThreeDimensionalAggregation | ThreeDimensionalAggregation (Example) |
Attachment | Attachment |
OntologyObject | OntologyObject |
OntologyObjectSet | OntologyObjectSet |
OntologyEdit | OntologyEdit |
Although both Integer
and Long
correspond to the Python type int
, any fields marked as int
directly in your function signature will be registered with type Integer
. Therefore, we instead recommend using either the Integer
or Long
types from the API to register numerical data types. Similar guidelines apply to Float
and Double
; if the Python type float
is directly in your function signature, it will be registered as Float
by default.
Optional arguments and return values can be declared using typing.Optional[T]
or T | None
. The T | None
syntax requires Python 3.10 or greater. The parameterized type T
must be specified, and it must be another supported type.
For optional arguments, it is helpful to also define a default value:
Copied!1 2
def my_optional_arg(maybe_value: String | None = None) -> String | None: ...
If no default value is specified, callers will still need to provide values for optional arguments (where None
is a valid value).
Collection types are parameterized by other types. For example, Array[String] is a list of strings and Map[String, Integer] is a dictionary with string keys and integer values. The parameterized types must be specified, and the type must be another supported type. Map keys may only be scalar types or an Ontology object type.
The TwoDimensionalAggregation
and ThreeDimensionalAggregation
types in the functions API package may be used as return value types.
Bucket value, key, and nested key types must all be specified in the function signature, for example:
Copied!1 2 3 4
@function def my_three_dimensional_aggregation_function() -> ( ThreeDimensionalAggregation[str, str, Double] ): ...
This type is compatible with the Workshop Chart XY widget function-backed layers.
The Attachment
class from the functions API package may be used as a function argument or return type.
See Python function attachments for more details on how to use this type.
Any classes that implement the abstract base class OntologyObject
or OntologyObjectSet
from the functions API package may be used as function argument or return types.
This includes any object and object set types generated as part of a Python Ontology SDK.
The OntologyEdit
class from the function API package may be used as a function return type. Ontology edits are generally returned as a list: List[OntologyEdit]
.
See Python function Ontology edits for more details on how to use this type.
Custom Python classes composed of other supported types can also be used in function signatures. The API package does not have an explicit Custom
type; instead, custom types are declared as user-defined Python classes.
To be a valid custom type, the class must adhere to the following:
__init__
method must accept only named arguments with the same names and type annotations as the fields.The dataclasses.dataclass
↗ decorator can be used to automatically generate an __init__
method that conforms with these requirements.
An example using the functions API types:
Copied!1 2 3 4 5 6
from functions.api import function, Long, String, Timestamp @function def get_end_day_of_week(start_time: Timestamp, elapsed_millis: Long) -> String: # function logic here pass
As shown in the above types table, this function could also be declared using only built-in Python types:
Copied!1 2 3 4 5 6 7
from functions.api import function from datetime import datetime @function def get_end_day_of_week(start_time: datetime, elapsed_millis: int) -> str: # function logic here pass
Additionally, you could use a combination of built-in and API types:
Copied!1 2 3 4 5 6 7
from functions.api import function, Long, String from datetime import datetime @function def get_end_day_of_week(start_time: datetime, elapsed_millis: Long) -> String: # function logic here pass
Here is an example of a TwoDimensionalAggregation
:
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
from functions.api import ( function, Double, TwoDimensionalAggregation, SingleBucket ) @function def my_two_dimensional_aggregation_function() -> TwoDimensionalAggregation[str, Double]: return TwoDimensionalAggregation( buckets=[ SingleBucket(key="bucket1", value=Double(5.0)), SingleBucket(key="bucket2", value=Double(6.0)), ] )
Here is an example of a ThreeDimensionalAggregation
:
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
from functions.api import ( function, Double, ThreeDimensionalAggregation, SingleBucket, NestedBucket, ) @function def my_three_dimensional_aggregation_function() -> ( ThreeDimensionalAggregation[str, str, Double] ): return ThreeDimensionalAggregation( buckets=[ NestedBucket(key="group-by-1", buckets=[ SingleBucket(key="partition-by-1", value=Double(5.0)), SingleBucket(key="partition-by-2", value=Double(6.0)), ]), NestedBucket(key="group-by-2", buckets=[ SingleBucket(key="partition-by-1", value=Double(7.0)), SingleBucket(key="partition-by-2", value=Double(8.0)), ]) ] )
Here is an example with dataclasses.dataclass
:
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
from dataclasses import dataclass from functions.api import Float, Integer, String, function @dataclass class InventoryItem: """Class for keeping track of an item in inventory.""" name: String unit_price: Float quantity_on_hand: Integer = 0 def total_cost(self) -> Float: return self.unit_price * self.quantity_on_hand @function def custom_type_with_init_from_decorator(inventory_item: InventoryItem) -> Float: return inventory_item.total_cost()
Here is an example without dataclasses.dataclass
, and instead using API types:
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
from functions.api import function, String, Timestamp class Event: timestamp: Timestamp message: String def __init__( self, timestamp: Timestamp, message: String ): self.timestamp = timestamp self.message = message @function def get_event_message(event: Event) -> String: return event.message