Skip to content

Resources & fields

Resources are the configurable, persistable components (connections, configs, destinations); fields declare how their values are collected.

Resource

Resource(**data: Any)

Bases: pydantic_settings.main.BaseSettings, interloper.component.base.Component

Base for injectable dependencies resolved and injected into asset functions.

Extends BaseSettings, so resource values can be loaded from environment variables, .env files, or passed directly. Subclass to define a custom resource:

class MyCache(Resource):
    model_config = SettingsConfigDict(env_prefix="my_cache_")

    host: str = "localhost"
    port: int = 6379

    def get(self, key: str) -> Any: ...
    def set(self, key: str, value: Any) -> None: ...

Resources are declared on assets via decorator kwargs or type annotations and resolved through a cascade: asset → source → auto-instantiate.

Built-in resource types: - Config: env-loaded settings - Connection: credentials and client factories

key

key = 'resource'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

kind

kind = 'resource'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

model_config

model_config = {'extra': 'forbid', 'arbitrary_types_allowed': True, 'validate_default': True, 'case_sensitive': False, 'env_prefix': '', 'env_prefix_target': 'variable', 'nested_model_default_partial_update': False, 'env_file': None, 'env_file_encoding': None, 'env_ignore_empty': False, 'env_nested_delimiter': None, 'env_nested_max_split': None, 'env_parse_none_str': None, 'env_parse_enums': None, 'cli_prog_name': None, 'cli_parse_args': None, 'cli_parse_none_str': None, 'cli_hide_none_type': False, 'cli_avoid_json': False, 'cli_enforce_required': False, 'cli_use_class_docs_for_groups': False, 'cli_show_env_vars': False, 'cli_exit_on_error': True, 'cli_prefix': '', 'cli_flag_prefix_char': '-', 'cli_implicit_flags': False, 'cli_ignore_unknown_args': False, 'cli_kebab_case': False, 'cli_shortcuts': None, 'json_file': None, 'json_file_encoding': None, 'yaml_file': None, 'yaml_file_encoding': None, 'yaml_config_section': None, 'toml_file': None, 'secrets_dir': None, 'protected_namespaces': ('model_validate', 'model_dump', 'settings_customise_sources'), 'enable_decoding': True, 'ignored_types': (<class 'interloper.serializable.base.IgnoredDescriptor'>, <class 'interloper.component.relation.Relation'>)}

dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)

relations

relations = {}

dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)

sensitive

sensitive = True

bool(x) -> bool

Returns True when the argument x is true, False otherwise. The builtins True and False are the only two instances of the class bool. The class bool is a subclass of the class int, and cannot be subclassed.

definition

definition() -> ResourceDefinition

Produce a structured definition of this resource class.

The config schema is inlined as it belongs to the resource itself.

Returns:

Type Description
ResourceDefinition

A ResourceDefinition with metadata and JSON Schema.

model_post_init

model_post_init(context: Any) -> None

Default id to a generated UUID if not provided.

Parameters:

Name Type Description Default
context Any

The pydantic validation context, unused here.

required

ResourceDefinition

Bases: interloper.component.base.ComponentDefinition

Definition of a resource with its config schema inlined.

The config schema is the JSON Schema of the resource's own fields: this is same-entity data so it's always inlined, never a key reference.

model_config

model_config = {}

dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)

config

config(target: Any = None, /, **settings: Any) -> Any

Create a Config subclass from a decorated class.

Can be used bare or with arguments:

@config
class MyConfig:
    api_key: str
    base_url: str = "https://api.example.com"

@config(key="custom", name="Custom Config")
class OtherConfig(Config):
    timeout: int = 30

The decorated class's annotations and attributes become the Config subclass body. Since Config extends BaseSettings, fields can still be loaded from environment variables.

relations maps a relation name to a Relation, a component class, or a list of component classes narrowing the relation the decorated class declares under that name. Every other keyword is one of the public ClassVars and field defaults the decorated class declares, or Config itself for a plain class (key, name, icon, tags). An unknown name is a TypeError at decoration.

Config

Config(**data: Any)

Bases: interloper.resource.base.Resource

A resource for arbitrary configuration values.

Like every Resource, config values can be loaded from environment variables, .env files, or passed directly:

class MyConfig(Config):
    api_key: str
    base_url: str = "https://api.example.com"

# Loads API_KEY from environment if not passed explicitly
config = MyConfig()

key

key = 'config'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

kind

kind = 'config'

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.

model_config

model_config = {'extra': 'forbid', 'arbitrary_types_allowed': True, 'validate_default': True, 'case_sensitive': False, 'env_prefix': '', 'env_prefix_target': 'variable', 'nested_model_default_partial_update': False, 'env_file': None, 'env_file_encoding': None, 'env_ignore_empty': False, 'env_nested_delimiter': None, 'env_nested_max_split': None, 'env_parse_none_str': None, 'env_parse_enums': None, 'cli_prog_name': None, 'cli_parse_args': None, 'cli_parse_none_str': None, 'cli_hide_none_type': False, 'cli_avoid_json': False, 'cli_enforce_required': False, 'cli_use_class_docs_for_groups': False, 'cli_show_env_vars': False, 'cli_exit_on_error': True, 'cli_prefix': '', 'cli_flag_prefix_char': '-', 'cli_implicit_flags': False, 'cli_ignore_unknown_args': False, 'cli_kebab_case': False, 'cli_shortcuts': None, 'json_file': None, 'json_file_encoding': None, 'yaml_file': None, 'yaml_file_encoding': None, 'yaml_config_section': None, 'toml_file': None, 'secrets_dir': None, 'protected_namespaces': ('model_validate', 'model_dump', 'settings_customise_sources'), 'enable_decoding': True, 'ignored_types': (<class 'interloper.serializable.base.IgnoredDescriptor'>, <class 'interloper.component.relation.Relation'>)}

dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)

relations

relations = {}

dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)

tags

tags = []

Built-in mutable sequence.

If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

model_post_init

model_post_init(context: Any) -> None

Default id to a generated UUID if not provided.

Parameters:

Name Type Description Default
context Any

The pydantic validation context, unused here.

required

InputField

InputField(default: Any = Ellipsis, **kwargs: Any) -> Any

String field rendered as a standard text input.

Parameters:

Name Type Description Default
default Any

Default value (... means required).

Ellipsis
**kwargs Any

Forwarded to pydantic.Field. Pass discriminator=True to mark the field as the component's instance discriminator.

required

Returns:

Type Description
Any

A Pydantic Field descriptor.

Example:

account_id: str = InputField(description="Your account ID")

TextField

TextField(default: Any = Ellipsis, **kwargs: Any) -> Any

String field rendered as a multi-line textarea.

Parameters:

Name Type Description Default
default Any

Default value (... means required).

Ellipsis
**kwargs Any

Forwarded to pydantic.Field.

required

Returns:

Type Description
Any

A Pydantic Field descriptor.

Example:

query: str = TextField(description="SQL query")

SecretField

SecretField(default: Any = Ellipsis, **kwargs: Any) -> Any

String field rendered as a password input.

Parameters:

Name Type Description Default
default Any

Default value (... means required).

Ellipsis
**kwargs Any

Forwarded to pydantic.Field.

required

Returns:

Type Description
Any

A Pydantic Field descriptor.

Example:

api_key: str = SecretField(description="API key")

SelectField

SelectField(
    default: Any = Ellipsis,
    *,
    options: list[dict[str, str]] | None = None,
    options_from: str | None = None,
    **kwargs: Any,
) -> Any

String field rendered as a dropdown select.

Options can be provided statically via options, or resolved dynamically at render time via options_from.

Parameters:

Name Type Description Default
default Any

Default value (... means required).

Ellipsis
options list[dict[str, str]] | None

Static list of {"label": "...", "value": "..."} dicts.

None
options_from str | None

Entity whose configured instances provide the options (e.g. "destinations"). Serialized as x-options-from in the JSON Schema so the frontend can resolve options from context.

None
**kwargs Any

Forwarded to pydantic.Field.

required

Returns:

Type Description
Any

A Pydantic Field descriptor.

Example:

region: str = SelectField(
    options=[
        {"label": "US", "value": "us"},
        {"label": "EU", "value": "eu"},
    ],
)

JsonField

JsonField(default: Any = Ellipsis, **kwargs: Any) -> Any

Dict/object field rendered as a JSON code editor.

Parameters:

Name Type Description Default
default Any

Default value (... means required).

Ellipsis
**kwargs Any

Forwarded to pydantic.Field.

required

Returns:

Type Description
Any

A Pydantic Field descriptor.

Example:

config: dict = JsonField(default_factory=dict)

CronField

CronField(default: Any = Ellipsis, **kwargs: Any) -> Any

Cron-expression field rendered with presets and a human-readable schedule.

Parameters:

Name Type Description Default
default Any

Default value (... means required).

Ellipsis
**kwargs Any

Forwarded to pydantic.Field.

required

Returns:

Type Description
Any

A Pydantic Field descriptor.

Example:

cron: str = CronField(description="When the job runs")

TimezoneField

TimezoneField(
    default: Any = Ellipsis, **kwargs: Any
) -> Any

IANA timezone field rendered as a searchable timezone picker.

Parameters:

Name Type Description Default
default Any

Default value (... means required).

Ellipsis
**kwargs Any

Forwarded to pydantic.Field.

required

Returns:

Type Description
Any

A Pydantic Field descriptor.

Example:

timezone: str = TimezoneField(default="UTC", description="Timezone the cron is evaluated in")

FetchField

FetchField(
    default: Any = Ellipsis,
    *,
    provider: str,
    label_key: str = "name",
    value_key: str = "id",
    **kwargs: Any,
) -> Any

Field whose options are fetched from a resource's provider method.

The backend instantiates the resource bound to the relation <name> (from the credentials the form already holds) and calls the fetch_field_provider method <method> on it. The lookup logic lives next to the credentials it uses; there is no per-provider API route to hand-write.

The dependency is the provider's own relation (the <name> part): the frontend waits for that resource to be selected, then resolves via /components/resolve. It is implicit in provider, so there is no separate depends_on.

Parameters:

Name Type Description Default
default Any

Default value (... means required).

Ellipsis
provider str

"<name>.<method>" reference to a @fetch_field_provider method on the resource bound to the relation <name>.

required
label_key str

Key in each response item used as the display label.

'name'
value_key str

Key in each response item used as the stored value.

'id'
**kwargs Any

Forwarded to pydantic.Field. Pass discriminator=True to mark the field as the component's instance discriminator.

required

Returns:

Type Description
Any

A Pydantic Field descriptor.

Raises:

Type Description
ValueError

If provider is not of the form "<name>.<method>".

Example:

account_id: str = FetchField(
    provider="connection.accounts",
    label_key="name",
    value_key="account_id",
)

fetch_field_provider

fetch_field_provider(fn: F) -> F

Mark a resource method as a FetchField data source.

A FetchField(provider="<name>.<method>") resolves its options by instantiating the resource bound to the relation <name> (from the credentials the form already holds) and calling the method named <method>. Only methods marked with this decorator may be invoked that way; it is the allowlist that stops the browser from calling arbitrary attributes.

The method runs inside the API process, which installs the connection classes but not their heavy provider SDK extras, so a provider must use lightweight HTTP (httpx2), never self.api (the SDK client).

It returns a list[dict]; the FetchField picks label_key / value_key out of each item:

class FacebookAdsConnection(il.Connection):
    @il.fetch_field_provider
    async def accounts(self) -> list[dict]:
        ...

Parameters:

Name Type Description Default
fn F

The resource method to mark as an options provider.

required

Returns:

Type Description
F

The same callable, stamped as a fetch provider.

is_fetch_field_provider

is_fetch_field_provider(candidate: Any) -> bool

Return whether candidate (a function or bound method) is a fetch provider.

Parameters:

Name Type Description Default
candidate Any

The attribute to test; anything without the provider stamp is not one.

required