1.. index:: validation, using traits 2 3.. _defining-traits-initialization-and-validation: 4 5============================================== 6Defining Traits: Initialization and Validation 7============================================== 8 9Using the Traits package in a Python program involves the following steps: 10 11.. index:: importing Traits names, traits.api; importing from 12 131. Import the names you need from the Traits package traits.api. 14 152. Define the traits you want to use. 16 17.. index:: HasTraits class 18 193. Define classes derived from HasTraits (or a subclass of HasTraits), with 20 attributes that use the traits you have defined. 21 22In practice, steps 2 and 3 are often combined by defining traits in-line 23in an attribute definition. This strategy is used in many examples in this 24guide. However, you can also define traits independently, and reuse the trait 25definitions across multiple classes and attributes (see 26:ref:`reusing-trait-definitions`). 27 28In order to use trait attributes in a class, the class must inherit from the 29HasTraits class in the Traits package (or from a subclass of HasTraits). The 30following example defines a class called Person that has a single trait 31attribute **weight**, which is initialized to 150.0 and can only take floating 32point values. 33 34.. index:: 35 single: examples; minimal 36 37:: 38 39 # minimal.py --- Minimal example of using traits. 40 41 from traits.api import HasTraits, Float 42 43 class Person(HasTraits): 44 weight = Float(150.0) 45 46.. index:: attribute definition 47 48In this example, the attribute named **weight** specifies that the class has a 49corresponding trait called **weight**. The value associated with the attribute 50**weight** (i.e., ``Float(150.0)``) specifies a predefined trait provided with 51the Traits package, which requires that values assigned be of the standard 52Python type **float**. The value 150.0 specifies the default value of the 53trait. 54 55The value associated with each class-level attribute determines the 56characteristics of the instance attribute identified by the attribute name. 57For example:: 58 59 >>> from minimal import Person 60 >>> # instantiate the class 61 >>> joe = Person() 62 >>> # Show the default value 63 >>> joe.weight 64 150.0 65 >>> # Assign new values 66 >>> joe.weight = 161.9 # OK to assign a float 67 >>> joe.weight = 162 # OK to assign an int 68 >>> joe.weight = 'average' # Error to assign a string 69 Traceback (most recent call last): 70 ... 71 traits.trait_errors.TraitError: The 'weight' trait of a Person instance 72 must be a float, but a value of 'average' <type 'str'> was specified. 73 74In this example, **joe** is an instance of the Person class defined in the 75previous example. The **joe** object has an instance attribute **weight**, 76whose initial value is the default value of the Person.weight trait (150.0), 77and whose assignment is governed by the Person.weight trait's validation 78rules. Assigning an integer to **weight** is acceptable because there is no 79loss of precision (but assigning a float to an Int trait would cause an error). 80 81The Traits package allows creation of a wide variety of trait types, ranging 82from very simple to very sophisticated. The following section presents some of 83the simpler, more commonly used forms. 84 85.. warning:: Unless otherwise stated as safe to do so, avoid naming 86 attributes with the prefix 'trait' or '_trait'. This avoids overshadowing 87 existing methods on HasTraits. 88 89 90A note about the Traits package structure 91----------------------------------------- 92 93We described above how trait type definitions and the :class:`~.HasTraits` 94class can be imported from the ``traits.api`` module. For example:: 95 96 from traits.api import Float, HasTraits, Int 97 98In fact, the :class:`HasTraits` class and various trait type classes are 99defined in other modules nested inside the Traits package structure, but 100they're re-imported to ``traits.api`` for user convenience. In general, 101everything you need should be available in either ``traits.api`` or one of the 102other ``*.api`` modules inside the package structure (for example, 103``traits.adaptation.api`` or ``traits.observation.api``). As a matter of best 104practices, you should import the things you need directly from one of these 105``*.api`` modules. If you discover that there's something that you need that's 106not available from one of these modules, please discuss with the Traits 107development team (for example, by opening an issue on the `Traits bug 108tracker`_). 109 110 111.. index:: predefined traits 112 113.. _predefined-traits: 114 115Predefined Traits 116----------------- 117The Traits package includes a large number of predefined traits for commonly 118used Python data types. In the simplest case, you can assign the trait name 119to an attribute of a class derived from HasTraits; any instances of the class 120will have that attribute initialized to the built-in default value for the 121trait. For example:: 122 123 account_balance = Float 124 125This statement defines an attribute whose value must be a floating point 126number, and whose initial value is 0.0 (the built-in default value for Floats). 127 128If you want to use an initial value other than the built-in default, you can 129pass it as an argument to the trait:: 130 131 account_balance = Float(10.0) 132 133Most predefined traits are callable, [2]_ and can accept a default value and 134possibly other arguments; all that are callable can also accept metadata as 135keyword arguments. (See :ref:`other-predefined-traits` for information on trait 136signatures, and see :ref:`trait-metadata` for information on metadata 137arguments.) 138 139.. index:: simple types 140 141.. _predefined-traits-for-simple-types: 142 143Predefined Traits for Simple Types 144`````````````````````````````````` 145There are two categories of predefined traits corresponding to Python simple 146types: those that coerce values, and those that cast values. These categories 147vary in the way that they handle assigned values that do not match the type 148explicitly defined for the trait. However, they are similar in terms of the 149Python types they correspond to, and their built-in default values, as listed 150in the following table. 151 152.. index:: 153 pair: types; casting 154 pair: types; coercing 155 pair: type; string 156.. index:: Boolean type, Bool trait, CBool trait, Complex trait, CComplex trait 157.. index:: Float trait, CFloat trait, Int trait, CInt trait 158.. index:: integer type, floating point number type, complex number type 159.. index:: Str trait, CStr trait, Bytes trait, CBytes trait 160 161.. _predefined-defaults-for-simple-types-table: 162 163.. rubric:: Predefined defaults for simple types 164 165============== ============= ====================== ====================== 166Coercing Trait Casting Trait Python Type Built-in Default Value 167============== ============= ====================== ====================== 168Bool CBool Boolean False 169Complex CComplex Complex number 0+0j 170Float CFloat Floating point number 0.0 171Int CInt Integer 0 172Str CStr String '' 173Bytes CBytes Bytes b'' 174============== ============= ====================== ====================== 175 176.. index:: 177 pair: types; coercing 178 179.. _trait-type-coercion: 180 181Trait Type Coercion 182::::::::::::::::::: 183For trait attributes defined using the predefined "coercing" 184traits, if a value is assigned to a trait attribute that is not of the type 185defined for the trait, but it can be coerced to the required type, then the 186coerced value is assigned to the attribute. If the value cannot be coerced to 187the required type, a TraitError exception is raised. Only widening coercions 188are allowed, to avoid any possible loss of precision. The following table 189lists traits that coerce values, and the types that each coerces. 190 191.. index:: 192 pair: types; coercing 193 194.. _type-coercions-permitted-for-coercing-traits-table: 195 196.. rubric:: Type coercions permitted for coercing traits 197 198============= =========================================== 199Trait Coercible Types 200============= =========================================== 201Complex Floating point number, integer 202Float Integer 203============= =========================================== 204 205.. index:: 206 pair: types; casting 207 208.. _trait-type-casting: 209 210Trait Type Casting 211:::::::::::::::::: 212For trait attributes defined using the predefined "casting" 213traits, if a value is assigned to a trait attribute that is not of the type 214defined for the trait, but it can be cast to the required type, then the cast 215value is assigned to the attribute. If the value cannot be cast to the required 216type, a TraitError exception is raised. Internally, casting is done using the 217Python built-in functions for type conversion: 218 219* bool() 220* complex() 221* float() 222* int() 223* str() 224* bytes() 225 226.. index:: 227 single: examples; coercing vs. casting 228 229The following example illustrates the difference between coercing traits and 230casting traits:: 231 232 >>> from traits.api import HasTraits, Float, CFloat 233 >>> class Person ( HasTraits ): 234 ... weight = Float 235 ... cweight = CFloat 236 ... 237 >>> bill = Person() 238 >>> bill.weight = 180 # OK, coerced to 180.0 239 >>> bill.cweight = 180 # OK, cast to float(180) 240 >>> bill.weight = '180' # Error, invalid coercion 241 Traceback (most recent call last): 242 ... 243 traits.trait_errors.TraitError: The 'weight' trait of a Person instance 244 must be a float, but a value of '180' <type 'str'> was specified. 245 >>> bill.cweight = '180' # OK, cast to float('180') 246 >>> print(bill.cweight) 247 180.0 248 249 250.. _other-predefined-traits: 251 252Other Predefined Traits 253``````````````````````` 254The Traits package provides a number of other predefined traits besides those 255for simple types, corresponding to other commonly used data types; these 256predefined traits are listed in the following table. Refer to the 257*Traits API Reference*, in the section for the module traits.traits, 258for details. Most can be used either as simple names, which use their built-in 259default values, or as callables, which can take additional arguments. If the 260trait cannot be used as a simple name, it is omitted from the Name column of 261the table. 262 263.. index:: Any(), Array(), Button(), Callable(), CArray(), Code() 264.. index:: CSet(), Constant(), Dict() 265.. index:: Directory(), Disallow, Either(), Enum() 266.. index:: Event(), Expression(), false, File() 267.. index:: Instance(), List(), Method(), Module() 268.. index:: Password(), Property(), Python() 269.. index:: PythonValue(), Range(), ReadOnly(), Regex() 270.. index:: Set() String(), This, 271.. index:: ToolbarButton(), true, Tuple(), Type() 272.. index:: undefined, UUID(), ValidatedTuple(), WeakRef() 273 274.. _predefined-traits-beyond-simple-types-table: 275 276.. rubric:: Predefined traits beyond simple types 277 278+------------------+----------------------------------------------------------+ 279| Name | Callable Signature | 280+==================+==========================================================+ 281| Any | Any( [*default_value* = None, \*, | 282| | *factory* = None, *args* = (), *kw* = {}, | 283| | \*\*\ *metadata* ) | 284+------------------+----------------------------------------------------------+ 285| Array | Array( [*dtype* = None, *shape* = None, *value* = None, | 286| | *typecode* = None, \*\*\ *metadata*] ) | 287+------------------+----------------------------------------------------------+ 288| ArrayOrNone | ArrayOrNone( [*dtype* = None, *shape* = None, | 289| | *value* = None, *typecode* = None, \*\*\ *metadata*] ) | 290+------------------+----------------------------------------------------------+ 291| Button | Button( [*label* = '', *image* = None, *style* = | 292| | 'button', *orientation* = 'vertical', *width_padding* = | 293| | 7, *height_padding* = 5, \*\*\ *metadata*] ) | 294+------------------+----------------------------------------------------------+ 295| Callable | Callable( [*value* = None, \*\*\ *metadata*] ) | 296+------------------+----------------------------------------------------------+ 297| CArray | CArray( [*dtype* = None, *shape* = None, *value* = None, | 298| | *typecode* = None, \*\*\ *metadata*] ) | 299+------------------+----------------------------------------------------------+ 300| Code | Code( [*value* = '', *minlen* = 0, | 301| | *maxlen* = sys.maxsize, *regex* = '', | 302| | \*\*\ *metadata*] ) | 303+------------------+----------------------------------------------------------+ 304| CSet | CSet( [*trait* = None, *value* = None, *items* = True, | 305| | \*\*\ *metadata*] ) | 306+------------------+----------------------------------------------------------+ 307| Constant | Constant( *value*\ [, \*\*\ *metadata*] ) | 308+------------------+----------------------------------------------------------+ 309| Dict | Dict( [*key_trait* = None, *value_trait* = None, | 310| | *value* = None, *items* = True, \*\*\ *metadata*] ) | 311+------------------+----------------------------------------------------------+ 312| Directory | Directory( [*value* = '', *auto_set* = False, *entries* =| 313| | 10, *exists* = False, \*\*\ *metadata*] ) | 314+------------------+----------------------------------------------------------+ 315| Disallow | n/a | 316+------------------+----------------------------------------------------------+ 317| Either | Either( *val1*\ [, *val2*, ..., *valN*, | 318| | \*\*\ *metadata*] ) | 319+------------------+----------------------------------------------------------+ 320| Enum | Enum( *values*\ [, \*\*\ *metadata*] ) | 321+------------------+----------------------------------------------------------+ 322| Event | Event( [*trait* = None, \*\*\ *metadata*] ) | 323+------------------+----------------------------------------------------------+ 324| Expression | Expression( [*value* = '0', \*\*\ *metadata*] ) | 325+------------------+----------------------------------------------------------+ 326| File | File( [*value* = '', *filter* = None, *auto_set* = False,| 327| | *entries* = 10, *exists* = False, \*\*\ *metadata* ] ) | 328+------------------+----------------------------------------------------------+ 329| Function [3]_ | Function( [*value* = None, \*\*\ *metadata*] ) | 330+------------------+----------------------------------------------------------+ 331| generic_trait | n/a | 332+------------------+----------------------------------------------------------+ 333| HTML | HTML( [*value* = '', *minlen* = 0, | 334| | *maxlen* = sys.maxsize, *regex* = '', | 335| | \*\*\ *metadata* ] ) | 336+------------------+----------------------------------------------------------+ 337| Instance | Instance( [*klass* = None, *factory* = None, *args* = | 338| | None, *kw* = None, *allow_none* = True, *adapt* = None, | 339| | *module* = None, \*\*\ *metadata*] ) | 340+------------------+----------------------------------------------------------+ 341| List | List( [*trait* = None, *value* = None, *minlen* = 0, | 342| | *maxlen* = sys.maxsize, *items* = True, | 343| | \*\*\ *metadata*] ) | 344+------------------+----------------------------------------------------------+ 345| Map | Map( *map*\ [, \*\*\ *metadata*] ) | 346+------------------+----------------------------------------------------------+ 347| Method [3]_ | Method ([\*\*\ *metadata*] ) | 348+------------------+----------------------------------------------------------+ 349| Module | Module ( [\*\*\ *metadata*] ) | 350+------------------+----------------------------------------------------------+ 351| Password | Password( [*value* = '', *minlen* = 0, *maxlen* = | 352| | sys.maxsize, *regex* = '', \*\*\ *metadata*] ) | 353+------------------+----------------------------------------------------------+ 354| PrefixList | PrefixList( *values*\ [, \*\*\ *metadata*] ) | 355+------------------+----------------------------------------------------------+ 356| PrefixMap | PrefixMap( *map*\ [, \*\*\ *metadata*] ) | 357+------------------+----------------------------------------------------------+ 358| Property | Property( [*fget* = None, *fset* = None, *fvalidate* = | 359| | None, *force* = False, *handler* = None, *trait* = None, | 360| | \*\*\ *metadata*] ) | 361| | | 362| | See :ref:`property-traits`, for details. | 363+------------------+----------------------------------------------------------+ 364| Python | Python ( [*value* = None, \*\*\ *metadata*] ) | 365+------------------+----------------------------------------------------------+ 366| PythonValue | PythonValue( [*value* = None, \*\*\ *metadata*] ) | 367+------------------+----------------------------------------------------------+ 368| Range | Range( [*low* = None, *high* = None, *value* = None, | 369| | *exclude_low* = False, *exclude_high* = False, | 370| | \*\ *metadata*] ) | 371+------------------+----------------------------------------------------------+ 372| ReadOnly | ReadOnly( [*value* = Undefined, \*\*\ *metadata*] ) | 373+------------------+----------------------------------------------------------+ 374| Regex | Regex( [*value* = '', *regex* = '.\*', \*\*\ *metadata*])| 375+------------------+----------------------------------------------------------+ 376| self | n/a | 377+------------------+----------------------------------------------------------+ 378| Set | Set( [*trait* = None, *value* = None, *items* = True, | 379| | \*\*\ *metadata*] ) | 380+------------------+----------------------------------------------------------+ 381| String | String( [*value* = '', *minlen* = 0, *maxlen* = | 382| | sys.maxsize, *regex* = '', \*\*\ *metadata*] ) | 383+------------------+----------------------------------------------------------+ 384| Subclass | Subclass( [*value* = None, *klass* = None, *allow_none* =| 385| | True, \*\*\ *metadata*] ) | 386+------------------+----------------------------------------------------------+ 387| This | n/a | 388+------------------+----------------------------------------------------------+ 389| ToolbarButton | ToolbarButton( [*label* = '', *image* = None, *style* = | 390| | 'toolbar', *orientation* = 'vertical', *width_padding* = | 391| | 2, *height_padding* = 2, \*\*\ *metadata*] ) | 392+------------------+----------------------------------------------------------+ 393| Tuple | Tuple( [\*\ *traits*, \*\*\ *metadata*] ) | 394+------------------+----------------------------------------------------------+ 395| Type | Type( [*value* = None, *klass* = None, *allow_none* = | 396| | True, \*\*\ *metadata*] ) | 397+------------------+----------------------------------------------------------+ 398| Union | Union( *val1*\ [, *val2*, ..., *valN*, | 399| | \*\*\ *metadata*] ) | 400+------------------+----------------------------------------------------------+ 401| UUID [4]_ | UUID( [\*\*\ *metadata*] ) | 402+------------------+----------------------------------------------------------+ 403| ValidatedTuple | ValidatedTuple( [\*\ *traits*, *fvalidate* = None, | 404| | *fvalidate_info* = '' , \*\*\ *metadata*] ) | 405+------------------+----------------------------------------------------------+ 406| WeakRef | WeakRef( [*klass* = 'traits.HasTraits', | 407| | *allow_none* = False, *adapt* = 'yes', \*\*\ *metadata*])| 408+------------------+----------------------------------------------------------+ 409 410.. index:: Instance trait 411 412.. _instance: 413 414Instance 415:::::::: 416One of the most fundamental and useful predefined trait types is 417:class:`~.Instance`. Instance trait values are an instance of a particular class 418or its subclasses, as specified by the **klass** argument. **klass** can be 419either an instance of a class or a class itself (note this applies to all python 420classes, not necessarily just :class:`~.HasTraits` subclasses). However, one should 421typically provide the type or interface they want an instance of, instead of 422providing an instance of a class. 423 424If **klass** is an instance or if it is a class and **args** and **kw** are not 425specified, the default value is ``None``. Otherwise, the default value is 426obtained by calling the callable **factory** argument (or **klass** if 427**factory** is None) with **args** and **kw**. Further, there is the 428**allow_none** argument which dictates whether the trait can take on a value of 429``None``. However, this does not include the default value for the trait. For 430example:: 431 432 # instance_trait_defaults.py --- Example of Instance trait default values 433 from traits.api import HasTraits, Instance 434 435 class Parent(HasTraits): 436 pass 437 438 class Child(HasTraits): 439 # default value is None 440 father = Instance(Parent) 441 # default value is still None, but None can not be assigned 442 grandfather = Instance(Parent, allow_none=False) 443 # default value is Parent() 444 mother = Instance(Parent, args=()) 445 446In the last case, the default ``Parent`` instance is not immediately 447created, but rather is lazily instantiated when the trait is first accessed. 448The default ``Parent`` will also be instantiated if the trait is assigned to 449and there is a change handler defined on the trait (to detect changes from the 450default value). For more details on change handlers and trait notification see 451:ref:`observe-notification`. 452 453Somewhat surprisingly, ``mother = Instance(Parent, ())`` will also yield a 454default value of ``Parent()``, even though in that case it is **factory** that 455is ``()`` not **args**. This is a result of implementation details, however 456the recommended way of writing this code is to explicitly pass **args** by 457keyword like so ``mother = Instance(Parent, args=())``. Another common mistake 458is passing in another trait type to Instance. For example, 459``some_trait = Instance(Int)``. This will likely lead to unexpected behavior 460and potential errors. Instead simply do ``some_trait = Int()``. 461 462.. index:: This trait, self trait 463 464.. _this-and-self: 465 466This and self 467::::::::::::: 468A couple of predefined traits that merit special explanation are This and 469**self**. They are intended for attributes whose values must be of the same 470class (or a subclass) as the enclosing class. The default value of This is 471None; the default value of **self** is the object containing the attribute. 472 473.. index:: 474 pair: This trait; examples 475 476The following is an example of using This:: 477 478 # this.py --- Example of This predefined trait 479 480 from traits.api import HasTraits, This 481 482 class Employee(HasTraits): 483 manager = This 484 485This example defines an Employee class, which has a **manager** trait 486attribute, which accepts only other Employee instances as its value. It might 487be more intuitive to write the following:: 488 489 # bad_self_ref.py --- Non-working example with self- referencing 490 # class definition 491 from traits.api import HasTraits, Instance 492 class Employee(HasTraits): 493 manager = Instance(Employee) 494 495However, the Employee class is not fully defined at the time that the 496**manager** attribute is defined. Handling this common design pattern is the 497main reason for providing the This trait. 498 499Note that if a trait attribute is defined using This on one class and is 500referenced on an instance of a subclass, the This trait verifies values based 501on the class on which it was defined. For example:: 502 503 >>> from traits.api import HasTraits, This 504 >>> class Employee(HasTraits): 505 ... manager = This 506 ... 507 >>> class Executive(Employee): 508 ... pass 509 ... 510 >>> fred = Employee() 511 >>> mary = Executive() 512 >>> # The following is OK, because fred's manager can be an 513 >>> # instance of Employee or any subclass. 514 >>> fred.manager = mary 515 >>> # This is also OK, because mary's manager can be an Employee 516 >>> mary.manager = fred 517 518.. index:: Map trait 519 520.. _map: 521 522Map 523::: 524The map trait ensures that the value assigned to a trait attribute 525is a key of a specified dictionary, and also assigns the dictionary 526value corresponding to that key to a shadow attribute. 527 528.. index:: 529 pair: Map trait; examples 530 531The following is an example of using Map:: 532 533 # map.py --- Example of Map predefined trait 534 535 from traits.api import HasTraits, Map 536 537 class Person(HasTraits): 538 married = Map({'yes': 1, 'no': 0 }, default_value="yes") 539 540This example defines a Person class which has a **married** trait 541attribute which accepts values "yes" and "no". The default value 542is set to "yes". The name of the shadow attribute is the name of 543the Map attribute followed by an underscore, i.e ``married_`` 544Instantiating the class produces the following:: 545 546 >>> from traits.api import HasTraits, Map 547 >>> bob = Person() 548 >>> print(bob.married) 549 yes 550 >>> print(bob.married_) 551 1 552 553.. index:: PrefixMap trait 554 555.. _prefixmap: 556 557PrefixMap 558::::::::: 559Like Map, PrefixMap is created using a dictionary, but in this 560case, the keys of the dictionary must be strings. Like PrefixList, 561a string *v* is a valid value for the trait attribute if it is a prefix of 562one and only one key *k* in the dictionary. The actual values assigned to 563the trait attribute is *k*, and its corresponding mapped attribute is map[*k*]. 564 565.. index:: 566 pair: PrefixMap trait; examples 567 568The following is an example of using PrefixMap:: 569 570 # prefixmap.py --- Example of PrefixMap predefined trait 571 572 from traits.api import HasTraits, PrefixMap 573 574 class Person(HasTraits): 575 married = PrefixMap({'yes': 1, 'no': 0 }, default_value="yes") 576 577This example defines a Person class which has a **married** trait 578attribute which accepts values "yes" and "no" or any unique 579prefix. The default value is set to "yes". The name of the shadow attribute 580is the name of the PrefixMap attribute followed by an underscore, i.e ``married_`` 581Instantiating the class produces the following:: 582 583 >>> bob = Person() 584 >>> print(bob.married) 585 yes 586 >>> print(bob.married_) 587 1 588 >>> bob.married = "n" # Setting a prefix 589 >>> print(bob.married) 590 no 591 >>> print(bob.married_) 592 0 593 594.. index:: PrefixList trait 595 596.. _prefixlist: 597 598PrefixList 599:::::::::: 600Ensures that a value assigned to the attribute is a member of a list of 601specified string values, or is a unique prefix of one of those values. 602The values that can be assigned to a trait attribute of type PrefixList 603is the set of all strings supplied to the PrefixList constructor, as well 604as any unique prefix of those strings. The actual value assigned to the 605trait is limited to the set of complete strings assigned to the 606PrefixList constructor. 607 608.. index:: 609 pair: PrefixList trait; examples 610 611The following is an example of using PrefixList:: 612 613 # prefixlist.py --- Example of PrefixList predefined trait 614 615 from traits.api import HasTraits, PrefixList 616 617 class Person(HasTraits): 618 married = PrefixList(["yes", "no"]) 619 620This example defines a Person class which has a **married** trait 621attribute which accepts values "yes" and "no" or any unique 622prefix. Instantiating the class produces the following:: 623 624 >>> bob = Person() 625 >>> print(bob.married) 626 yes 627 >>> bob.married = "n" # Setting a prefix 628 >>> print(bob.married) 629 no 630 631.. index:: Either trait 632 633.. _either: 634 635Either 636:::::: 637Another predefined trait that merits special explanation is Either. The 638Either trait is intended for attributes that may take a value of more than 639a single trait type, including None. The default value of Either is None, even 640if None is not one of the types the user explicitly defines in the constructor, 641but a different default value can be provided using the ``default`` argument. 642 643.. index:: 644 pair: Either trait; examples 645 646The following is an example of using Either:: 647 648 # either.py --- Example of Either predefined trait 649 650 from traits.api import HasTraits, Either, Str 651 652 class Employee(HasTraits): 653 manager_name = Either(Str, None) 654 655This example defines an Employee class, which has a **manager_name** trait 656attribute, which accepts either an Str instance or None as its value, and 657will raise a TraitError if a value of any other type is assigned. For example:: 658 659 >>> from traits.api import HasTraits, Either, Str 660 >>> class Employee(HasTraits): 661 ... manager_name = Either(Str, None) 662 ... 663 >>> steven = Employee(manager_name="Jenni") 664 >>> # Here steven's manager is named "Jenni" 665 >>> steven.manager_name 666 'Jenni' 667 >>> eric = Employee(manager_name=None) 668 >>> # Eric is the boss, so he has no manager. 669 >>> eric.manager_name is None 670 True 671 >>> # Assigning a value that is neither a string nor None will fail. 672 >>> steven.manager_name = 5 673 traits.trait_errors.TraitError: The 'manager_name' trait of an Employee instance must be a string or None, but a value of 5 <type 'int'> was specified. 674 675.. index:: Union trait 676 677.. _union: 678 679Union 680:::::: 681The Union trait accepts a value that is considered valid by at least one 682of the traits in its definition. It is a simpler and therefore less error-prone 683alternative to the `Either` trait, which allows more complex constructs and 684may sometimes exhibit mysterious validation behaviour. The Union trait however, 685validates the value assigned to it against each of the traits in its definition 686in the order they are defined. Union only accepts trait types or trait type 687instances or None in its definition. Prefer to use Union over `Either` to 688remain future proof. 689 690.. index:: 691 pair: Union trait; examples 692 693The following is an example of using Union:: 694 695 # union.py --- Example of Union predefined trait 696 697 from traits.api import HasTraits, Union, Int, Float, Instance 698 699 class Salary(HasTraits): 700 basic = Float 701 bonus = Float 702 703 class Employee(HasTraits): 704 manager_name = Union(Str, None) 705 pay = Union(Instance(Salary), Float) 706 707This example defines an Employee class, which has a **manager_name** trait 708attribute, which accepts either an Str instance or None as its value, a 709**salary** trait that accepts an instance of Salary or Float and will raise a 710TraitError if a value of any other type is assigned. For example:: 711 712 >>> from traits.api import HasTraits, Either, Str 713 >>> class Employee(HasTraits): 714 ... manager_name = Union(Str, None) 715 ... 716 >>> steven = Employee(manager_name="Jenni") 717 >>> # Here steven's manager is named "Jenni" 718 >>> # Assigning a value that is neither a string nor None will fail. 719 >>> steven.manager_name = 5 720 traits.trait_errors.TraitError: The 'manager_name' trait of an Employee instance must be a string or a None type, but a value of 5 <class 'int'> was specified. 721 722The following example illustrates the difference between `Either` and `Union`:: 723 724 >>> from traits.api import HasTraits, Either, Union, Str 725 >>> class IntegerClass(HasTraits): 726 ... primes = Either([2], None, {'3':6}, 5, 7, 11) 727 ... 728 >>> i = IntegerClass(primes=2) # Acceptable value, no error 729 >>> i = IntegerClass(primes=4) 730 traits.trait_errors.TraitError: The 'primes' trait of an IntegerClass instance must be 2 or None or 5 or 7 or 11 or '3', but a value of 4 <class 'int'> was specified. 731 >>> 732 >>> # But Union does not allow such declarations. 733 >>> class IntegerClass(HasTraits): 734 ... primes = Union([2], None, {'3':6}, 5, 7, 11) 735 ValueError: Union trait declaration expects a trait type or an instance of trait type or None, but got [2] instead 736 737 738.. _migration_either_to_union: 739 740.. rubric:: Migration from Either to Union 741 742* Static default values are defined on Union via the **default_value** 743 attribute, whereas Either uses the **default** attribute. The naming of 744 **default_value** is consistent with other trait types. 745 For example:: 746 747 Either(None, Str(), default="unknown") 748 749 would be changed to:: 750 751 Union(None, Str(), default_value="unknown") 752 753* If a default value is not defined, Union uses the default value from the 754 first trait in its definition, whereas Either uses None. 755 756 For example:: 757 758 Either(Int(), Float()) 759 760 has a default value of None. However None is not one of the allowed values. 761 If the trait is later set to None from a non-None value, a validation error 762 will occur. 763 764 If the trait definition is changed to:: 765 766 Union(Int(), Float()) 767 768 Then the default value will be 0, which is the default value of the first 769 trait. 770 771 To keep None as the default, use None as the first item:: 772 773 Union(None, Int(), Float()) 774 775 With this, None also becomes one of the allowed values. 776 777.. index:: multiple values, defining trait with 778 779.. _list-of-possibl-values: 780 781List of Possible Values 782::::::::::::::::::::::: 783You can define a trait whose possible values include disparate types. To do 784this, use the predefined Enum trait, and pass it a list of all possible values. 785The values must all be of simple Python data types, such as strings, integers, 786and floats, but they do not have to be all of the same type. This list of 787values can be a typical parameter list, an explicit (bracketed) list, or a 788variable whose type is list. The first item in the list is used as the default 789value. 790 791.. index:: examples; list of values 792 793A trait defined in this fashion can accept only values that are contained in 794the list of permitted values. The default value is the first value specified; 795it is also a valid value for assignment. 796:: 797 798 >>> from traits.api import Enum, HasTraits, Str 799 >>> class InventoryItem(HasTraits): 800 ... name = Str # String value, default is '' 801 ... stock = Enum(None, 0, 1, 2, 3, 'many') 802 ... # Enumerated list, default value is 803 ... #'None' 804 ... 805 >>> hats = InventoryItem() 806 >>> hats.name = 'Stetson' 807 808 >>> print('%s: %s' % (hats.name, hats.stock)) 809 Stetson: None 810 811 >>> hats.stock = 2 # OK 812 >>> hats.stock = 'many' # OK 813 >>> hats.stock = 4 # Error, value is not in \ 814 >>> # permitted list 815 Traceback (most recent call last): 816 ... 817 traits.trait_errors.TraitError: The 'stock' trait of an InventoryItem 818 instance must be None or 0 or 1 or 2 or 3 or 'many', but a value of 4 819 <type 'int'> was specified. 820 821 822This defines an :py:class:`InventoryItem` class, with two trait attributes, 823**name**, and **stock**. The name attribute is simply a string. The **stock** 824attribute has an initial value of None, and can be assigned the values None, 0, 8251, 2, 3, and 'many'. The example then creates an instance of the InventoryItem 826class named **hats**, and assigns values to its attributes. 827 828When the list of possible values can change during the lifetime of the object, 829one can specify **another trait** that holds the list of possible values:: 830 831 >>> from traits.api import Enum, HasTraits, List 832 >>> class InventoryItem(HasTraits): 833 ... possible_stock_states = List([None, 0, 1, 2, 3, 'many']) 834 ... stock = Enum(0, values="possible_stock_states") 835 ... # Enumerated list, default value is 0. The list of 836 ... # allowed values is whatever possible_stock_states holds 837 ... 838 839 >>> hats = InventoryItem() 840 >>> hats.stock 841 0 842 >>> hats.stock = 2 # OK 843 >>> hats.stock = 4 # TraitError like above 844 Traceback (most recent call last): 845 ... 846 traits.trait_errors.TraitError: The 'stock' trait of an InventoryItem 847 instance must be None or 0 or 1 or 2 or 3 or 'many', but a value of 4 848 <type 'int'> was specified. 849 850 >>> hats.possible_stock_states.append(4) # Add 4 to list of allowed values 851 >>> hats.stock = 4 # OK 852 853 854.. index:: metadata attributes; on traits 855 856.. _trait-metadata: 857 858Trait Metadata 859-------------- 860Trait objects can contain metadata attributes, which fall into three categories: 861 862* Internal attributes, which you can query but not set. 863* Recognized attributes, which you can set to determine the behavior of the 864 trait. 865* Arbitrary attributes, which you can use for your own purposes. 866 867You can specify values for recognized or arbitrary metadata attributes by 868passing them as keyword arguments to callable traits. The value of each 869keyword argument becomes bound to the resulting trait object as the value 870of an attribute having the same name as the keyword. 871 872.. index:: metadata attributes; internal 873 874.. _internal-metadata-attributes: 875 876Internal Metadata Attributes 877```````````````````````````` 878The following metadata attributes are used internally by the Traits package, 879and can be queried: 880 881.. index:: array metadata attribute, default metadata attribute 882.. index:: default_kind metadata attribute, delegate; metadata attribute 883.. index:: inner_traits metadata attribute, parent metadata attribute 884.. index:: prefix metadata attribute, trait_type metadata attribute 885.. index:: type metadata attribute 886 887* **array**: Indicates whether the trait is an array. 888* **default**: Returns the default value for the trait, if known; otherwise it 889 returns Undefined. 890* **default_kind**: Returns a string describing the type of value returned by 891 the default attribute for the trait. The possible values are: 892 893 * ``value``: The default attribute returns the actual default value. 894 * ``list``: A copy of the list default value. 895 * ``dict``: A copy of the dictionary default value. 896 * ``self``: The default value is the object the trait is bound to; the 897 **default** attribute returns Undefined. 898 * ``factory``: The default value is created by calling a factory; the 899 **default** attribute returns Undefined. 900 * ``method``: The default value is created by calling a method on the object 901 the trait is bound to; the **default** attribute returns Undefined. 902 903* **delegate**: The name of the attribute on this object that references the 904 object that this object delegates to. 905* **inner_traits**: Returns a tuple containing the "inner" traits 906 for the trait. For most traits, this is empty, but for List and Dict traits, 907 it contains the traits that define the items in the list or the keys and 908 values in the dictionary. 909* **parent**: The trait from which this one is derived. 910* **prefix**: A prefix or substitution applied to the delegate attribute. 911 See :ref:`deferring-traits` for details. 912* **trait_type**: Returns the type of the trait, which is typically a handler 913 derived from TraitType. 914* **type**: One of the following, depending on the nature of the trait: 915 916 * ``constant`` 917 * ``delegate`` 918 * ``event`` 919 * ``property`` 920 * ``trait`` 921 922.. index:: recognized metadata attributes, metadata attributes; recognized 923 924.. _recognized-metadata-attributes: 925 926Recognized Metadata Attributes 927`````````````````````````````` 928The following metadata attributes are not predefined, but are recognized by 929HasTraits objects: 930 931.. index:: desc metadata attribute, editor metadata attribute 932.. index:: label; metadata attribute, comparison_mode metadata attribute 933.. index:: transient metadata attribute 934 935* **desc**: A string describing the intended meaning of the trait. It is used 936 in exception messages and fly-over help in user interface trait editors. 937* **editor**: Specifies an instance of a subclass of TraitEditor to use when 938 creating a user interface editor for the trait. Refer to the 939 `TraitsUI User Manual 940 <http://docs.enthought.com/traitsui/traitsui_user_manual/index.html>`_ 941 for more information on trait editors. 942* **label**: A string providing a human-readable name for the trait. It is 943 used to label trait attribute values in user interface trait editors. 944* **comparison_mode**: Indicates when trait change notifications should be 945 generated based upon the result of comparing the old and new values of a 946 trait assignment. This should be a member of the 947 :class:`~traits.constants.ComparisonMode` enumeration class. 948* **transient**: A Boolean indicating that the trait value is not persisted 949 when the object containing it is persisted. The default value for most 950 predefined traits is False (the value will be persisted if its container is). 951 You can set it to True for traits whose values you know you do not want to 952 persist. Do not set it to True on traits where it is set internally to 953 False, as doing so is likely to create unintended consequences. See 954 :ref:`persistence` for more information. 955 956Other metadata attributes may be recognized by specific predefined traits. 957 958.. index:: metadata attributes; accessing 959 960.. _accessing-metadata-attributes: 961 962Accessing Metadata Attributes 963````````````````````````````` 964.. index:: 965 pair: examples; metadata attributes 966 967Here is an example of setting trait metadata using keyword arguments:: 968 969 # keywords.py --- Example of trait keywords 970 from traits.api import HasTraits, Str 971 972 class Person(HasTraits): 973 first_name = Str('', 974 desc='first or personal name', 975 label='First Name') 976 last_name = Str('', 977 desc='last or family name', 978 label='Last Name') 979 980In this example, in a user interface editor for a Person object, the labels 981"First Name" and "Last Name" would be used for entry 982fields corresponding to the **first_name** and **last_name** trait attributes. 983If the user interface editor supports rollover tips, then the **first_name** 984field would display "first or personal name" when the user moves 985the mouse over it; the last_name field would display "last or family 986name" when moused over. 987 988To get the value of a trait metadata attribute, you can use the trait() method 989on a HasTraits object to get a reference to a specific trait, and then access 990the metadata attribute:: 991 992 # metadata.py --- Example of accessing trait metadata attributes 993 from traits.api import HasTraits, Int, List, Float, Str, \ 994 Instance, Any, TraitType 995 996 class Foo( HasTraits ): pass 997 998 class Test( HasTraits ): 999 i = Int(99) 1000 lf = List(Float) 1001 foo = Instance( Foo, () ) 1002 any = Any( "123" ) 1003 1004 t = Test() 1005 1006 print(t.trait( 'i' ).default) # 99 1007 print(t.trait( 'i' ).default_kind) # value 1008 print(t.trait( 'i' ).inner_traits) # () 1009 print(t.trait( 'i' ).is_trait_type( Int )) # True 1010 print(t.trait( 'i' ).is_trait_type( Float )) # False 1011 1012 print(t.trait( 'lf' ).default) # [] 1013 print(t.trait( 'lf' ).default_kind) # list 1014 print(t.trait( 'lf' ).inner_traits) 1015 # (<traits.traits.CTrait object at 0x01B24138>,) 1016 print(t.trait( 'lf' ).is_trait_type( List )) # True 1017 print(t.trait( 'lf' ).is_trait_type( TraitType )) # True 1018 print(t.trait( 'lf' ).is_trait_type( Float )) # False 1019 print(t.trait( 'lf' ).inner_traits[0].is_trait_type( Float )) # True 1020 1021 print(t.trait( 'foo' ).default) # <undefined> 1022 print(t.trait( 'foo' ).default_kind) # factory 1023 print(t.trait( 'foo' ).inner_traits) # () 1024 print(t.trait( 'foo' ).is_trait_type( Instance )) # True 1025 print(t.trait( 'foo' ).is_trait_type( List )) # False 1026 1027 print(t.trait( 'any' ).default) # 123 1028 print(t.trait( 'any' ).default_kind) # value 1029 print(t.trait( 'any' ).inner_traits) # () 1030 print(t.trait( 'any' ).is_trait_type( Any )) # True 1031 print(t.trait( 'any' ).is_trait_type( Str )) # False 1032 1033.. rubric:: Footnotes 1034.. [2] Most callable predefined traits are classes, but a few are functions. 1035 The distinction does not make a difference unless you are trying to 1036 extend an existing predefined trait. See the *Traits API Reference* for 1037 details on particular traits, and see Chapter 5 for details on extending 1038 existing traits. 1039.. [3] The Function and Method trait types are now deprecated. See |Function|, 1040 |Method| 1041.. [4] Available in Python 2.5. 1042 1043.. 1044 external urls 1045 1046.. _Traits bug tracker: https://github.com/enthought/traits/issues 1047 1048.. 1049 # substitutions 1050 1051.. |Function| replace:: :class:`~traits.trait_types.Function` 1052.. |Method| replace:: :class:`~traits.trait_types.Method` 1053