This is very cool, and it almost works for me, so I went spelunking to figure out what was wrong with the last bit. I notice a few things. Sorry this brain dump is kind of raw - Iām trying to put it out there before I knock off for the day.
Two minor ones first:
- When you collect the imports from
#export
ed cells, that variable imports
is always the empty string, because split_flags_and_code
returns a tuple, so line
is actually taking on values from that tuple, each of which becomes a list of either tags or lines. So when youāre on the list of lines and you do if 'import' in line
, youāre actually checking if the string āimportā is exactly equal to the entirety of any of the lines, which it never is. Might not be that big of a deal because anything you would have imported this way comes in when you import every member of the entire module.
- Because youāre
insert
ing into position 0 of nb['cells']
as you iterate in order through the exports, youāre actually reversing them in the resulting notebook. Didnāt end up being my problem, but it might cause trouble for other people if the order matters.
Then I found the actual cause of my problem:
Setup:
I do a bunch of monkey patching in my tests, to mock out stuff each function under test calls, and in this case in the notebook I have an exported version of an object for production set to some variable, and another version of that object that overwrites it (set to the same variable) right afterwards thatās configured differently for test, and itās not exported. Then, an exported function closes over a method call on this object.
Test
So then when Iām running your script, it imports the production version of the object and the version of the function pointed at that version of the variable. I overwrite that variable with the test version in my non-exported test code, but in this test run only the method is still pointed at the production version of the variable, so when I monkeypatch stuff in the variable as always, it doesnāt affect the method call, and it just goes ahead and runs code I donāt want it to.
One-off fix
I was able to resolve the problem in a one-off way while I was messing around with your code in a notebook by explicitly setting themodule.variable = variable
after I had instantiated the test version of variable
in my tests.
This suggests to me that we might be able to do something clever like checking whether any left-hand-side of an equals sign in the userās unexported cells shadows something we import from a module, and then explicitly add a line after that shadowing to propagate that shadowing back into the module as well⦠That seems like it would work, but maybe thereās an easier way Iām not thinking of right now.