1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
# --------------------------------------------------------------------------------------
# Copyright (c) 2013-2025, Nucleic Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file LICENSE, distributed with this software.
# --------------------------------------------------------------------------------------
from typing import Tuple as TTuple
from .catom import DefaultValue, Member, Validate
from .instance import Instance
from .typing_utils import extract_types, is_optional
class Tuple(Member):
"""A member which allows tuple values.
If item validation is used, then assignment will create a copy of
the original tuple before validating the items, since validation
may change the item values.
"""
__slots__ = ("item",)
def __init__(self, item=None, default=()):
"""Initialize a Tuple.
Parameters
----------
item : Member, type, or tuple of types, optional
A member to use for validating the types of items allowed in
the tuple. This can also be a type object or a tuple of types,
in which case it will be wrapped with an Instance member. If
this is not given, no item validation is performed.
default : tuple, optional
The default tuple of values.
"""
if item is not None and not isinstance(item, Member):
opt, types = is_optional(extract_types(item))
item = Instance(types, optional=opt)
self.item = item
self.set_default_value_mode(DefaultValue.Static, default)
self.set_validate_mode(Validate.Tuple, item)
def set_name(self, name):
"""Set the name of the member.
This method ensures that the item member name is also updated.
"""
super(Tuple, self).set_name(name)
if self.item is not None:
self.item.set_name(name + "|item")
def set_index(self, index):
"""Assign the index to this member.
This method ensures that the item member index is also updated.
"""
super(Tuple, self).set_index(index)
if self.item is not None:
self.item.set_index(index)
def clone(self):
"""Create a clone of the tuple.
This will clone the internal tuple item if one is in use.
"""
clone = super(Tuple, self).clone()
item = self.item
if item is not None:
clone.item = item_clone = item.clone()
mode, _ctxt = self.validate_mode
clone.set_validate_mode(mode, item_clone)
else:
clone.item = None
return clone
class FixedTuple(Member):
"""A member which allows tuple values with a fixed number of items.
Items are always validated and can be of different types.
Assignment will create a copy of the original tuple before validating the
items, since validation may change the item values.
"""
#: Members used to validate each element of the tuple.
items: TTuple[Member, ...]
__slots__ = ("items",)
def __init__(self, *items, default=None):
"""Initialize a Tuple.
Parameters
----------
items : Iterable[Member | type | tuple[type, ...]]
A member to use for validating the types of items allowed in
the tuple. This can also be a type object or a tuple of types,
in which case it will be wrapped with an Instance member.
default : tuple, optional
The default tuple of values.
"""
mitems = []
for i in items:
if not isinstance(i, Member):
opt, types = is_optional(extract_types(i))
i = Instance(types, optional=opt)
mitems.append(i)
self.items = mitems
if default is None:
self.set_default_value_mode(DefaultValue.NonOptional, None)
else:
self.set_default_value_mode(DefaultValue.Static, default)
self.set_validate_mode(Validate.FixedTuple, tuple(mitems))
def set_name(self, name):
"""Set the name of the member.
This method ensures that the item member name is also updated.
"""
super().set_name(name)
for i, item in enumerate(self.items):
item.set_name(name + f"|item_{i}")
def set_index(self, index):
"""Assign the index to this member.
This method ensures that the item member index is also updated.
"""
super().set_index(index)
for item in self.items:
item.set_index(index)
def clone(self):
"""Create a clone of the tuple.
This will clone the internal tuple item if one is in use.
"""
clone = super().clone()
clone.items = items_clone = tuple(i.clone() for i in self.items)
mode, _ = self.validate_mode
clone.set_validate_mode(mode, items_clone)
return clone
|