From 8f3cd4ec3d224535b2d0cd5d33019c0c36970c19 Mon Sep 17 00:00:00 2001 From: awygle Date: Fri, 24 Apr 2020 14:15:00 -0700 Subject: [PATCH] hdl.ir: typecheck `convert(ports=)` more carefully. The `ports` argument to the `convert` functions is a frequent hotspot of beginner issues. Check to make sure it is either a list or a tuple, and give an appropriately helpful error message if not. Fixes #362. --- nmigen/hdl/ir.py | 6 ++++++ nmigen/test/test_hdl_ir.py | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/nmigen/hdl/ir.py b/nmigen/hdl/ir.py index b9963c1..b7161c2 100644 --- a/nmigen/hdl/ir.py +++ b/nmigen/hdl/ir.py @@ -532,6 +532,12 @@ class Fragment: if ports is None: fragment._propagate_ports(ports=(), all_undef_as_ports=True) else: + if not isinstance(ports, tuple) and not isinstance(ports, list): + msg = "`ports` must be either a list or a tuple, not {!r}"\ + .format(ports) + if isinstance(ports, Value): + msg += " (did you mean `ports=(,)`, rather than `ports=`?)" + raise TypeError(msg) mapped_ports = [] # Lower late bound signals like ClockSignal() to ports. port_lowerer = DomainLowerer(fragment.domains) diff --git a/nmigen/test/test_hdl_ir.py b/nmigen/test/test_hdl_ir.py index 2ea762a..b93537d 100644 --- a/nmigen/test/test_hdl_ir.py +++ b/nmigen/test/test_hdl_ir.py @@ -304,6 +304,16 @@ class FragmentPortsTestCase(FHDLTestCase): msg="Only signals may be added as ports, not (const 1'd1)"): f.prepare(ports=(Const(1),)) + def test_port_not_iterable(self): + f = Fragment() + with self.assertRaises(TypeError, + msg="`ports` must be either a list or a tuple, not 1"): + f.prepare(ports=1) + with self.assertRaises(TypeError, + msg="`ports` must be either a list or a tuple, not (const 1'd1)" + + " (did you mean `ports=(,)`, rather than `ports=`?)"): + f.prepare(ports=Const(1)) + class FragmentDomainsTestCase(FHDLTestCase): def test_iter_signals(self): cd1 = ClockDomain() -- 2.30.2