A trait type representing a Union type.
| 2400 | |
| 2401 | |
| 2402 | class Union(TraitType[t.Any, t.Any]): |
| 2403 | """A trait type representing a Union type.""" |
| 2404 | |
| 2405 | def __init__(self, trait_types: t.Any, **kwargs: t.Any) -> None: |
| 2406 | """Construct a Union trait. |
| 2407 | |
| 2408 | This trait allows values that are allowed by at least one of the |
| 2409 | specified trait types. A Union traitlet cannot have metadata on |
| 2410 | its own, besides the metadata of the listed types. |
| 2411 | |
| 2412 | Parameters |
| 2413 | ---------- |
| 2414 | trait_types : sequence |
| 2415 | The list of trait types of length at least 1. |
| 2416 | **kwargs |
| 2417 | Extra kwargs passed to `TraitType` |
| 2418 | |
| 2419 | Notes |
| 2420 | ----- |
| 2421 | Union([Float(), Bool(), Int()]) attempts to validate the provided values |
| 2422 | with the validation function of Float, then Bool, and finally Int. |
| 2423 | |
| 2424 | Parsing from string is ambiguous for container types which accept other |
| 2425 | collection-like literals (e.g. List accepting both `[]` and `()` |
| 2426 | precludes Union from ever parsing ``Union([List(), Tuple()])`` as a tuple; |
| 2427 | you can modify behaviour of too permissive container traits by overriding |
| 2428 | ``_literal_from_string_pairs`` in subclasses. |
| 2429 | Similarly, parsing unions of numeric types is only unambiguous if |
| 2430 | types are provided in order of increasing permissiveness, e.g. |
| 2431 | ``Union([Int(), Float()])`` (since floats accept integer-looking values). |
| 2432 | """ |
| 2433 | self.trait_types = list(trait_types) |
| 2434 | self.info_text = " or ".join([tt.info() for tt in self.trait_types]) |
| 2435 | super().__init__(**kwargs) |
| 2436 | |
| 2437 | def default(self, obj: t.Any = None) -> t.Any: |
| 2438 | default = super().default(obj) |
| 2439 | for trait in self.trait_types: |
| 2440 | if default is Undefined: |
| 2441 | default = trait.default(obj) |
| 2442 | else: |
| 2443 | break |
| 2444 | return default |
| 2445 | |
| 2446 | def class_init(self, cls: type[HasTraits], name: str | None) -> None: |
| 2447 | for trait_type in reversed(self.trait_types): |
| 2448 | trait_type.class_init(cls, None) |
| 2449 | super().class_init(cls, name) |
| 2450 | |
| 2451 | def subclass_init(self, cls: type[t.Any]) -> None: |
| 2452 | for trait_type in reversed(self.trait_types): |
| 2453 | trait_type.subclass_init(cls) |
| 2454 | # explicitly not calling super().subclass_init(cls) |
| 2455 | # to opt out of instance_init |
| 2456 | |
| 2457 | def validate(self, obj: t.Any, value: t.Any) -> t.Any: |
| 2458 | with obj.cross_validation_lock: |
| 2459 | for trait_type in self.trait_types: |
no outgoing calls
searching dependent graphs…