diff --git a/amaranth/_unused.py b/amaranth/_unused.py index 6e053435a..4f2507bc1 100644 --- a/amaranth/_unused.py +++ b/amaranth/_unused.py @@ -32,7 +32,7 @@ def __del__(self): return if hasattr(self, "_MustUse__used") and not self._MustUse__used: if get_linter_option(self._MustUse__context["filename"], - self._MustUse__warning.__name__, bool, True): + self._MustUse__warning.__qualname__, bool, True): warnings.warn_explicit( f"{self!r} created but never used", self._MustUse__warning, **self._MustUse__context) diff --git a/amaranth/_utils.py b/amaranth/_utils.py index 938461527..10b125b16 100644 --- a/amaranth/_utils.py +++ b/amaranth/_utils.py @@ -44,7 +44,7 @@ def union(i, start=None): def final(cls): def init_subclass(): raise TypeError("Subclassing {}.{} is not supported" - .format(cls.__module__, cls.__name__)) + .format(cls.__module__, cls.__qualname__)) cls.__init_subclass__ = init_subclass return cls diff --git a/amaranth/build/plat.py b/amaranth/build/plat.py index 432ae6770..d5b02ab30 100644 --- a/amaranth/build/plat.py +++ b/amaranth/build/plat.py @@ -40,7 +40,7 @@ def __init__(self): def default_clk_constraint(self): if self.default_clk is None: raise AttributeError("Platform '{}' does not define a default clock" - .format(type(self).__name__)) + .format(type(self).__qualname__)) return self.lookup(self.default_clk).clock @property @@ -48,7 +48,7 @@ def default_clk_frequency(self): constraint = self.default_clk_constraint if constraint is None: raise AttributeError("Platform '{}' does not constrain its default clock" - .format(type(self).__name__)) + .format(type(self).__qualname__)) return constraint.frequency def add_file(self, filename, content): @@ -173,7 +173,7 @@ def toolchain_program(self, products, name, **kwargs): Extract bitstream for fragment ``name`` from ``products`` and download it to a target. """ raise NotImplementedError("Platform '{}' does not support programming" - .format(type(self).__name__)) + .format(type(self).__qualname__)) class TemplatedPlatform(Platform): @@ -244,7 +244,7 @@ def _extract_override(var, *, expected_type): if issubclass(expected_type, str) and not isinstance(kwarg, str) and isinstance(kwarg, Iterable): kwarg = " ".join(kwarg) if not isinstance(kwarg, expected_type) and not expected_type is None: - raise TypeError(f"Override '{var}' must be a {expected_type.__name__}, not {kwarg!r}") + raise TypeError(f"Override '{var}' must be a {expected_type.__qualname__}, not {kwarg!r}") return kwarg else: return jinja2.Undefined(name=var) diff --git a/amaranth/hdl/_ast.py b/amaranth/hdl/_ast.py index 64f86ccc2..ef863a67a 100644 --- a/amaranth/hdl/_ast.py +++ b/amaranth/hdl/_ast.py @@ -244,16 +244,16 @@ def __init__(self, *args, **kwargs): def __init_subclass__(cls, **kwargs): if cls.as_shape is ShapeCastable.as_shape: - raise TypeError(f"Class '{cls.__name__}' deriving from 'ShapeCastable' must override " + raise TypeError(f"Class '{cls.__qualname__}' deriving from 'ShapeCastable' must override " f"the 'as_shape' method") if cls.const is ShapeCastable.const: - raise TypeError(f"Class '{cls.__name__}' deriving from 'ShapeCastable' must override " + raise TypeError(f"Class '{cls.__qualname__}' deriving from 'ShapeCastable' must override " f"the 'const' method") if cls.__call__ is ShapeCastable.__call__: - raise TypeError(f"Class '{cls.__name__}' deriving from 'ShapeCastable' must override " + raise TypeError(f"Class '{cls.__qualname__}' deriving from 'ShapeCastable' must override " f"the '__call__' method") if cls.from_bits is ShapeCastable.from_bits: - raise TypeError(f"Class '{cls.__name__}' deriving from 'ShapeCastable' must override " + raise TypeError(f"Class '{cls.__qualname__}' deriving from 'ShapeCastable' must override " f"the 'from_bits' method") # The signatures and definitions of these methods are weird because they are present here for @@ -1400,10 +1400,10 @@ def __init__(self, *args, **kwargs): def __init_subclass__(cls, **kwargs): if cls.as_value is ValueCastable.as_value: - raise TypeError(f"Class '{cls.__name__}' deriving from 'ValueCastable' must override " + raise TypeError(f"Class '{cls.__qualname__}' deriving from 'ValueCastable' must override " "the 'as_value' method") if cls.shape is ValueCastable.shape: - raise TypeError(f"Class '{cls.__name__}' deriving from 'ValueCastable' must override " + raise TypeError(f"Class '{cls.__qualname__}' deriving from 'ValueCastable' must override " "the 'shape' method") # The signatures and definitions of these methods are weird because they are present here for @@ -2065,12 +2065,12 @@ def __init__(self, shape=None, *, name=None, init=None, reset=None, reset_less=F if isinstance(orig_shape, ShapeCastable): self._format = orig_shape.format(orig_shape(self), "") elif isinstance(orig_shape, type) and issubclass(orig_shape, Enum): - self._format = Format.Enum(self, orig_shape, name=orig_shape.__name__) + self._format = Format.Enum(self, orig_shape, name=orig_shape.__qualname__) else: self._format = Format("{}", self) if isinstance(decoder, type) and issubclass(decoder, Enum): - self._format = Format.Enum(self, decoder, name=decoder.__name__) + self._format = Format.Enum(self, decoder, name=decoder.__qualname__) self._decoder = decoder @@ -3185,7 +3185,7 @@ def __len__(self): def __repr__(self): pairs = [f"({k!r}, {v!r})" for k, v in self.items()] - return "{}.{}([{}])".format(type(self).__module__, type(self).__name__, + return "{}.{}([{}])".format(type(self).__module__, type(self).__qualname__, ", ".join(pairs)) @@ -3217,7 +3217,7 @@ def __len__(self): return len(self._storage) def __repr__(self): - return "{}.{}({})".format(type(self).__module__, type(self).__name__, + return "{}.{}({})".format(type(self).__module__, type(self).__qualname__, ", ".join(repr(x) for x in self)) @@ -3247,7 +3247,7 @@ def __lt__(self, other): return self._intern < other._intern def __repr__(self): - return f"<{__name__}.SignalKey {self.signal!r}>" + return f"<{__qualname__}.SignalKey {self.signal!r}>" class SignalDict(_MappedKeyDict): diff --git a/amaranth/hdl/_dsl.py b/amaranth/hdl/_dsl.py index c66df2e21..6de5b1e4f 100644 --- a/amaranth/hdl/_dsl.py +++ b/amaranth/hdl/_dsl.py @@ -144,9 +144,9 @@ def __init__(self, builder, depth): def __getattr__(self, name): if name in ("comb", "sync"): raise AttributeError("'{}' object has no attribute '{}'; did you mean 'd.{}'?" - .format(type(self).__name__, name, name)) + .format(type(self).__qualname__, name, name)) raise AttributeError("'{}' object has no attribute '{}'" - .format(type(self).__name__, name)) + .format(type(self).__qualname__, name)) class _ModuleBuilderSubmodules: diff --git a/amaranth/hdl/_nir.py b/amaranth/hdl/_nir.py index 7f9c26867..2cd4d28e2 100644 --- a/amaranth/hdl/_nir.py +++ b/amaranth/hdl/_nir.py @@ -465,7 +465,7 @@ def traverse(net): elif isinstance(obj, Operator): obj = f"operator {obj.operator}" else: - obj = f"cell {obj.__class__.__name__}" + obj = f"cell {obj.__class__.__qualname__}" src_loc = ":0" if src_loc is None else f"{src_loc[0]}:{src_loc[1]}" msg.append(f" {src_loc}: {obj} bit {bit}\n") raise CombinationalCycle("".join(msg)) @@ -656,7 +656,7 @@ class Operator(Cell): The ternary operators are: - - 'm': multiplexer, first input needs to have width of 1, second and third operand need to have + - 'm': multiplexer, first input needs to have width of 1, second and third operand need to have the same width as output; implements arg0 ? arg1 : arg2 Attributes diff --git a/amaranth/lib/cdc.py b/amaranth/lib/cdc.py index 776c1bcc8..d92cbe23b 100644 --- a/amaranth/lib/cdc.py +++ b/amaranth/lib/cdc.py @@ -96,7 +96,7 @@ def elaborate(self, platform): if self._max_input_delay is not None: raise NotImplementedError("Platform '{}' does not support constraining input delay " "for FFSynchronizer" - .format(type(platform).__name__)) + .format(type(platform).__qualname__)) m = Module() flops = [Signal(self.i.shape(), name=f"stage{index}", @@ -170,7 +170,7 @@ def elaborate(self, platform): if self._max_input_delay is not None: raise NotImplementedError("Platform '{}' does not support constraining input delay " "for AsyncFFSynchronizer" - .format(type(platform).__name__)) + .format(type(platform).__qualname__)) m = Module() m.domains += ClockDomain("async_ff", async_reset=True) diff --git a/amaranth/lib/data.py b/amaranth/lib/data.py index 8c77cc2cf..e58c9f372 100644 --- a/amaranth/lib/data.py +++ b/amaranth/lib/data.py @@ -907,7 +907,7 @@ def __and__(self, other): __rxor__ = __and__ def __repr__(self): - return f"{self.__class__.__name__}({self.__layout!r}, {self.__target!r})" + return f"{self.__class__.__qualname__}({self.__layout!r}, {self.__target!r})" class Const(ValueCastable): @@ -1124,7 +1124,7 @@ def __and__(self, other): __rxor__ = __and__ def __repr__(self): - return f"{self.__class__.__name__}({self.__layout!r}, {self.__target!r})" + return f"{self.__class__.__qualname__}({self.__layout!r}, {self.__target!r})" class _AggregateMeta(ShapeCastable, type): diff --git a/amaranth/lib/enum.py b/amaranth/lib/enum.py index 032f281a7..d6463c3bd 100644 --- a/amaranth/lib/enum.py +++ b/amaranth/lib/enum.py @@ -178,7 +178,7 @@ def from_bits(cls, bits): def format(cls, value, format_spec): if format_spec != "": raise ValueError(f"Format specifier {format_spec!r} is not supported for enums") - return Format.Enum(value, cls, name=cls.__name__) + return Format.Enum(value, cls, name=cls.__qualname__) # In 3.11, Python renamed EnumMeta to EnumType. Like Python itself, we support both for @@ -310,7 +310,7 @@ def __ne__(self, other): return self.target != other.target def __repr__(self): - return f"{type(self).__name__}({self.enum.__name__}, {self.target!r})" + return f"{type(self).__qualname__}({self.enum.__qualname__}, {self.target!r})" class FlagView(EnumView): diff --git a/amaranth/lib/wiring.py b/amaranth/lib/wiring.py index 1bf963e96..b91a0e74c 100644 --- a/amaranth/lib/wiring.py +++ b/amaranth/lib/wiring.py @@ -1198,7 +1198,7 @@ def __repr__(self): attrs = ''.join(f", {name}={value!r}" for name, value in self.__dict__.items() if name != "signature") - return f'<{type(self).__name__}: {self.signature}{attrs}>' + return f'<{type(self).__qualname__}: {self.signature}{attrs}>' # To reduce API surface area `FlippedInterface` is made final. This restriction could be lifted diff --git a/amaranth/rpc.py b/amaranth/rpc.py index 42be902b4..f52e9dfd7 100644 --- a/amaranth/rpc.py +++ b/amaranth/rpc.py @@ -76,7 +76,7 @@ def _serve_yosys(modules): rtlil_text = rtlil.convert(elaboratable, name=module_name, ports=ports) response = {"frontend": "ilang", "source": rtlil_text} except Exception as error: - response = {"error": f"{type(error).__name__}: {str(error)}"} + response = {"error": f"{type(error).__qualname__}: {str(error)}"} else: return {"error": "Unrecognized method {!r}".format(request["method"])} diff --git a/amaranth/vendor/_xilinx.py b/amaranth/vendor/_xilinx.py index 9a44c6253..b952ff482 100644 --- a/amaranth/vendor/_xilinx.py +++ b/amaranth/vendor/_xilinx.py @@ -1236,7 +1236,7 @@ def get_ff_sync(self, ff_sync): elif ff_sync._max_input_delay is not None: raise NotImplementedError("Platform '{}' does not support constraining input delay " "for FFSynchronizer" - .format(type(self).__name__)) + .format(type(self).__qualname__)) for i, o in zip((ff_sync.i, *flops), flops): m.d[ff_sync._o_domain] += o.eq(i) m.d.comb += ff_sync.o.eq(flops[-1]) @@ -1284,7 +1284,7 @@ def get_async_ff_sync(self, async_ff_sync): elif async_ff_sync._max_input_delay is not None: raise NotImplementedError("Platform '{}' does not support constraining input delay " "for AsyncFFSynchronizer" - .format(type(self).__name__)) + .format(type(self).__qualname__)) for i, o in zip((0, *flops_q), flops_d): m.d.comb += o.eq(i) diff --git a/tests/test_back_rtlil.py b/tests/test_back_rtlil.py index 6c4dbcc81..a52f7ce94 100644 --- a/tests/test_back_rtlil.py +++ b/tests/test_back_rtlil.py @@ -2024,7 +2024,7 @@ class MyEnum(enum.Enum, shape=unsigned(2)): attribute \generator "Amaranth" attribute \top 1 module \top - attribute \enum_base_type "MyEnum" + attribute \enum_base_type "DetailTestCase.test_enum..MyEnum" attribute \enum_value_00 "A" attribute \enum_value_01 "B" attribute \enum_value_10 "C" @@ -2052,7 +2052,7 @@ class Meow(data.Struct): attribute \top 1 module \top wire width 13 input 0 \sig - attribute \enum_base_type "MyEnum" + attribute \enum_base_type "DetailTestCase.test_struct..MyEnum" attribute \enum_value_00 "A" attribute \enum_value_01 "B" attribute \enum_value_10 "C" diff --git a/tests/test_hdl_ast.py b/tests/test_hdl_ast.py index cdb03679d..a7ba972b4 100644 --- a/tests/test_hdl_ast.py +++ b/tests/test_hdl_ast.py @@ -185,7 +185,7 @@ def from_bits(self, bits): class ShapeCastableTestCase(FHDLTestCase): def test_no_override(self): with self.assertRaisesRegex(TypeError, - r"^Class 'MockShapeCastableNoOverride' deriving from 'ShapeCastable' must " + r"^Class '.+\.MockShapeCastableNoOverride' deriving from 'ShapeCastable' must " r"override the 'as_shape' method$"): class MockShapeCastableNoOverride(ShapeCastable): def __init__(self): @@ -509,7 +509,7 @@ def __init__(self, value): def shape(self): return MockConstShape() - + def as_value(self): return Const(self.value, 8) @@ -1308,7 +1308,7 @@ class Color(Enum): BLUE = 2 s = Signal(decoder=Color) self.assertEqual(s.decoder, Color) - self.assertRepr(s._format, "(format-enum (sig s) 'Color' (1 'RED') (2 'BLUE'))") + self.assertRepr(s._format, f"(format-enum (sig s) '{Color.__qualname__}' (1 'RED') (2 'BLUE'))") def test_enum(self): s1 = Signal(UnsignedEnum) @@ -1481,14 +1481,14 @@ def __getattr__(self, attr): class ValueCastableTestCase(FHDLTestCase): def test_no_override(self): with self.assertRaisesRegex(TypeError, - r"^Class 'MockValueCastableNoOverrideAsValue' deriving from 'ValueCastable' must " + r"^Class '.+\.MockValueCastableNoOverrideAsValue' deriving from 'ValueCastable' must " r"override the 'as_value' method$"): class MockValueCastableNoOverrideAsValue(ValueCastable): def __init__(self): pass with self.assertRaisesRegex(TypeError, - r"^Class 'MockValueCastableNoOverrideShapec' deriving from 'ValueCastable' must " + r"^Class '.+\.MockValueCastableNoOverrideShapec' deriving from 'ValueCastable' must " r"override the 'shape' method$"): class MockValueCastableNoOverrideShapec(ValueCastable): def __init__(self): diff --git a/tests/test_hdl_ir.py b/tests/test_hdl_ir.py index 060e67ef4..bd555070d 100644 --- a/tests/test_hdl_ir.py +++ b/tests/test_hdl_ir.py @@ -3416,7 +3416,7 @@ class MyEnum(enum.Enum, shape=unsigned(2)): ]) self.assertEqual(nl.signal_fields[s1.as_value()], { (): SignalField(nl.signals[s1.as_value()], signed=False), - ('a',): SignalField(nl.signals[s1.as_value()][0:2], signed=False, enum_name="MyEnum", enum_variants={ + ('a',): SignalField(nl.signals[s1.as_value()][0:2], signed=False, enum_name=MyEnum.__qualname__, enum_variants={ 0: "A", 1: "B", 2: "C", @@ -3424,7 +3424,7 @@ class MyEnum(enum.Enum, shape=unsigned(2)): ('b',): SignalField(nl.signals[s1.as_value()][2:5], signed=True) }) self.assertEqual(nl.signal_fields[s2.as_value()], { - (): SignalField(nl.signals[s2.as_value()], signed=False, enum_name="MyEnum", enum_variants={ + (): SignalField(nl.signals[s2.as_value()], signed=False, enum_name=MyEnum.__qualname__, enum_variants={ 0: "A", 1: "B", 2: "C", @@ -3515,4 +3515,4 @@ def test_require_renamed(self): m.submodules += DomainRenamer("test")(RequirePosedge("sync")) with self.assertRaisesRegex(DomainRequirementFailed, r"^Domain test has a negedge clock, but posedge clock is required by top.U\$0 at .*$"): - Fragment.get(m, None).prepare() \ No newline at end of file + Fragment.get(m, None).prepare() diff --git a/tests/test_lib_enum.py b/tests/test_lib_enum.py index ce0c67d30..1cfe1e231 100644 --- a/tests/test_lib_enum.py +++ b/tests/test_lib_enum.py @@ -107,9 +107,9 @@ def test_const_shape(self): class EnumA(Enum, shape=8): Z = 0 A = 10 - self.assertRepr(EnumA.const(None), "EnumView(EnumA, (const 8'd0))") - self.assertRepr(EnumA.const(10), "EnumView(EnumA, (const 8'd10))") - self.assertRepr(EnumA.const(EnumA.A), "EnumView(EnumA, (const 8'd10))") + self.assertRepr(EnumA.const(None), f"EnumView({EnumA.__qualname__}, (const 8'd0))") + self.assertRepr(EnumA.const(10), f"EnumView({EnumA.__qualname__}, (const 8'd10))") + self.assertRepr(EnumA.const(EnumA.A), f"EnumView({EnumA.__qualname__}, (const 8'd10))") def test_from_bits(self): class EnumA(Enum, shape=2): @@ -138,7 +138,7 @@ class EnumA(IntEnum, shape=signed(4)): B = -3 a = Signal(EnumA) self.assertRepr(a, "(sig a)") - self.assertRepr(a._format, "(format-enum (sig a) 'EnumA' (0 'A') (-3 'B'))") + self.assertRepr(a._format, f"(format-enum (sig a) '{EnumA.__qualname__}' (0 'A') (-3 'B'))") def test_enum_view(self): class EnumA(Enum, shape=signed(4)): @@ -153,7 +153,7 @@ class EnumB(Enum, shape=signed(4)): d = Signal(4) self.assertIsInstance(a, EnumView) self.assertIs(a.shape(), EnumA) - self.assertRepr(a, "EnumView(EnumA, (sig a))") + self.assertRepr(a, f"EnumView({EnumA.__qualname__}, (sig a))") self.assertRepr(a.as_value(), "(sig a)") self.assertRepr(a.eq(c), "(eq (sig a) (sig c))") for op in [ @@ -214,7 +214,7 @@ class FlagB(Flag, shape=unsigned(4)): c = Signal(FlagA) d = Signal(4) self.assertIsInstance(a, FlagView) - self.assertRepr(a, "FlagView(FlagA, (sig a))") + self.assertRepr(a, f"FlagView({FlagA.__qualname__}, (sig a))") for op in [ operator.__add__, operator.__sub__, @@ -260,17 +260,17 @@ class FlagB(Flag, shape=unsigned(4)): self.assertRepr(a == FlagA.B, "(== (sig a) (const 4'd4))") self.assertRepr(FlagA.B == a, "(== (sig a) (const 4'd4))") self.assertRepr(a != FlagA.B, "(!= (sig a) (const 4'd4))") - self.assertRepr(a | c, "FlagView(FlagA, (| (sig a) (sig c)))") - self.assertRepr(a & c, "FlagView(FlagA, (& (sig a) (sig c)))") - self.assertRepr(a ^ c, "FlagView(FlagA, (^ (sig a) (sig c)))") - self.assertRepr(~a, "FlagView(FlagA, (& (~ (sig a)) (const 3'd5)))") - self.assertRepr(a | FlagA.B, "FlagView(FlagA, (| (sig a) (const 4'd4)))") + self.assertRepr(a | c, f"FlagView({FlagA.__qualname__}, (| (sig a) (sig c)))") + self.assertRepr(a & c, f"FlagView({FlagA.__qualname__}, (& (sig a) (sig c)))") + self.assertRepr(a ^ c, f"FlagView({FlagA.__qualname__}, (^ (sig a) (sig c)))") + self.assertRepr(~a, f"FlagView({FlagA.__qualname__}, (& (~ (sig a)) (const 3'd5)))") + self.assertRepr(a | FlagA.B, f"FlagView({FlagA.__qualname__}, (| (sig a) (const 4'd4)))") if sys.version_info >= (3, 11): class FlagC(Flag, shape=unsigned(4), boundary=py_enum.KEEP): A = 1 B = 4 e = Signal(FlagC) - self.assertRepr(~e, "FlagView(FlagC, (~ (sig e)))") + self.assertRepr(~e, f"FlagView({FlagC.__qualname__}, (~ (sig e)))") def test_enum_view_wrong(self): class EnumA(Enum, shape=signed(4)): @@ -327,6 +327,4 @@ class EnumA(Enum, shape=unsigned(2)): B = 1 sig = Signal(EnumA) - self.assertRepr(EnumA.format(sig, ""), """ - (format-enum (sig sig) 'EnumA' (0 'A') (1 'B')) - """) + self.assertRepr(EnumA.format(sig, ""), f"(format-enum (sig sig) '{EnumA.__qualname__}' (0 'A') (1 'B'))") diff --git a/tests/test_lib_wiring.py b/tests/test_lib_wiring.py index d4b7d8cc5..79f96e292 100644 --- a/tests/test_lib_wiring.py +++ b/tests/test_lib_wiring.py @@ -635,7 +635,7 @@ def test_repr_inherit(self): class CustomInterface(PureInterface): pass intf = CustomInterface(Signature({}), path=()) - self.assertRegex(repr(intf), r"^$") + self.assertRegex(repr(intf), r"^<.+\.CustomInterface: .+?>$") class FlippedInterfaceTestCase(unittest.TestCase):