Table of Contents

Using Python in EasyMorph

EasyMorph provides tight integration with Python by means of the "Call Python" action and the "easymorph" Python module that contains low-level bindings for use in Python scripts and is installed automatically with every EasyMorph installation. The action and the module allow:

Developing Python scripts for EasyMorph

The "easymorph" Python module can (and should) be used when writing Python scripts outside EasyMorph. The module gracefully handles the absence of a calling EasyMorph workflow, which is convenient for Python development in a standalone IDE. The module provides options for substituting workflow parameters and the input dataset with sample values for development and debugging without EasyMorph.

The "easymorph" module is located in the EasyMorph installation folder. Using the module without EasyMorph requires installing the module with the help of Python Wheels from the subfolder Python\dist in the EasyMorph installation folder.

Supported Python versions

Limits

The current implementation of Python integration in EasyMorph has the following limits:

Description Value
Max text string length 1,073,741,823 characters
Max rows in a dataset 536,870,897 rows
Max columns in a dataset 100,000 columns
Max number value* in a dataset cell 79228162514264337593543950335.0
Min number value* in a dataset cell -79228162514264337593543950335.0

* Number values in EasyMorph are 128-bit fixed-point decimals with 28-29 significant digits with or without the decimal point between them. A loss of precision is possible when converting numbers with a long fractional part to/from the popular Python float data type (64-bit floating point, 15 to 17 significant digits).

Sample Python script

example.py
from datetime import datetime
import time, math
 
# Import easymorph module. If the script is started by EasyMorph workflow, import
# would automatically read parameters and the input dataset of the Call Python action.
# Module does not have to be installed in this case, EasyMorph would make it available
# for this script via PYTHONPATH envar.
import easymorph as em
 
# EasyMorph module can used directly from command line as well, which we would refer as 'standalone' mode
# For standalone usage you would need to either add EasyMorph/Python/modules
# to PYTHONPATH or install WHL:` pip install --force-reinstall --no-index --find-links="Python/modules" easymorph `
# (assuming current working dir is EasyMorph installation location)
if em.standalone:
    print("Running in standalone mode; easymorph.input is not available")
else:
    print(
        f"Running from workflow: {em.input.length=}, {em.input.width=}"
    )  # print rows & columns counts
 
# Immutable input dataset is provided via easymorph.input.
# Simple way to define default dataset for standalone (when em.input is None):
src: em.Dataset = (
    em.input or em.DatasetBuilder().add_column("count", [1, 2, 3]).to_dataset()
)
 
 
def build_dataset():
    # Build dataset with mixed types and both dict/positional rows
    ds = (
        em.DatasetBuilder().add_rows(
            [
                {
                    "sensor": "S1",
                    "reading": 0.5,
                    "status": "ok",
                    "timestamp": datetime(2025, 1, 1),
                },
                {
                    "sensor": "S2",
                    "reading": None,
                    # 'status' column value is missing, will insert None and report warning 
                    # "status": "ok", - uncommenting this will fix the warning
                    "timestamp": None,
                },
                ["S3", 19.8, "ok", datetime(2025, 1, 3)],  # positional row
            ]
        )
        # Columns can be inserted via add_column; values are filled starting from the first row,
        # rest padded to None. Note that there is a fast path for float arrays. 
        .add_column("last_reported", [1.0, math.nan, 2.0]) 
    ).to_dataset()
 
    # Dataset info
    print("Column names:", [c.name for c in ds.columns])
    print("Row count:", ds.length)
 
 
 
    # Columns can be indexed:
    c0 = ds.columns[0]          # by index
    cs = ds.columns["sensor"]   # by name
    print("ds.columns[0].name:", c0.name, "ds.columns['sensor'].name:", cs.name)
    # First value from column 'status'
    print("ds['status'][0]:", ds.columns["status"][0])
 
    # Rows are convertible to 'dict'
    print("Last row as dict:", ds.rows[-1].to_dict())
    print("Last row [reading] value:", ds.rows[-1]["reading"])
 
    # Read a few values from columns
    print("sensor[0:2]:", list(cs[0:2]))
    print("reading[all]:", list(ds.columns["reading"]))
 
    # Column view to numbers (non-numbers are converted to NaN). This is the most efficient way to get numeric data.
    print("Readings as array:", ds.columns["reading"].to_numbers_array())
 
    # Slice rows
    first_two = ds.rows[:2]
    print("First two statuses:", [r["status"] for r in first_two])
 
    em.yield_output(ds)
 
 
# Simple passthrough demo. Note: this is lossy because numbers on the Python side are floats, not decimals
def passthrough():
    # yield_output is used to set output of the calling action and can be called only once
    # per script exectution. em.yield_output(None) is allowed to explicitly 'return' empty dataset
    em.yield_output(
        src  # em.input can be None if the calling action is set to not pass it
    )
 
 
# You can get all workflow parameters by calling em.get_params_as_dict()
def show_params():
    params = em.get_params_as_dict() or {"placeholder":True}
    print("Workflow parameters:", params)
    # return params as dataset
    em.yield_output(em.DatasetBuilder().add_row(params))
 
 
# Shows how to read/write .dset file
def file_operations():
    ds = em.DatasetBuilder().add_column("count", [1, 2, 3]).to_dataset()
    # Save a dataset to file and read it back
    em.save_dataset(ds, "example.dset")
    em.yield_output(
        em.read_dataset(
            "example.dset"
        )  # returned dataset is immutable just as em.input
    )
 
 
# Shows how cancellation can be handled in long running script
def cancellation(timeout=20.0):
    start_time = time.time()
    print("- waiting for cancellation (timeout", timeout, "s)")
    while not em.is_cancellation_requested():
        if time.time() - start_time > timeout:
            raise SystemError("Example script timed out. Expected cancellation.")
        time.sleep(0.2)
 
    # At any point where it is logically appropriate you can check if running workflow
    # is requesting cancellation. In standalone mode `is_cancellation_requested` returns False.
    # Script is not required to raise an exception on cancellation: this is simply one way to handle it
    if em.is_cancellation_requested():
        raise RuntimeError("Cancelled")
 
 
# It is possible to report warnings back to EasyMorp workflow using em.warn function
# Up to 128 warnings can be reported. 
def warnings():
    em.warn("First warning")    
    # Unequal column lengths result in a warning issued by DatasetBuilder 
    em.yield_output(
        em.DatasetBuilder().add_column("id", [1, 2]).add_column("count", [1, 2, 3]).to_dataset()
    )
    # warnings can be reported even after yield_output
    em.warn("Second warning", show_callsite=False) # this warning will not include call-site information
 
 
# Note: In version 1.0.0 there is no dedicated from/to_df functions yet.
# With glue code (fairly slow) there is a way to convert to/from DataFrame, if needed.
def pandas_interop():
    import pandas as pd   
    def dataset_to_df(ds: em.Dataset) -> pd.DataFrame: 
        return pd.DataFrame({col.name: list(col) for col in ds.columns})
    def dataset_to_df_numeric(ds: em.Dataset) -> pd.DataFrame:
        # All columns as float, non-numeric -> NaN. 
        # This is much faster option for numeric data
        return pd.DataFrame({col.name: col.to_numbers_array() for col in ds.columns})
 
    def df_to_dataset(df: pd.DataFrame) -> em.Dataset:
        b = em.DatasetBuilder()
        for name, series in df.items(): b.add_column(name, series)
        return b.to_dataset() 
 
    src_df = pd.DataFrame(
        {
            "C1": [1.0, float("nan"), 3.5],
            "C2": [3, None, "c"]
        }
    )
    ds_from_df = df_to_dataset(src_df) 
    df_from_ds = dataset_to_df(ds_from_df) 
    out_ds = df_to_dataset(df_from_ds)
    em.yield_output(out_ds)
 
 
def run_example(mode="standalone"):
    print(f"Running in mode '{mode}'")
    modes = {
        "build_dataset": build_dataset,
        "passthrough": passthrough,
        "cancellation": cancellation,
        "file_operations": file_operations,
        "warnings": warnings,
        "show_params": show_params,
        "pandas_interop": pandas_interop,
    } 
    try:
        modes[mode]()
    except KeyError:
        raise KeyError(f"Unknown mode '{mode}'. Valid modes: {list(modes)}") 
 
 
# In the workflow, parameter 'mode' is expected to be set; otherwise use 'when_standalone'
run_example(em.get_param("mode", when_standalone="show_params"))

Public interface

easymorph.pyi
import collections.abc
import numpy
import numpy.typing
import typing
from typing import Any, overload
 
input: None
standalone: bool
 
class Column:
    def __init__(self, *args, **kwargs) -> None:
        """Initialize self.  See help(type(self)) for accurate signature."""
    def to_numbers_array(self) -> numpy.typing.NDArray[numpy.float64]:
        """to_numbers_array(self: easymorph.Column) -> numpy.typing.NDArray[numpy.float64]
 
        Returns a copy of the column as an array of floats. Non-numeric values are NaNs.
        """
    def __array__(self) -> numpy.typing.NDArray[numpy.float64]:
        """__array__(self: easymorph.Column) -> numpy.typing.NDArray[numpy.float64]
 
        Returns a copy of the column as an array of floats. Non-numeric values are NaNs.
        """
    @overload
    def __getitem__(self, arg0: typing.SupportsInt) -> None | str | float | bool:
        """__getitem__(*args, **kwargs)
        Overloaded function.
 
        1. __getitem__(self: easymorph.Column, arg0: typing.SupportsInt) -> None | str | float | bool
 
        2. __getitem__(self: easymorph.Column, arg0: slice) -> easymorph.ColumnSliceView
        """
    @overload
    def __getitem__(self, arg0: slice) -> ColumnSliceView:
        """__getitem__(*args, **kwargs)
        Overloaded function.
 
        1. __getitem__(self: easymorph.Column, arg0: typing.SupportsInt) -> None | str | float | bool
 
        2. __getitem__(self: easymorph.Column, arg0: slice) -> easymorph.ColumnSliceView
        """
    def __iter__(self) -> collections.abc.Iterator[None | str | float | bool]:
        """__iter__(self: easymorph.Column) -> collections.abc.Iterator[None | str | float | bool]"""
    def __len__(self) -> int:
        """__len__(self: easymorph.Column) -> int"""
    @property
    def name(self) -> str:
        """(arg0: easymorph.Column) -> str"""
 
class ColumnSliceView:
    def __init__(self, *args, **kwargs) -> None:
        """Initialize self.  See help(type(self)) for accurate signature."""
    def __getitem__(self, arg0: typing.SupportsInt) -> None | str | float | bool:
        """__getitem__(self: easymorph.ColumnSliceView, arg0: typing.SupportsInt) -> None | str | float | bool"""
    def __iter__(self) -> collections.abc.Iterator[None | str | float | bool]:
        """__iter__(self: easymorph.ColumnSliceView) -> collections.abc.Iterator[None | str | float | bool]"""
    def __len__(self) -> int:
        """__len__(self: easymorph.ColumnSliceView) -> int"""
 
class ColumnsRange:
    def __init__(self, *args, **kwargs) -> None:
        """Initialize self.  See help(type(self)) for accurate signature."""
    def __contains__(self, arg0: str) -> bool:
        """__contains__(self: easymorph.ColumnsRange, arg0: str) -> bool"""
    @overload
    def __getitem__(self, arg0: typing.SupportsInt) -> Column:
        """__getitem__(*args, **kwargs)
        Overloaded function.
 
        1. __getitem__(self: easymorph.ColumnsRange, arg0: typing.SupportsInt) -> easymorph.Column
 
        2. __getitem__(self: easymorph.ColumnsRange, arg0: str) -> easymorph.Column
        """
    @overload
    def __getitem__(self, arg0: str) -> Column:
        """__getitem__(*args, **kwargs)
        Overloaded function.
 
        1. __getitem__(self: easymorph.ColumnsRange, arg0: typing.SupportsInt) -> easymorph.Column
 
        2. __getitem__(self: easymorph.ColumnsRange, arg0: str) -> easymorph.Column
        """
    def __iter__(self) -> collections.abc.Iterator[Column]:
        """__iter__(self: easymorph.ColumnsRange) -> collections.abc.Iterator[easymorph.Column]"""
    def __len__(self) -> int:
        """__len__(self: easymorph.ColumnsRange) -> int"""
 
class Dataset:
    """Immutable columnar dataset."""
    def __init__(self, *args, **kwargs) -> None:
        """Initialize self.  See help(type(self)) for accurate signature."""
    @overload
    def get_cell(self, column: typing.SupportsInt, row: typing.SupportsInt) -> None | str | float | bool:
        """get_cell(*args, **kwargs)
        Overloaded function.
 
        1. get_cell(self: easymorph.Dataset, column: typing.SupportsInt, row: typing.SupportsInt) -> None | str | float | bool
 
        Get cell data as bool | str | float or None.
 
        2. get_cell(self: easymorph.Dataset, column: str, row: typing.SupportsInt) -> None | str | float | bool
 
        Get cell data as bool | str | float or None.
        """
    @overload
    def get_cell(self, column: str, row: typing.SupportsInt) -> None | str | float | bool:
        """get_cell(*args, **kwargs)
        Overloaded function.
 
        1. get_cell(self: easymorph.Dataset, column: typing.SupportsInt, row: typing.SupportsInt) -> None | str | float | bool
 
        Get cell data as bool | str | float or None.
 
        2. get_cell(self: easymorph.Dataset, column: str, row: typing.SupportsInt) -> None | str | float | bool
 
        Get cell data as bool | str | float or None.
        """
    def get_cell_as_date(self, column: typing.SupportsInt, row: typing.SupportsInt) -> object:
        """get_cell_as_date(self: easymorph.Dataset, column: typing.SupportsInt, row: typing.SupportsInt) -> object
 
        Try converting numeric cell value to datetime.
        """
    @overload
    def get_cell_as_text(self, column: typing.SupportsInt, row: typing.SupportsInt) -> str:
        """get_cell_as_text(*args, **kwargs)
        Overloaded function.
 
        1. get_cell_as_text(self: easymorph.Dataset, column: typing.SupportsInt, row: typing.SupportsInt) -> str
 
        Get cell content as text string.
 
        2. get_cell_as_text(self: easymorph.Dataset, column: str, row: typing.SupportsInt) -> str
 
        Get cell content as text string.
        """
    @overload
    def get_cell_as_text(self, column: str, row: typing.SupportsInt) -> str:
        """get_cell_as_text(*args, **kwargs)
        Overloaded function.
 
        1. get_cell_as_text(self: easymorph.Dataset, column: typing.SupportsInt, row: typing.SupportsInt) -> str
 
        Get cell content as text string.
 
        2. get_cell_as_text(self: easymorph.Dataset, column: str, row: typing.SupportsInt) -> str
 
        Get cell content as text string.
        """
    @property
    def columns(self) -> ColumnsRange:
        """Column view.
        (arg0: easymorph.Dataset) -> easymorph.ColumnsRange
        """
    @property
    def length(self) -> int:
        """Number of rows.
        (arg0: easymorph.Dataset) -> int
        """
    @property
    def rows(self) -> RowsView:
        """Row view.
        (arg0: easymorph.Dataset) -> easymorph.RowsView
        """
    @property
    def width(self) -> int:
        """Number of columns.
        (arg0: easymorph.Dataset) -> int
        """
 
class DatasetBuilder:
    """Incrementally builds a columnar Dataset in native memory."""
    def __init__(self) -> None:
        """__init__(self: easymorph.DatasetBuilder) -> None"""
    @overload
    def add_column(self, arg0: str, arg1: collections.abc.Iterable) -> DatasetBuilder:
        """add_column(*args, **kwargs)
        Overloaded function.
 
        1. add_column(self: easymorph.DatasetBuilder, arg0: str, arg1: collections.abc.Iterable) -> easymorph.DatasetBuilder
 
 
        add_column(name, values)
 
        Bulk append rows to specified column. Creates column if it is not found.
 
        Notes
        -----
        - This is fastest way to build a dataset. 
 
 
        2. add_column(self: easymorph.DatasetBuilder, arg0: str, arg1: collections.abc.Sequence[typing.SupportsFloat]) -> easymorph.DatasetBuilder
 
 
        add_column(name, values)
 
        Bulk append rows to specified column. Creates column if it is not found.
 
        Notes
        -----
        - This is fastest way to build a dataset. 
 
        """
    @overload
    def add_column(self, name, values) -> Any:
        """add_column(*args, **kwargs)
        Overloaded function.
 
        1. add_column(self: easymorph.DatasetBuilder, arg0: str, arg1: collections.abc.Iterable) -> easymorph.DatasetBuilder
 
 
        add_column(name, values)
 
        Bulk append rows to specified column. Creates column if it is not found.
 
        Notes
        -----
        - This is fastest way to build a dataset. 
 
 
        2. add_column(self: easymorph.DatasetBuilder, arg0: str, arg1: collections.abc.Sequence[typing.SupportsFloat]) -> easymorph.DatasetBuilder
 
 
        add_column(name, values)
 
        Bulk append rows to specified column. Creates column if it is not found.
 
        Notes
        -----
        - This is fastest way to build a dataset. 
 
        """
    @overload
    def add_column(self, arg0: str, arg1: collections.abc.Sequence[typing.SupportsFloat]) -> DatasetBuilder:
        """add_column(*args, **kwargs)
        Overloaded function.
 
        1. add_column(self: easymorph.DatasetBuilder, arg0: str, arg1: collections.abc.Iterable) -> easymorph.DatasetBuilder
 
 
        add_column(name, values)
 
        Bulk append rows to specified column. Creates column if it is not found.
 
        Notes
        -----
        - This is fastest way to build a dataset. 
 
 
        2. add_column(self: easymorph.DatasetBuilder, arg0: str, arg1: collections.abc.Sequence[typing.SupportsFloat]) -> easymorph.DatasetBuilder
 
 
        add_column(name, values)
 
        Bulk append rows to specified column. Creates column if it is not found.
 
        Notes
        -----
        - This is fastest way to build a dataset. 
 
        """
    @overload
    def add_column(self, name, values) -> Any:
        """add_column(*args, **kwargs)
        Overloaded function.
 
        1. add_column(self: easymorph.DatasetBuilder, arg0: str, arg1: collections.abc.Iterable) -> easymorph.DatasetBuilder
 
 
        add_column(name, values)
 
        Bulk append rows to specified column. Creates column if it is not found.
 
        Notes
        -----
        - This is fastest way to build a dataset. 
 
 
        2. add_column(self: easymorph.DatasetBuilder, arg0: str, arg1: collections.abc.Sequence[typing.SupportsFloat]) -> easymorph.DatasetBuilder
 
 
        add_column(name, values)
 
        Bulk append rows to specified column. Creates column if it is not found.
 
        Notes
        -----
        - This is fastest way to build a dataset. 
 
        """
    @overload
    def add_columns(self, columns: dict) -> DatasetBuilder:
        """add_columns(self: easymorph.DatasetBuilder, columns: dict) -> easymorph.DatasetBuilder
 
 
        add_columns(columns)
 
        Add several columns in a single call.
 
        Parameters
        ----------
        columns : Mapping[str, Iterable[Any] | numpy.ndarray]
            Dict mapping column names to data.
            - Fast path: a 1D float64 array.
            - Otherwise: any iterable of convertible values.
 
        Returns
        -------
        DatasetBuilder
            The builder itself (chainable).
 
        Raises
        ------
        TypeError | ValueError
            When a value cannot be represented as EasyMorph cell type. 
 
        """
    @overload
    def add_columns(self, columns) -> Any:
        """add_columns(self: easymorph.DatasetBuilder, columns: dict) -> easymorph.DatasetBuilder
 
 
        add_columns(columns)
 
        Add several columns in a single call.
 
        Parameters
        ----------
        columns : Mapping[str, Iterable[Any] | numpy.ndarray]
            Dict mapping column names to data.
            - Fast path: a 1D float64 array.
            - Otherwise: any iterable of convertible values.
 
        Returns
        -------
        DatasetBuilder
            The builder itself (chainable).
 
        Raises
        ------
        TypeError | ValueError
            When a value cannot be represented as EasyMorph cell type. 
 
        """
    @overload
    def add_row(self, record: object) -> DatasetBuilder:
        """add_row(self: easymorph.DatasetBuilder, record: object) -> easymorph.DatasetBuilder
 
 
        add_row(record)
 
        Append a single row.
 
        Parameters
        ----------
        record : dict[str, Any] | Sequence[Any]
            - Mapping: keys become column names; missing columns are padded
              with empty cells. Extra keys create new columns on the fly.
            - Sequence: values are written by position; missing tail values
              are padded. New columns are created when the sequence is longer
              than the current width.
 
        Raises
        ------
        TypeError
            If *record* is neither a dict nor a sequence.
 
        """
    @overload
    def add_row(self, record) -> Any:
        """add_row(self: easymorph.DatasetBuilder, record: object) -> easymorph.DatasetBuilder
 
 
        add_row(record)
 
        Append a single row.
 
        Parameters
        ----------
        record : dict[str, Any] | Sequence[Any]
            - Mapping: keys become column names; missing columns are padded
              with empty cells. Extra keys create new columns on the fly.
            - Sequence: values are written by position; missing tail values
              are padded. New columns are created when the sequence is longer
              than the current width.
 
        Raises
        ------
        TypeError
            If *record* is neither a dict nor a sequence.
 
        """
    @overload
    def add_rows(self, records: collections.abc.Iterable) -> DatasetBuilder:
        """add_rows(self: easymorph.DatasetBuilder, records: collections.abc.Iterable) -> easymorph.DatasetBuilder
 
 
        add_rows(records)
 
        Bulk append rows from any iterable that yields row objects. 
 
        Parameters
        ----------
        records : Iterable[Any]
            Objects accepted by add_row.
 
        Notes
        -----
        - This is a bit faster than calling `add_row` in a Python loop. 
 
        """
    @overload
    def add_rows(self, records) -> Any:
        """add_rows(self: easymorph.DatasetBuilder, records: collections.abc.Iterable) -> easymorph.DatasetBuilder
 
 
        add_rows(records)
 
        Bulk append rows from any iterable that yields row objects. 
 
        Parameters
        ----------
        records : Iterable[Any]
            Objects accepted by add_row.
 
        Notes
        -----
        - This is a bit faster than calling `add_row` in a Python loop. 
 
        """
    @overload
    def to_dataset(self, reset: bool = ...) -> Dataset:
        """to_dataset(self: easymorph.DatasetBuilder, reset: bool = True) -> easymorph.Dataset
 
 
        to_dataset(reset=True)
 
        Finalize the builder and return an immutable dataset.
 
        Parameters
        ----------
        reset : bool, default True
            Clear the builder after the dataset is created.
 
        Returns
        -------
        Dataset
            Resulting immutable dataset.
 
        """
    @overload
    def to_dataset(self, reset=...) -> Any:
        """to_dataset(self: easymorph.DatasetBuilder, reset: bool = True) -> easymorph.Dataset
 
 
        to_dataset(reset=True)
 
        Finalize the builder and return an immutable dataset.
 
        Parameters
        ----------
        reset : bool, default True
            Clear the builder after the dataset is created.
 
        Returns
        -------
        Dataset
            Resulting immutable dataset.
 
        """
    @property
    def column_names(self) -> list[str]:
        """Return a list of all column names.
        (arg0: easymorph.DatasetBuilder) -> list[str]
        """
    @property
    def length(self) -> int:
        """Number of rows.
        (arg0: easymorph.DatasetBuilder) -> int
        """
    @property
    def width(self) -> int:
        """Number of columns.
        (arg0: easymorph.DatasetBuilder) -> int
        """
 
class ErrorValue:
    """EasyMorph error cell value."""
    def __init__(self, arg0: str) -> None:
        """__init__(self: easymorph.ErrorValue, arg0: str) -> None"""
    @property
    def text(self) -> str:
        """(self: easymorph.ErrorValue) -> str"""
 
class Row:
    def __init__(self, *args, **kwargs) -> None:
        """Initialize self.  See help(type(self)) for accurate signature."""
    def to_dict(self) -> dict:
        """to_dict(self: easymorph.Row) -> dict"""
    @overload
    def __getitem__(self, arg0: typing.SupportsInt) -> None | str | float | bool:
        """__getitem__(*args, **kwargs)
        Overloaded function.
 
        1. __getitem__(self: easymorph.Row, arg0: typing.SupportsInt) -> None | str | float | bool
 
        2. __getitem__(self: easymorph.Row, arg0: str) -> None | str | float | bool
        """
    @overload
    def __getitem__(self, arg0: str) -> None | str | float | bool:
        """__getitem__(*args, **kwargs)
        Overloaded function.
 
        1. __getitem__(self: easymorph.Row, arg0: typing.SupportsInt) -> None | str | float | bool
 
        2. __getitem__(self: easymorph.Row, arg0: str) -> None | str | float | bool
        """
    def __len__(self) -> int:
        """__len__(self: easymorph.Row) -> int"""
 
class RowsView:
    def __init__(self, *args, **kwargs) -> None:
        """Initialize self.  See help(type(self)) for accurate signature."""
    @overload
    def __getitem__(self, arg0: typing.SupportsInt) -> Row:
        """__getitem__(*args, **kwargs)
        Overloaded function.
 
        1. __getitem__(self: easymorph.RowsView, arg0: typing.SupportsInt) -> easymorph.Row
 
        2. __getitem__(self: easymorph.RowsView, arg0: slice) -> easymorph.RowsView
        """
    @overload
    def __getitem__(self, arg0: slice) -> RowsView:
        """__getitem__(*args, **kwargs)
        Overloaded function.
 
        1. __getitem__(self: easymorph.RowsView, arg0: typing.SupportsInt) -> easymorph.Row
 
        2. __getitem__(self: easymorph.RowsView, arg0: slice) -> easymorph.RowsView
        """
    def __iter__(self) -> collections.abc.Iterator[Row]:
        """__iter__(self: easymorph.RowsView) -> collections.abc.Iterator[easymorph.Row]"""
    def __len__(self) -> int:
        """__len__(self: easymorph.RowsView) -> int"""
 
def get_param(key: str, when_standalone: object = ...) -> object:
    """get_param(key: str, when_standalone: object = None) -> object
 
    Get parameter passed from the calling workflow. Optional argument for standalone scripts.
    """
def get_param_as_date(key: str, when_standalone: object = ...) -> object:
    """get_param_as_date(key: str, when_standalone: object = None) -> object
 
    Return a workflow parameter converted to datetime. Raises if not convertible. Optional argument for standalone scripts.
    """
def get_params_as_dict(errors_as_values: bool = ...) -> dict:
    """get_params_as_dict(errors_as_values: bool = False) -> dict
 
    Return all workflow parameters as a dict.
    """
def is_cancellation_requested() -> bool:
    """is_cancellation_requested() -> bool
 
    Return True if the EasyMorph engine requested cancellation; the script should exit soon.
    """
def number_to_date(arg0: typing.SupportsFloat) -> object:
    """number_to_date(arg0: typing.SupportsFloat) -> object
 
    Convert OADate number to datetime.
    """
def read_dataset(arg0: str) -> Dataset:
    """read_dataset(arg0: str) -> easymorph.Dataset
 
 
    Read a dataset from disk.
 
    Parameters
    ----------
    fname : str | os.PathLike
        Path to an EasyMorph .dset file.
 
    Returns
    -------
    Dataset
        Immutable dataset loaded into native memory.
 
    Raises
    ------
    RuntimeError | ValueError
        When the file is not a valid dataset.
 
    """
def save_dataset(arg0: Dataset, arg1: str) -> None:
    """save_dataset(arg0: easymorph.Dataset, arg1: str) -> None
 
 
    Save a dataset to disk.
 
    Parameters
    ----------
    output_dset : Dataset
        Dataset to write.
    fname : str | os.PathLike
        Target file path.
 
    Raises
    ------
    ValueError
        If *output_dset* is None.
 
    """
def warn(msg: str, show_callsite: bool = ...) -> None:
    """warn(msg: str, show_callsite: bool = True) -> None
 
 
    Log a warning message to the EasyMorph engine.
 
    Parameters
    ----------
    msg : str
        Warning text.
    show_callsite : bool, default True
        Include the call-site line when True.
 
    Notes
    -----
    - The message is recorded only in the module's internal warning collection, it's not
      passed to python's `warnings`. 
 
    """
@overload
def yield_output(arg0: Dataset) -> None:
    """yield_output(*args, **kwargs)
    Overloaded function.
 
    1. yield_output(arg0: easymorph.Dataset) -> None
 
    Sets the output of calling EasyMorph action. Has no effect in standalone mode.
 
    2. yield_output(arg0: easymorph.DatasetBuilder) -> None
 
    Sets the output of calling EasyMorph action. Has no effect in standalone mode.
    """
@overload
def yield_output(arg0: DatasetBuilder) -> None:
    """yield_output(*args, **kwargs)
    Overloaded function.
 
    1. yield_output(arg0: easymorph.Dataset) -> None
 
    Sets the output of calling EasyMorph action. Has no effect in standalone mode.
 
    2. yield_output(arg0: easymorph.DatasetBuilder) -> None
 
    Sets the output of calling EasyMorph action. Has no effect in standalone mode.
    """