Jason Lowe-Power has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/51568 )
Change subject: python: Add check to SimObject for __init__
......................................................................
python: Add check to SimObject for __init__
When extending a SimObject by subclassing, if you don't call
`super().__init__()` you get a confusing infinite recursion error. The
infinite recursion occurs because SimObject overrides `__getattr__`. So,
if an attribute is accessed that is set in SimObject.__init__ but that
function hasn't been called there's a problem.
This patch adds another member variable to track if __init__ has been
called. This member variable is set to False in the *meta class* so
that it will always be available, even if __init__ has not been called.
There is one check for whether init has been called in the __getattr__
function. This is where I have experienced prior issues. This function
could be called from other SimObject functions, if needed.
With this change, a helpful error is shown telling the user to be sure
to call super().__init__ in the specific class that is missing the call.
Note: I have been bitten by this an embarrassing number of times. A
helpful error message would have saved me many hours.
Change-Id: Id919c540b23fc2783e203ef625bce3000ba808a9
Signed-off-by: Jason Lowe-Power <[email protected]>
---
M src/python/m5/SimObject.py
1 file changed, 41 insertions(+), 0 deletions(-)
diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py
index d18d879..923700d 100644
--- a/src/python/m5/SimObject.py
+++ b/src/python/m5/SimObject.py
@@ -479,6 +479,7 @@
cls._children = multidict() # SimObject children
cls._port_refs = multidict() # port ref objects
cls._instantiated = False # really instantiated, cloned, or
subclassed
+ cls._init_called = False # Used to check if __init__ overridden
# We don't support multiple inheritance of sim objects. If you
want
# to, you must fix multidict to deal with it properly. Non
sim-objects
@@ -1323,6 +1324,7 @@
self._ccObject = None # pointer to C++ object
self._ccParams = None
self._instantiated = False # really "cloned"
+ self._init_called = True # Checked so subclasses don't forget
__init__
# Clone children specified at class level. No need for a
# multidict here since we will be cloning everything.
@@ -1352,6 +1354,14 @@
for key,val in kwargs.items():
setattr(self, key, val)
+ def _check_init(self):
+ """Utility function to check to make sure that all subclasses call
+ __init__
+ """
+ if not self._init_called:
+ raise RuntimeError(f"{str(self.__class__)} is missing a call "
+ "to super().__init__()")
+
# "Clone" the current instance by creating another instance of
# this instance's class, but that inherits its parameter values
# and port mappings from the current instance. If we're in a
@@ -1385,6 +1395,8 @@
return ref
def __getattr__(self, attr):
+ self._check_init() # Check for inifinite recursion
+
if attr in self._deprecated_params:
dep_param = self._deprecated_params[attr]
dep_param.printWarning(self._name, self.__class__.__name__)
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/51568
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Id919c540b23fc2783e203ef625bce3000ba808a9
Gerrit-Change-Number: 51568
Gerrit-PatchSet: 1
Gerrit-Owner: Jason Lowe-Power <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s