Defining new trait types#
To define a new trait type, subclass from TraitType
. You can define the
following things:
- class traitlets.MyTrait#
- info_text#
A short string describing what this trait should hold.
- default_value#
A default value, if one makes sense for this trait type. If there is no obvious default, don’t provide this.
- validate(obj, value)#
Check whether a given value is valid. If it is, it should return the value (coerced to the desired type, if necessary). If not, it should raise
TraitError
.TraitType.error()
is a convenient way to raise an descriptive error saying that the given value is not of the required type.obj
is the object to which the trait belongs.
For instance, here’s the definition of the TCPAddress
trait:
class TCPAddress(TraitType[G, S]):
"""A trait for an (ip, port) tuple.
This allows for both IPv4 IP addresses as well as hostnames.
"""
default_value = ("127.0.0.1", 0)
info_text = "an (ip, port) tuple"
if t.TYPE_CHECKING:
@t.overload
def __init__(
self: TCPAddress[tuple[str, int], tuple[str, int]],
default_value: bool | Sentinel = ...,
allow_none: Literal[False] = ...,
read_only: bool | None = ...,
help: str | None = ...,
config: t.Any = ...,
**kwargs: t.Any,
) -> None:
...
@t.overload
def __init__(
self: TCPAddress[tuple[str, int] | None, tuple[str, int] | None],
default_value: bool | None | Sentinel = ...,
allow_none: Literal[True] = ...,
read_only: bool | None = ...,
help: str | None = ...,
config: t.Any = ...,
**kwargs: t.Any,
) -> None:
...
def __init__(
self: TCPAddress[tuple[str, int] | None, tuple[str, int] | None]
| TCPAddress[tuple[str, int], tuple[str, int]],
default_value: bool | None | Sentinel = Undefined,
allow_none: Literal[True, False] = False,
read_only: bool | None = None,
help: str | None = None,
config: t.Any = None,
**kwargs: t.Any,
) -> None:
...
def validate(self, obj: t.Any, value: t.Any) -> G:
if isinstance(value, tuple):
if len(value) == 2:
if isinstance(value[0], str) and isinstance(value[1], int):
port = value[1]
if port >= 0 and port <= 65535:
return t.cast(G, value)
self.error(obj, value)
def from_string(self, s: str) -> G:
if self.allow_none and s == "None":
return t.cast(G, None)
if ":" not in s:
raise ValueError("Require `ip:port`, got %r" % s)
ip, port_str = s.split(":", 1)
port = int(port_str)
return t.cast(G, (ip, port))