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

Reply via email to