Skip to content

Update model.py #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open

Conversation

ren-oz
Copy link

@ren-oz ren-oz commented Mar 14, 2022

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:

from python_actr import ACTR, Model

env = Model()
env.a1 = ACTR()
print(env.get_children())  # List is empty
print(env._children)  # Raises AttributeError: "'Model' object has no attribute '_children'."
env.a2 = ACTR()
print(env.get_children())  # List has only one value
print(env._children)  # No exception raised, but only a2 is in children!

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:

for k, v in list(self.__dict__.items()):
    if k[0] != '_' and k != 'parent' and isinstance(v, Model):
        if not v.__converted:
            v.__convert(parent=self)

This leads to the child instance having its parent attribute set, and thus the parent _children attribute does not get set due to if 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.

ren-oz added 5 commits March 14, 2022 04:38
Cleaned up old comments, made code PEP-8 compliant. Moved "self.__dict__[key] = value" to the end of the __setattr__ method in class Model to resolve a bug related to setting children (first child did not initialize as expected).
Cleaned up scheduler.py (PEP-8). Deleted heapq try block. Changed old string formatting to Python 3 f-strings. Added logic for deprecated cmp function. Renamed SchedulerError to SchedulerException and moved to own module for package organization purposes.
Added experimental (dev) folder for new (unofficial) modules. Updated setup.py to automatically find new modules, excluding tests and experimental.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant