-
Notifications
You must be signed in to change notification settings - Fork 38
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
Patch plugin cache #748
Patch plugin cache #748
Conversation
Checked also with different straxen plugins that things are now working as expected. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, thanks.
The only thing that bothers me a bit is modifying targets
inside the loop iterating over it. I dont think this is defined behavior by the python spec so a future implementation of the list object may break it. Especially since python will be removing the GIL soon, CPython core implementations are expected to change in the near future.
Maybe go with the standard way of doing this
while targets:
target = targets.pop(0)
...
Sorry, based on your comment I am not sure whether you think the for-loop, or the appending-to-the-same-list is the problem. The former I agree, can be changed into a while loop. The latter cannot be changed as I do not know my full list of targets at the beginning of the loop (in the sense that I do not know the list of plugins my actual target depends on). So using pop does not work ( At least I cannot see how this would work). The only other solution I could think about is defining some "global" dictionary and do some recursive function call like it is done in |
So something like this: plugins = {}
def _get_depndent_plugins(targets):
for target in targets:
target_plugin = cached_plugins[target]
for provides in target_plugin.provides:
plugins[provides] = target_plugin
[_get_depndent_plugins((target,)) for target in target_plugin.depends_on]
_get_depndent_plugins(targets) But I liked the other solution better because it is easier to understand. However, if you are saying that this might lead to issues in the future we should move to this solution. |
Sorry if I wasnt explicit enough. for loops in python use iterators, the next value is returned from the iterator object and not the original object. In many list-like implementations including the current implementation of the builtin list, the iterator object returned is the original object so modifying it inside the loop can work but its undefined behavior that can change with the implementation of list in CPython. The while loop does not create an iterator, and therefore should always work. while targets:
target = targets.pop(0)
if target in plugins:
continue
target_plugin = cached_plugins[target]
for provides in target_plugin.provides:
plugins[provides] = target_plugin
targets += list(target_plugin.depends_on) |
I am learning new things now, nice. How does the while loop then work if not with iterators? (It is hard to find any information about this by simply searching for it. You always get things like "how to write a while loop in python...") So in a while loop the iteration is not done on the original object but the modified one? |
the while loop will re-evaluates the expression for thuthyness at every iteration and executes the code body if the expression is true, calling |
Ah sorry, no I was more curious why while list:
item = list.pop(0)
list.append(...) #modify list is okay but for item in list:
list.append(...) #modify list is not. For me both are iterators. I understood from your comment above (maybe wrongly), that a for-loop is only defined to loop over the original "list" without it being modifications, and in the while loop "list" is reevaluated after each iteration. |
The python spec. The for loop only evaluates the expression once. The while loop evaluates it at every execution |
Cool thanks, was an interesting discussion. I will push the while loop change. |
Maybe the confusion is on what an iterator is in python? The for loop first evaluates the expression to get an iterator (calling |
Yes this I knew, and due to this I would have though that modifying the list in a for loop would be save. Because the iterator only knows about the next object while iterating and only stops if |
Ah yes, now i understand. The issue is that there is nothing in the spec that tells you to return the original object from |
Thanks, was a nice discussion :D I can already go home now as I learned something today :D |
Should be ready to be merged now. |
oops, forgot to approve :) |
What is the problem / what does the code in this PR do
Adds fix and test for #747