# 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):
        """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'

        def validate(self, obj, value):
            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 value
            self.error(obj, value)

        def from_string(self, s):
            if self.allow_none and s == 'None':
                return None
            if ':' not in s:
                raise ValueError('Require `ip:port`, got %r' % s)
            ip, port = s.split(':', 1)
            port = int(port)
            return (ip, port)