elif isinstance(obj, Elaboratable):
code = obj.elaborate.__code__
obj._MustUse__used = True
- obj = obj.elaborate(platform)
+ new_obj = obj.elaborate(platform)
elif hasattr(obj, "elaborate"):
warnings.warn(
message="Class {!r} is an elaboratable that does not explicitly inherit from "
category=RuntimeWarning,
stacklevel=2)
code = obj.elaborate.__code__
- obj = obj.elaborate(platform)
+ new_obj = obj.elaborate(platform)
else:
raise AttributeError("Object {!r} cannot be elaborated".format(obj))
- if obj is None and code is not None:
+ if new_obj is obj:
+ raise RecursionError("Object {!r} elaborates to itself".format(obj))
+ if new_obj is None and code is not None:
warnings.warn_explicit(
message=".elaborate() returned None; missing return statement?",
category=UserWarning,
filename=code.co_filename,
lineno=code.co_firstlineno)
+ obj = new_obj
def __init__(self):
self.ports = SignalDict()
from .utils import *
-class BadElaboratable(Elaboratable):
+class ElaboratesToNone(Elaboratable):
def elaborate(self, platform):
return
+class ElaboratesToSelf(Elaboratable):
+ def elaborate(self, platform):
+ return self
+
+
class FragmentGetTestCase(FHDLTestCase):
- def test_get_wrong(self):
+ def test_get_wrong_none(self):
with self.assertRaisesRegex(AttributeError,
r"^Object None cannot be elaborated$"):
Fragment.get(None, platform=None)
r"^\.elaborate\(\) returned None; missing return statement\?$"):
with self.assertRaisesRegex(AttributeError,
r"^Object None cannot be elaborated$"):
- Fragment.get(BadElaboratable(), platform=None)
+ Fragment.get(ElaboratesToNone(), platform=None)
+
+ def test_get_wrong_self(self):
+ with self.assertRaisesRegex(RecursionError,
+ r"^Object <.+?ElaboratesToSelf.+?> elaborates to itself$"):
+ Fragment.get(ElaboratesToSelf(), platform=None)
class FragmentGeneratedTestCase(FHDLTestCase):