parent
3271f85650
commit
2bf1b4dafc
|
@ -1462,26 +1462,38 @@ class Const(Value, metaclass=_ConstMeta):
|
||||||
|
|
||||||
def __init__(self, value, shape=None, *, src_loc_at=0):
|
def __init__(self, value, shape=None, *, src_loc_at=0):
|
||||||
# We deliberately do not call Value.__init__ here.
|
# We deliberately do not call Value.__init__ here.
|
||||||
self.value = int(operator.index(value))
|
value = int(operator.index(value))
|
||||||
if shape is None:
|
if shape is None:
|
||||||
shape = Shape(bits_for(self.value), signed=self.value < 0)
|
shape = Shape(bits_for(value), signed=value < 0)
|
||||||
elif isinstance(shape, int):
|
elif isinstance(shape, int):
|
||||||
shape = Shape(shape, signed=self.value < 0)
|
shape = Shape(shape, signed=value < 0)
|
||||||
else:
|
else:
|
||||||
if isinstance(shape, range) and self.value == shape.stop:
|
if isinstance(shape, range) and value == shape.stop:
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
message="Value {!r} equals the non-inclusive end of the constant "
|
message=f"Value {value!r} equals the non-inclusive end of the constant "
|
||||||
"shape {!r}; this is likely an off-by-one error"
|
f"shape {shape!r}; this is likely an off-by-one error",
|
||||||
.format(self.value, shape),
|
|
||||||
category=SyntaxWarning,
|
category=SyntaxWarning,
|
||||||
stacklevel=3)
|
stacklevel=3)
|
||||||
shape = Shape.cast(shape, src_loc_at=1 + src_loc_at)
|
shape = Shape.cast(shape, src_loc_at=1 + src_loc_at)
|
||||||
self.width = shape.width
|
self._width = shape.width
|
||||||
self.signed = shape.signed
|
self._signed = shape.signed
|
||||||
if self.signed and self.value >> (self.width - 1) & 1:
|
if shape.signed and value >> (shape.width - 1) & 1:
|
||||||
self.value |= -(1 << self.width)
|
value |= -(1 << shape.width)
|
||||||
else:
|
else:
|
||||||
self.value &= (1 << self.width) - 1
|
value &= (1 << shape.width) - 1
|
||||||
|
self._value = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
return self._value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def width(self):
|
||||||
|
return self._width
|
||||||
|
|
||||||
|
@property
|
||||||
|
def signed(self):
|
||||||
|
return self._signed
|
||||||
|
|
||||||
def shape(self):
|
def shape(self):
|
||||||
return Shape(self.width, self.signed)
|
return Shape(self.width, self.signed)
|
||||||
|
@ -1500,8 +1512,16 @@ C = Const # shorthand
|
||||||
class Operator(Value):
|
class Operator(Value):
|
||||||
def __init__(self, operator, operands, *, src_loc_at=0):
|
def __init__(self, operator, operands, *, src_loc_at=0):
|
||||||
super().__init__(src_loc_at=1 + src_loc_at)
|
super().__init__(src_loc_at=1 + src_loc_at)
|
||||||
self.operator = operator
|
self._operator = operator
|
||||||
self.operands = [Value.cast(op) for op in operands]
|
self._operands = tuple(Value.cast(op) for op in operands)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def operator(self):
|
||||||
|
return self._operator
|
||||||
|
|
||||||
|
@property
|
||||||
|
def operands(self):
|
||||||
|
return self._operands
|
||||||
|
|
||||||
def shape(self):
|
def shape(self):
|
||||||
def _bitwise_binary_shape(a_shape, b_shape):
|
def _bitwise_binary_shape(a_shape, b_shape):
|
||||||
|
@ -1614,9 +1634,21 @@ class Slice(Value):
|
||||||
raise IndexError(f"Slice start {start} must be less than slice stop {stop}")
|
raise IndexError(f"Slice start {start} must be less than slice stop {stop}")
|
||||||
|
|
||||||
super().__init__(src_loc_at=src_loc_at)
|
super().__init__(src_loc_at=src_loc_at)
|
||||||
self.value = value
|
self._value = value
|
||||||
self.start = int(operator.index(start))
|
self._start = int(operator.index(start))
|
||||||
self.stop = int(operator.index(stop))
|
self._stop = int(operator.index(stop))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
return self._value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def start(self):
|
||||||
|
return self._start
|
||||||
|
|
||||||
|
@property
|
||||||
|
def stop(self):
|
||||||
|
return self._stop
|
||||||
|
|
||||||
def shape(self):
|
def shape(self):
|
||||||
return Shape(self.stop - self.start)
|
return Shape(self.stop - self.start)
|
||||||
|
@ -1645,10 +1677,26 @@ class Part(Value):
|
||||||
raise TypeError("Part offset must be unsigned")
|
raise TypeError("Part offset must be unsigned")
|
||||||
|
|
||||||
super().__init__(src_loc_at=src_loc_at)
|
super().__init__(src_loc_at=src_loc_at)
|
||||||
self.value = value
|
self._value = value
|
||||||
self.offset = offset
|
self._offset = offset
|
||||||
self.width = width
|
self._width = width
|
||||||
self.stride = stride
|
self._stride = stride
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
return self._value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def offset(self):
|
||||||
|
return self._offset
|
||||||
|
|
||||||
|
@property
|
||||||
|
def width(self):
|
||||||
|
return self._width
|
||||||
|
|
||||||
|
@property
|
||||||
|
def stride(self):
|
||||||
|
return self._stride
|
||||||
|
|
||||||
def shape(self):
|
def shape(self):
|
||||||
return Shape(self.width)
|
return Shape(self.width)
|
||||||
|
@ -1691,7 +1739,7 @@ class Cat(Value):
|
||||||
"""
|
"""
|
||||||
def __init__(self, *args, src_loc_at=0):
|
def __init__(self, *args, src_loc_at=0):
|
||||||
super().__init__(src_loc_at=src_loc_at)
|
super().__init__(src_loc_at=src_loc_at)
|
||||||
self.parts = []
|
parts = []
|
||||||
for index, arg in enumerate(flatten(args)):
|
for index, arg in enumerate(flatten(args)):
|
||||||
if isinstance(arg, Enum) and (not isinstance(type(arg), ShapeCastable) or
|
if isinstance(arg, Enum) and (not isinstance(type(arg), ShapeCastable) or
|
||||||
not hasattr(arg, "_amaranth_shape_")):
|
not hasattr(arg, "_amaranth_shape_")):
|
||||||
|
@ -1706,7 +1754,12 @@ class Cat(Value):
|
||||||
"context; specify the width explicitly using C({}, {})"
|
"context; specify the width explicitly using C({}, {})"
|
||||||
.format(index + 1, arg, arg, bits_for(arg)),
|
.format(index + 1, arg, arg, bits_for(arg)),
|
||||||
SyntaxWarning, stacklevel=2 + src_loc_at)
|
SyntaxWarning, stacklevel=2 + src_loc_at)
|
||||||
self.parts.append(Value.cast(arg))
|
parts.append(Value.cast(arg))
|
||||||
|
self._parts = tuple(parts)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def parts(self):
|
||||||
|
return self._parts
|
||||||
|
|
||||||
def shape(self):
|
def shape(self):
|
||||||
return Shape(sum(len(part) for part in self.parts))
|
return Shape(sum(len(part) for part in self.parts))
|
||||||
|
@ -1784,8 +1837,8 @@ class Signal(Value, DUID, metaclass=_SignalMeta):
|
||||||
shape = unsigned(1)
|
shape = unsigned(1)
|
||||||
else:
|
else:
|
||||||
shape = Shape.cast(shape, src_loc_at=1 + src_loc_at)
|
shape = Shape.cast(shape, src_loc_at=1 + src_loc_at)
|
||||||
self.width = shape.width
|
self._width = shape.width
|
||||||
self.signed = shape.signed
|
self._signed = shape.signed
|
||||||
|
|
||||||
# TODO(amaranth-0.7): remove
|
# TODO(amaranth-0.7): remove
|
||||||
if reset is not None:
|
if reset is not None:
|
||||||
|
@ -1831,8 +1884,8 @@ class Signal(Value, DUID, metaclass=_SignalMeta):
|
||||||
.format(orig_init, shape),
|
.format(orig_init, shape),
|
||||||
category=SyntaxWarning,
|
category=SyntaxWarning,
|
||||||
stacklevel=2)
|
stacklevel=2)
|
||||||
self.init = init.value
|
self._init = init.value
|
||||||
self.reset_less = bool(reset_less)
|
self._reset_less = bool(reset_less)
|
||||||
|
|
||||||
if isinstance(orig_shape, range) and orig_init is not None and orig_init not in orig_shape:
|
if isinstance(orig_shape, range) and orig_init is not None and orig_init not in orig_shape:
|
||||||
if orig_init == orig_shape.stop:
|
if orig_init == orig_shape.stop:
|
||||||
|
@ -1843,21 +1896,21 @@ class Signal(Value, DUID, metaclass=_SignalMeta):
|
||||||
raise SyntaxError(
|
raise SyntaxError(
|
||||||
f"Initial value {orig_init!r} is not within the signal shape {orig_shape!r}")
|
f"Initial value {orig_init!r} is not within the signal shape {orig_shape!r}")
|
||||||
|
|
||||||
self.attrs = OrderedDict(() if attrs is None else attrs)
|
self._attrs = OrderedDict(() if attrs is None else attrs)
|
||||||
|
|
||||||
if decoder is not None:
|
if decoder is not None:
|
||||||
# The value representation is specified explicitly. Since we do not expose `hdl._repr`,
|
# The value representation is specified explicitly. Since we do not expose `hdl._repr`,
|
||||||
# this is the only way to add a custom filter to the signal right now. The setter sets
|
# this is the only way to add a custom filter to the signal right now. The setter sets
|
||||||
# `self._value_repr` as well as the compatibility `self.decoder`.
|
# `self._value_repr` as well as the compatibility `self.decoder`.
|
||||||
self.decoder = decoder
|
pass
|
||||||
else:
|
else:
|
||||||
# If it's an enum, expose it via `self.decoder` for compatibility, whether it's a Python
|
# If it's an enum, expose it via `self.decoder` for compatibility, whether it's a Python
|
||||||
# enum or an Amaranth enum. This also sets the value representation, even for custom
|
# enum or an Amaranth enum. This also sets the value representation, even for custom
|
||||||
# shape-castables that implement their own `_value_repr`.
|
# shape-castables that implement their own `_value_repr`.
|
||||||
if isinstance(orig_shape, type) and issubclass(orig_shape, Enum):
|
if isinstance(orig_shape, type) and issubclass(orig_shape, Enum):
|
||||||
self.decoder = orig_shape
|
decoder = orig_shape
|
||||||
else:
|
else:
|
||||||
self.decoder = None
|
decoder = None
|
||||||
# The value representation is specified implicitly in the shape of the signal.
|
# The value representation is specified implicitly in the shape of the signal.
|
||||||
if isinstance(orig_shape, ShapeCastable):
|
if isinstance(orig_shape, ShapeCastable):
|
||||||
# A custom shape-castable always has a `_value_repr`, at least the default one.
|
# A custom shape-castable always has a `_value_repr`, at least the default one.
|
||||||
|
@ -1869,24 +1922,6 @@ class Signal(Value, DUID, metaclass=_SignalMeta):
|
||||||
# Any other case is formatted as a plain integer.
|
# Any other case is formatted as a plain integer.
|
||||||
self._value_repr = (Repr(FormatInt(), self),)
|
self._value_repr = (Repr(FormatInt(), self),)
|
||||||
|
|
||||||
@property
|
|
||||||
def reset(self):
|
|
||||||
warnings.warn("`Signal.reset` is deprecated, use `Signal.init` instead",
|
|
||||||
DeprecationWarning, stacklevel=2)
|
|
||||||
return self.init
|
|
||||||
|
|
||||||
@reset.setter
|
|
||||||
def reset(self, value):
|
|
||||||
warnings.warn("`Signal.reset` is deprecated, use `Signal.init` instead",
|
|
||||||
DeprecationWarning, stacklevel=2)
|
|
||||||
self.init = value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def decoder(self):
|
|
||||||
return self._decoder
|
|
||||||
|
|
||||||
@decoder.setter
|
|
||||||
def decoder(self, decoder):
|
|
||||||
# Compute the value representation that will be used by Amaranth.
|
# Compute the value representation that will be used by Amaranth.
|
||||||
if decoder is None:
|
if decoder is None:
|
||||||
self._value_repr = (Repr(FormatInt(), self),)
|
self._value_repr = (Repr(FormatInt(), self),)
|
||||||
|
@ -1903,6 +1938,37 @@ class Signal(Value, DUID, metaclass=_SignalMeta):
|
||||||
return str(value)
|
return str(value)
|
||||||
self._decoder = enum_decoder
|
self._decoder = enum_decoder
|
||||||
|
|
||||||
|
@property
|
||||||
|
def width(self):
|
||||||
|
return self._width
|
||||||
|
|
||||||
|
@property
|
||||||
|
def signed(self):
|
||||||
|
return self._signed
|
||||||
|
|
||||||
|
@property
|
||||||
|
def init(self):
|
||||||
|
return self._init
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reset(self):
|
||||||
|
warnings.warn("`Signal.reset` is deprecated, use `Signal.init` instead",
|
||||||
|
DeprecationWarning, stacklevel=2)
|
||||||
|
return self._init
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reset_less(self):
|
||||||
|
return self._reset_less
|
||||||
|
|
||||||
|
@property
|
||||||
|
def attrs(self):
|
||||||
|
# Would ideally be frozendict...
|
||||||
|
return self._attrs
|
||||||
|
|
||||||
|
@property
|
||||||
|
def decoder(self):
|
||||||
|
return self._decoder
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def like(cls, other, *, name=None, name_suffix=None, init=None, reset=None, src_loc_at=0, **kwargs):
|
def like(cls, other, *, name=None, name_suffix=None, init=None, reset=None, src_loc_at=0, **kwargs):
|
||||||
"""Create Signal based on another.
|
"""Create Signal based on another.
|
||||||
|
@ -1970,7 +2036,11 @@ class ClockSignal(Value):
|
||||||
raise TypeError(f"Clock domain name must be a string, not {domain!r}")
|
raise TypeError(f"Clock domain name must be a string, not {domain!r}")
|
||||||
if domain == "comb":
|
if domain == "comb":
|
||||||
raise ValueError(f"Domain '{domain}' does not have a clock")
|
raise ValueError(f"Domain '{domain}' does not have a clock")
|
||||||
self.domain = domain
|
self._domain = domain
|
||||||
|
|
||||||
|
@property
|
||||||
|
def domain(self):
|
||||||
|
return self._domain
|
||||||
|
|
||||||
def shape(self):
|
def shape(self):
|
||||||
return Shape(1)
|
return Shape(1)
|
||||||
|
@ -2006,8 +2076,16 @@ class ResetSignal(Value):
|
||||||
raise TypeError(f"Clock domain name must be a string, not {domain!r}")
|
raise TypeError(f"Clock domain name must be a string, not {domain!r}")
|
||||||
if domain == "comb":
|
if domain == "comb":
|
||||||
raise ValueError(f"Domain '{domain}' does not have a reset")
|
raise ValueError(f"Domain '{domain}' does not have a reset")
|
||||||
self.domain = domain
|
self._domain = domain
|
||||||
self.allow_reset_less = allow_reset_less
|
self._allow_reset_less = allow_reset_less
|
||||||
|
|
||||||
|
@property
|
||||||
|
def domain(self):
|
||||||
|
return self._domain
|
||||||
|
|
||||||
|
@property
|
||||||
|
def allow_reset_less(self):
|
||||||
|
return self._allow_reset_less
|
||||||
|
|
||||||
def shape(self):
|
def shape(self):
|
||||||
return Shape(1)
|
return Shape(1)
|
||||||
|
@ -2032,8 +2110,16 @@ class AnyValue(Value, DUID):
|
||||||
super().__init__(src_loc_at=src_loc_at)
|
super().__init__(src_loc_at=src_loc_at)
|
||||||
self.kind = self.Kind(kind)
|
self.kind = self.Kind(kind)
|
||||||
shape = Shape.cast(shape, src_loc_at=1 + src_loc_at)
|
shape = Shape.cast(shape, src_loc_at=1 + src_loc_at)
|
||||||
self.width = shape.width
|
self._width = shape.width
|
||||||
self.signed = shape.signed
|
self._signed = shape.signed
|
||||||
|
|
||||||
|
@property
|
||||||
|
def width(self):
|
||||||
|
return self._width
|
||||||
|
|
||||||
|
@property
|
||||||
|
def signed(self):
|
||||||
|
return self._signed
|
||||||
|
|
||||||
def shape(self):
|
def shape(self):
|
||||||
return Shape(self.width, self.signed)
|
return Shape(self.width, self.signed)
|
||||||
|
@ -2147,8 +2233,16 @@ class Array(MutableSequence):
|
||||||
class ArrayProxy(Value):
|
class ArrayProxy(Value):
|
||||||
def __init__(self, elems, index, *, src_loc_at=0):
|
def __init__(self, elems, index, *, src_loc_at=0):
|
||||||
super().__init__(src_loc_at=1 + src_loc_at)
|
super().__init__(src_loc_at=1 + src_loc_at)
|
||||||
self.elems = elems
|
self._elems = elems
|
||||||
self.index = Value.cast(index)
|
self._index = Value.cast(index)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def elems(self):
|
||||||
|
return self._elems
|
||||||
|
|
||||||
|
@property
|
||||||
|
def index(self):
|
||||||
|
return self._index
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
def __getattr__(self, attr):
|
||||||
return ArrayProxy([getattr(elem, attr) for elem in self.elems], self.index)
|
return ArrayProxy([getattr(elem, attr) for elem in self.elems], self.index)
|
||||||
|
@ -2245,8 +2339,16 @@ class Statement:
|
||||||
class Assign(Statement):
|
class Assign(Statement):
|
||||||
def __init__(self, lhs, rhs, *, src_loc_at=0):
|
def __init__(self, lhs, rhs, *, src_loc_at=0):
|
||||||
super().__init__(src_loc_at=src_loc_at)
|
super().__init__(src_loc_at=src_loc_at)
|
||||||
self.lhs = Value.cast(lhs)
|
self._lhs = Value.cast(lhs)
|
||||||
self.rhs = Value.cast(rhs)
|
self._rhs = Value.cast(rhs)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def lhs(self):
|
||||||
|
return self._lhs
|
||||||
|
|
||||||
|
@property
|
||||||
|
def rhs(self):
|
||||||
|
return self._rhs
|
||||||
|
|
||||||
def _lhs_signals(self):
|
def _lhs_signals(self):
|
||||||
return self.lhs._lhs_signals()
|
return self.lhs._lhs_signals()
|
||||||
|
@ -2273,13 +2375,25 @@ class Property(Statement, MustUse):
|
||||||
|
|
||||||
def __init__(self, kind, test, *, name=None, src_loc_at=0):
|
def __init__(self, kind, test, *, name=None, src_loc_at=0):
|
||||||
super().__init__(src_loc_at=src_loc_at)
|
super().__init__(src_loc_at=src_loc_at)
|
||||||
self.kind = self.Kind(kind)
|
self._kind = self.Kind(kind)
|
||||||
self.test = Value.cast(test)
|
self._test = Value.cast(test)
|
||||||
self.name = name
|
self._name = name
|
||||||
if not isinstance(self.name, str) and self.name is not None:
|
if not isinstance(self.name, str) and self.name is not None:
|
||||||
raise TypeError("Property name must be a string or None, not {!r}"
|
raise TypeError("Property name must be a string or None, not {!r}"
|
||||||
.format(self.name))
|
.format(self.name))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def kind(self):
|
||||||
|
return self._kind
|
||||||
|
|
||||||
|
@property
|
||||||
|
def test(self):
|
||||||
|
return self._test
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self._name
|
||||||
|
|
||||||
def _lhs_signals(self):
|
def _lhs_signals(self):
|
||||||
return set()
|
return set()
|
||||||
|
|
||||||
|
@ -2322,8 +2436,8 @@ class Switch(Statement):
|
||||||
# be automatically traced, so whatever constructs a Switch may optionally provide it.
|
# be automatically traced, so whatever constructs a Switch may optionally provide it.
|
||||||
self.case_src_locs = {}
|
self.case_src_locs = {}
|
||||||
|
|
||||||
self.test = Value.cast(test)
|
self._test = Value.cast(test)
|
||||||
self.cases = OrderedDict()
|
self._cases = OrderedDict()
|
||||||
for orig_keys, stmts in cases.items():
|
for orig_keys, stmts in cases.items():
|
||||||
# Map: None -> (); key -> (key,); (key...) -> (key...)
|
# Map: None -> (); key -> (key,); (key...) -> (key...)
|
||||||
keys = orig_keys
|
keys = orig_keys
|
||||||
|
@ -2354,10 +2468,18 @@ class Switch(Statement):
|
||||||
new_keys = (*new_keys, key)
|
new_keys = (*new_keys, key)
|
||||||
if not isinstance(stmts, Iterable):
|
if not isinstance(stmts, Iterable):
|
||||||
stmts = [stmts]
|
stmts = [stmts]
|
||||||
self.cases[new_keys] = Statement.cast(stmts)
|
self._cases[new_keys] = Statement.cast(stmts)
|
||||||
if orig_keys in case_src_locs:
|
if orig_keys in case_src_locs:
|
||||||
self.case_src_locs[new_keys] = case_src_locs[orig_keys]
|
self.case_src_locs[new_keys] = case_src_locs[orig_keys]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def test(self):
|
||||||
|
return self._test
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cases(self):
|
||||||
|
return self._cases
|
||||||
|
|
||||||
def _lhs_signals(self):
|
def _lhs_signals(self):
|
||||||
return union((s._lhs_signals() for s in self.cases.values()), start=SignalSet())
|
return union((s._lhs_signals() for s in self.cases.values()), start=SignalSet())
|
||||||
|
|
||||||
|
|
|
@ -1237,10 +1237,6 @@ class SignalTestCase(FHDLTestCase):
|
||||||
with self.assertWarnsRegex(DeprecationWarning,
|
with self.assertWarnsRegex(DeprecationWarning,
|
||||||
r"^`Signal.reset` is deprecated, use `Signal.init` instead$"):
|
r"^`Signal.reset` is deprecated, use `Signal.init` instead$"):
|
||||||
self.assertEqual(s1.reset, 0b111)
|
self.assertEqual(s1.reset, 0b111)
|
||||||
with self.assertWarnsRegex(DeprecationWarning,
|
|
||||||
r"^`Signal.reset` is deprecated, use `Signal.init` instead$"):
|
|
||||||
s1.reset = 0b010
|
|
||||||
self.assertEqual(s1.init, 0b010)
|
|
||||||
with self.assertWarnsRegex(DeprecationWarning,
|
with self.assertWarnsRegex(DeprecationWarning,
|
||||||
r"^`reset=` is deprecated, use `init=` instead$"):
|
r"^`reset=` is deprecated, use `init=` instead$"):
|
||||||
s2 = Signal.like(s1, reset=3)
|
s2 = Signal.like(s1, reset=3)
|
||||||
|
|
|
@ -194,20 +194,6 @@ class RecordTestCase(FHDLTestCase):
|
||||||
r4 = Record.like(r1, name_suffix="foo")
|
r4 = Record.like(r1, name_suffix="foo")
|
||||||
self.assertEqual(r4.name, "r1foo")
|
self.assertEqual(r4.name, "r1foo")
|
||||||
|
|
||||||
def test_like_modifications(self):
|
|
||||||
r1 = Record([("a", 1), ("b", [("s", 1)])])
|
|
||||||
self.assertEqual(r1.a.name, "r1__a")
|
|
||||||
self.assertEqual(r1.b.name, "r1__b")
|
|
||||||
self.assertEqual(r1.b.s.name, "r1__b__s")
|
|
||||||
r1.a.init = 1
|
|
||||||
r1.b.s.init = 1
|
|
||||||
r2 = Record.like(r1)
|
|
||||||
self.assertEqual(r2.a.init, 1)
|
|
||||||
self.assertEqual(r2.b.s.init, 1)
|
|
||||||
self.assertEqual(r2.a.name, "r2__a")
|
|
||||||
self.assertEqual(r2.b.name, "r2__b")
|
|
||||||
self.assertEqual(r2.b.s.name, "r2__b__s")
|
|
||||||
|
|
||||||
def test_slice_tuple(self):
|
def test_slice_tuple(self):
|
||||||
r1 = Record([("a", 1), ("b", 2), ("c", 3)])
|
r1 = Record([("a", 1), ("b", 2), ("c", 3)])
|
||||||
r2 = r1["a", "c"]
|
r2 = r1["a", "c"]
|
||||||
|
|
Loading…
Reference in a new issue