add mechanism to reload Cpython modules and mark graph dirty#11714
add mechanism to reload Cpython modules and mark graph dirty#11714mjkkirschner merged 17 commits intoDynamoDS:masterfrom
Conversation
raise event from button handle event in cpython engine fix python thread macros - no need for double lock. mixing thread state and gil state. shutdown when requested fix tests.
|
@mjkkirschner The location of the restart button makes sense! For the button style, could we not have the outline? |
Hey @Jingyi-Wen yep it looks just like the |
Got it. Looks good then! |
resx for add style resx for restart resx for tooltip on restart button
logging re enabled
add failing test modify tests to use different module names to avoid moving on disk error - missing mod spec
remove extra python
change tooltips and button text update tests fix bug with engine name
|
|
||
| #endregion | ||
|
|
||
| #region events |
There was a problem hiding this comment.
moved all DynamoModel events to DynamoModelEvents.cs file.
| <value>Learn more about Node Autocomplete feature.</value> | ||
| </data> | ||
| <data name="AddStyleButton" xml:space="preserve"> | ||
| <value>Add Style</value> |
There was a problem hiding this comment.
this was missing a resx property.
| if (CurrentWorkspace is HomeWorkspaceModel hmwsm) | ||
| { | ||
| RequestPythonReset?.Invoke(pythonEngine); | ||
| ResetEngine(true); |
There was a problem hiding this comment.
I think this is probably overkill, but this function is only triggered manually for now.
There was a problem hiding this comment.
by manually you mean via new button in preferences ?
When/if we move to something more reactive/automated....we will probably want to reset only the nodes that are affected by the .py reloads right ?
There was a problem hiding this comment.
Yes, that would be the ideal - BUT identifying those nodes without creating a circular reference is kind of a pain - we can use reflection or string matching if necessary.
There was a problem hiding this comment.
so by re executing all the nodes we are also taking care (refreshing) of potentially dangling objects that might still reference the old python files right ?
| <value>Reset CPython</value> | ||
| </data> | ||
| <data name="ResetCPythonButtonToolTip" xml:space="preserve"> | ||
| <value>Resets CPython environment by reloading modules.</value> |
There was a problem hiding this comment.
does this need to be more descriptive ?
all modules ? or some ? do we need to be specific I wonder ...
There was a problem hiding this comment.
thanks @pinzart90 - I was thinking to leave it a bit intentionally vague at this point so we can adjust it easily, but we could specify modules that have file attributes?
There was a problem hiding this comment.
not sure....maybe vague here and more specific in some dynamoDS wiki ?
There was a problem hiding this comment.
I've added https://github.com/DynamoDS/Dynamo/wiki/Work-in-progress-to-improve-Python-3-support#import-module-works-differently-in-ironpython-and-cpython-wip for docs, we can expand on specifics there and easily update it.
|
|
||
| IntPtr gs = PythonEngine.AcquireLock(); | ||
| try | ||
| { |
There was a problem hiding this comment.
this lock stuff is not needed anymore ?
There was a problem hiding this comment.
nope, I believe this is the same as using Py.GIL() - see the description and threading wiki that says as much.
fix issue with static logger reference
| import importlib.util | ||
| import os | ||
| def getInfoFile(module): | ||
| if not hasattr(module, '__file__') or module.__file__ is None: |
There was a problem hiding this comment.
maybe add comments to all these filters/conditions so that we know what the intention was (in case something goes wrong)
There was a problem hiding this comment.
good idea, will add some comments
There was a problem hiding this comment.
where did you find documentation for these module attributes ?
There was a problem hiding this comment.
Maybe we should add a comment (like in the importlib.reload documentation)
Reloading sys, __main__, builtins and other key modules is not recommended
https://docs.python.org/3.4/library/importlib.html#importlib.reload
There was a problem hiding this comment.
will do - these attributes (and this function) were modified from the autoreload.py script which is why I added attribution to this library in the license and about boxes.
| return py_filename | ||
|
|
||
|
|
||
| for modname,mod in sys.modules.copy().items(): |
There was a problem hiding this comment.
any idea why we need to make the copy() call ?
There was a problem hiding this comment.
yes because iterating over sys.modules and reloading modules directly modifies the keys in this dictionary during iteration.
Making a copy avoids modifying the dictionary we're iterating over.
update comments in reload snippet
|
@pinzart90 PTAL - I've added comments, please check if they are adequate. When this is merged, I will update the wiki with specifics and note that the change has been merged. |
|
@pinzart90 this passed on the parallel job here: though there were some flaky test failures we've seen before that occurred on the previous parallel run. I'm going to merge this, but if we see them get more frequent we can revert. |
Purpose
https://jira.autodesk.com/browse/DYN-3514
https://jira.autodesk.com/browse/DYN-2941
Update:
To help dynamo users who write their own python modules in cpython deal with the difference in module import/reload between cpython and ironPython- this PR adds a button to Reset CPython. What it does is to reload python modules that are backed by a .py file and are not named
__main__and a few other checks inspired byautoreloadhttps://ipython.org/ipython-doc/3/config/extensions/autoreload.html
The implementation is a subset of what autoreload does:
ie:
Currently, after the modules are reloaded, the Dynamo engine is reset and all nodes are marked dirty - this is very likely overkill. I think we would be safe simply marking the nodes dirty in topological order or disabling execution, marking all nodes dirty, and then re-enabling execution.
The goal is to have the DS GC collect the old objects created with out dated modules, the easiest way to do this is to rerun the graph.
also:
I had to change the use of python thread macros and lock code we started using in this PR: Tests for CPython3 Engine as well as for IronPython. #10631 - I think it was a bit confused (passing a pointer from the GIL mutex to a macro that expected a pointer to a different mutex).
https://github.com/pythonnet/pythonnet/wiki/Threading
acquireandreleaselock calls as I believe using theGIL()call is analogous to that.I ended up using static internal events to avoid having any references on DSCPython or PythonNet in DynamoCore/DynamoCoreWPF - I guess I could also use interfaces and a singleton or something. Feedback welcome there.
Modified the style for
flatButtonso that its center aligned @Jingyi-Wen fyi. (that affects the group add stye button)TODO:
Declarations
Check these if you believe they are true
*.resxfiles