Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Cleaned up (deleted) old comments, made code PEP-8 compliant. Updated Python 2 string formatting to Python 3 f-strings. Fixed bug related to initializing children -- does not work as expected.
The issue can be recreated with the following code:
This is resolved by moving
self.__dict__[key] = value
to the end of the__setattr__
method in class Model.The problem occurs because (if I am correct) whenever a class attribute of type Model is set for the first time in a parent Model instance (e.g., an environment), the parent class instance is forced into a conversion method (
self._ensure_converted
). During this conversion process, all Model instances in the parent namespace are also converted via:This leads to the child instance having its parent attribute set, and thus the parent
_children
attribute does not get set due toif getattr(value, 'parent', None) is not None: pass
Interestingly, commenting out the
for k, v in list(self.__dict__.items()): [...]
block doesn't seem to break anything (hasn't been extensively tested though) and also resolves the issue as the children conversion happens later on in__setaatr__
along with an explicit setting of the parent_children
attribute. But this is a larger block of code and must have been put in for some reason, so I'm hesitant to commit its deletion in this pull request.Future changes to consider:
Ultimately, the methods in this file have low cohesion and are responsible for a lot of unrelated work. Refactoring
model.py
to delegate single responsibilities to other methods is something to strongly consider as it would help make maintenance easier in the event of future bugs. It should also help in developing new subclasses with less pain and ideally favour extensibility. That said, this must be done with care as much is built on top of this module so the changes could snowball. I am happy to assist in this process with pull requests if the team deems it worthwhile.