hdl._ast: deprecate ValueCastable.lowermethod.

This commit is contained in:
Wanda 2024-02-13 05:21:39 +01:00 committed by Catherine
parent e2fd819742
commit 0da439cce1
7 changed files with 10 additions and 39 deletions

View file

@ -1262,9 +1262,6 @@ class ValueCastable:
if cls.shape is ValueCastable.shape:
raise TypeError(f"Class '{cls.__name__}' deriving from 'ValueCastable' must override "
"the 'shape' method")
if not hasattr(cls.as_value, "_ValueCastable__memoized"):
raise TypeError(f"Class '{cls.__name__}' deriving from 'ValueCastable' must decorate "
"the 'as_value' method with the 'ValueCastable.lowermethod' decorator")
# The signatures and definitions of these methods are weird because they are present here for
# documentation (and error checking above) purpose only and should not affect control flow.
@ -1333,17 +1330,10 @@ class ValueCastable:
"""
return super().shape(*args, **kwargs) # :nocov:
# TODO(amaranth-0.6): remove
@staticmethod
@deprecated("`ValueCastable.lowermethod` is no longer required and will be removed in Amaranth 0.6")
def lowermethod(func):
"""Decorator to memoize lowering methods.
Ensures the decorated method is called only once, with subsequent method calls returning
the object returned by the first first method call.
This decorator is required to decorate the :pc:`as_value` method of :pc:`ValueCastable`
subclasses. This is to ensure that Amaranth's view of representation of all values stays
internally consistent.
"""
@functools.wraps(func)
def wrapper_memoized(self, *args, **kwargs):
# Use `in self.__dict__` instead of `hasattr` to avoid interfering with custom

View file

@ -178,7 +178,6 @@ class Record(ValueCastable):
raise AttributeError("{} does not have a field '{}'. Did you mean one of: {}?"
.format(reference, item, ", ".join(self.fields))) from None
@ValueCastable.lowermethod
def as_value(self):
return Cat(self.fields.values())

View file

@ -638,7 +638,6 @@ class View(ValueCastable):
"""
return self.__orig_layout
@ValueCastable.lowermethod
def as_value(self):
"""Get underlying value.

View file

@ -232,7 +232,6 @@ class EnumView(ValueCastable):
"""Returns the underlying enum type."""
return self.enum
@ValueCastable.lowermethod
def as_value(self):
"""Returns the underlying value."""
return self.target

View file

@ -1040,7 +1040,6 @@ class ArrayTestCase(FHDLTestCase):
def test_index_value_castable(self):
class MyValue(ValueCastable):
@ValueCastable.lowermethod
def as_value(self):
return Signal()
@ -1328,7 +1327,6 @@ class MockValueCastable(ValueCastable):
def shape(self):
return Value.cast(self.dest).shape()
@ValueCastable.lowermethod
def as_value(self):
return self.dest
@ -1340,6 +1338,7 @@ class MockValueCastableChanges(ValueCastable):
def shape(self):
return unsigned(self.width)
with _ignore_deprecated():
@ValueCastable.lowermethod
def as_value(self):
return Signal(self.width)
@ -1352,6 +1351,7 @@ class MockValueCastableCustomGetattr(ValueCastable):
def shape(self):
assert False
with _ignore_deprecated():
@ValueCastable.lowermethod
def as_value(self):
return Const(0)
@ -1361,20 +1361,6 @@ class MockValueCastableCustomGetattr(ValueCastable):
class ValueCastableTestCase(FHDLTestCase):
def test_not_decorated(self):
with self.assertRaisesRegex(TypeError,
r"^Class 'MockValueCastableNotDecorated' deriving from 'ValueCastable' must "
r"decorate the 'as_value' method with the 'ValueCastable.lowermethod' decorator$"):
class MockValueCastableNotDecorated(ValueCastable):
def __init__(self):
pass
def shape(self):
pass
def as_value(self):
return Signal()
def test_no_override(self):
with self.assertRaisesRegex(TypeError,
r"^Class 'MockValueCastableNoOverrideAsValue' deriving from 'ValueCastable' must "

View file

@ -4,7 +4,6 @@ import unittest
from types import SimpleNamespace as NS
from amaranth import *
from amaranth.hdl._ast import ValueCastable
from amaranth.lib import data, enum
from amaranth.lib.wiring import Flow, In, Out, Member
from amaranth.lib.wiring import SignatureError, SignatureMembers, FlippedSignatureMembers

View file

@ -728,7 +728,6 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
def test_value_castable(self):
class MyValue(ValueCastable):
@ValueCastable.lowermethod
def as_value(self):
return Signal()