Skip to content

Helper types

ErrorMessage = TypeVar('ErrorMessage')

A string, callback validation error message.

TagValue = TypeVar('TagValue', bound=Any)

Any value. It is being wrapped by a Tag.

UiValue = TagValue | str

Candidate for the TagValue. Produced by the UI. Might be of the same type as the target TagValue, or str (as the default input type for interfaces that do not implement the given type further).

ValidationCallback = Callable[['Tag'], ValidationResult | tuple[ValidationResult, TagValue]] | BaseMetadata | GroupedMetadata

Being used at Tag.validation.

Either use a custom callback function, a provided validator, or an annotated-types predicate. (You can use multiple validation callbacks combined into an itarable.)

ValidationResult is a bool or the error message that implicitly means it has failed. Optionally, you may add a second argument to specify the tag value (to ex. recommend a better value).

Custom function

Handles the Tag.

from mininterface.tag import Tag

def my_validation(tag: Tag):
    return tag.val > 50

m.form({"number", Tag("", validation=my_validation)})

Provided validators

Found in the mininterface.validators module.

from mininterface.validators import not_empty
m.form({"number", Tag("", validation=not_empty)})
# User cannot leave the field empty.

You may use the validation in a type annotation.

from mininterface import Tag, Validation
@dataclass
class Env:
    my_text: Annotated[str, Validation(not_empty)] = "will not be emtpy"

    # which is an alias for:
    # my_text: Annotated[str, Tag(validation=not_empty)] = "will not be emtpy"

annotated-types predicate.

The annotated-types are de-facto standard for types restraining.

Currently, Gt, Ge, Lt, Le, MultipleOf and Len are supported.

from dataclasses import dataclass
from annotated_types import Ge
from mininterface import run

@dataclass
class AnnotatedTypes:
    age: Annotated[int, Ge(18)]

run(AnnotatedTypes).env.age  # guaranteed to be >= 18

Info

The annotated-types from the Annotated are prepended to the Tag(validation=) iterable.

@dataclass
class AnnotatedTypes:
    age: Annotated[int, Ge(18), Tag(validation=custom)]

# -> age: Annotated[int, Tag(validation=[Ge(18), custom])]

ValidationResult = bool | ErrorMessage

Being used at Tag.validation.

A bool or the error message (that implicitly means the ValidationCallback has failed) as shows the following table. Optionally, you may add a second argument to specify the tag value (to ex. recommend a better value).

return description
bool True if validation succeeded or False if validation failed.
str Error message if the validation failed.
tuple[bool|str, TagVal] The first argument is the same as above. The second is the value to be set.

This example shows the str error message:

def check(tag: Tag):
    if tag.val < 10:
        return "The value must be at least 10"
m.form({"number", Tag(12, validation=check)})

This example shows the value transformation. For val=50+, the validation fails.

def check(tag: Tag):
    return True, tag.val * 2
m.form({"number", Tag(12, validation=(check, Lt(100)))})

OptionsType = list[TagValue] | tuple[TagValue, ...] | set[TagValue] | dict[RichOptionLabel, TagValue] | Iterable[Enum] | Type[Enum]

You can denote the options in many ways. Either put options in an iterable or to a dict {labels: value}. Values might be Tags as well. Let's take a detailed look. We will use the run.select(OptionsType) to illustrate the examples.

Iterables like list

Either put options in an iterable:

from mininterface import run
m = run()
m.select([1, 2])

Options as a list

Dict for labels

Or to a dict {name: value}. Then name are used as labels.

m.select({"one": 1, "two": 2})  # returns 1
Dict with tuples for table

If you use tuple as the keys, they will be joined into a table.

m.select({("one", "two", "three"): 1, ("lorem", "ipsum", "dolor") : 2})

Table like

Tags for labels

Alternatively, you may specify the names in Tags.

m.select([Tag(1, name="one"), Tag(2, name="two")])  # returns 1

Options with labels

Enums

Alternatively, you may use an Enum.

class Color(Enum):
    RED = "red"
    GREEN = "green"
    BLUE = "blue"

m.select(Color)

Options from enum

Alternatively, you may use an Enum instance. (Which means the default value is already selected.)

class Color(Enum):
    RED = "red"
    GREEN = "green"
    BLUE = "blue"

m.select(Color.BLUE)

Options from enum

Alternatively, you may use an Enum instances list.

m.select([Color.GREEN, Color.BLUE])

Options from enum list

Further examples

See mininterface.select or SelectTag.options for further usage.

DataClass = TypeVar('DataClass')

Any dataclass. Or a pydantic model or attrs.

EnvClass = TypeVar('EnvClass', bound=DataClass)

Any dataclass. Its instance will be available through Mininterface.env after CLI parsing. Its fields or whole class might be annotated with tyro conf flags.

The following example turns down boolean flag conversion.

from dataclasses import dataclass
from mininterface import run
from tyro.conf import FlagConversionOff

@dataclass
class Env:
    my_bool: bool = False

m = run(FlagConversionOff[Env])
$ program.py --help
# --my-bool {True,False}  (default: False)

Whereas by default, both flags are generated:

m = run(Env)
$ program.py --help
# --my-bool, --no-my-bool (default: False)

FormDict = dict[Hashable, TypeVar('FormDictRecursiveValue', TagValue, Tag, 'Self')]

Nested dict that can have descriptions (through Tag) instead of plain values.

mininterface.interfaces.InterfaceType = Type[Mininterface] | InterfaceName | None

Either a class symbol or a shortcut string.