Defining Task Signatures: The Native Interface
When you define a task in flyte-sdk, the framework needs to understand its inputs and outputs to ensure type safety, enable serialization, and facilitate validation across different execution environments. This understanding is encapsulated by the task's signature.
The flyte-sdk uses the NativeInterface class to represent this signature. It acts as a bridge, translating Python function definitions into a structured format that Flyte can process. Complementing NativeInterface is the _has_default marker class, which signals the presence of a default value for an input, particularly when the actual value isn't immediately available.
Core Functionality of NativeInterface
The NativeInterface class, defined in models.py, is a frozen dataclass that stores comprehensive information about a task's signature:
@dataclass(frozen=True)
class NativeInterface:
inputs: Dict[str, Tuple[Type, Any]]
outputs: Dict[str, Type]
docstring: Optional[Docstring] = None
_remote_defaults: Optional[Dict[str, literals_pb2.Literal]] = field(default=None, repr=False)
has_default: ClassVar[Type[_has_default]] = _has_default
inputs: A dictionary where keys are input parameter names (strings) and values are tuples. Each tuple contains the Python type of the input (Type) and its default value (Any). If an input has no default,inspect.Parameter.emptyis used. For remote tasks with default values, the specialNativeInterface.has_defaultmarker might be used instead of the actual value.outputs: A dictionary mapping output names (strings) to their corresponding Python types (Type).docstring: An optionalDocstringobject, capturing the task's documentation._remote_defaults: An optional dictionary used to store default values for remote tasks. These values are typicallyflyteidl.core.literals_pb2.Literalobjects, which are the Flyte IDL representation of literal values.has_default: A class variable set to_has_default. This marker is used internally to indicate that an input has a default value, but the value itself might be resolved externally (e.g., from_remote_defaults).
Defining Interfaces from Python Functions (from_callable)
For most flyte-sdk users, the primary way to define a task's interface is by writing a standard Python function with type hints and, optionally, default values. flyte-sdk then introspects this function to automatically construct the NativeInterface.
Consider a typical Flyte task definition:
from flytekit import task
from typing import List, Optional
@task
def process_data(input_id: int, data_source: str = "default_source", filters: Optional[List[str]] = None) -> str:
"""
Processes data based on an input ID and optional filters.
"""
if filters:
return f"Processing \{input_id\} from \{data_source\} with filters: \{