-
Notifications
You must be signed in to change notification settings - Fork 192
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
QualifiedNameProvider
matcher unusable with Windows process pools
#435
Comments
I don't quite follow what the "all" is doing, but a callable object may be picklable enough to find the next windows bug... class QualnameMatcher:
def __init__(self, name: str):
self.name = name
def __call__(self, qualnames) -> bool:
return all(n.name == self.name for n in qualnames)
...
return m.MatchMetadataIfTrue(
cst.metadata.QualifiedNameProvider,
QualnameMatcher(name), # <-- callable object now
) |
(the The class approach does indeed fix a pickle problem, but: KeyError: Call(
func=DoNotCare(),
args=[
ZeroOrMore(DoNotCare()),
Arg(
value=Name(value='None', lpar=DoNotCare(), rpar=DoNotCare(), metadata=DoNotCare()),
keyword=Name(value='min_magnitude', lpar=DoNotCare(), rpar=DoNotCare(), metadata=DoNotCare()),
equal=DoNotCare(), comma=DoNotCare(), star=DoNotCare(), whitespace_after_star=DoNotCare(), whitespace_after_arg=DoNotCare(), metadata=DoNotCare()
),
ZeroOrMore(DoNotCare())
],
lpar=DoNotCare(), rpar=DoNotCare(), whitespace_after_func=DoNotCare(), whitespace_before_args=DoNotCare(),
metadata=MatchMetadataIfTrue(
key=<class 'libcst.metadata.scope_provider.QualifiedNameProvider'>,
func=<hypothesis.extra.codemods.QualnameMatcher object at 0x000001B9FB3AD780>
)
)
Traceback (most recent call last):
File "libcst/codemod/_cli.py", line 294, in _execute_transform
output_tree = transformer.transform_module(input_tree)
File "libcst/codemod/_command.py", line 72, in transform_module
tree = super().transform_module(tree)
File "libcst/codemod/_codemod.py", line 108, in transform_module
return self.transform_module_impl(tree_with_metadata)
File "libcst/codemod/_visitor.py", line 32, in transform_module_impl
return tree.visit(self)
File "libcst/_nodes/module.py", line 91, in visit
result = super(Module, self).visit(visitor)
File "libcst/_nodes/base.py", line 225, in visit
_CSTNodeSelfT, self._visit_and_replace_children(visitor)
File "libcst/_nodes/module.py", line 75, in _visit_and_replace_children
body=visit_body_sequence(self, "body", self.body, visitor),
File "libcst/_nodes/internal.py", line 200, in visit_body_sequence
return tuple(visit_body_iterable(parent, fieldname, children, visitor))
File "libcst/_nodes/internal.py", line 172, in visit_body_iterable
new_child = child.visit(visitor)
File "libcst/_nodes/base.py", line 225, in visit
_CSTNodeSelfT, self._visit_and_replace_children(visitor)
File "libcst/_nodes/statement.py", line 424, in _visit_and_replace_children
body=visit_sequence(self, "body", self.body, visitor),
File "libcst/_nodes/internal.py", line 156, in visit_sequence
return tuple(visit_iterable(parent, fieldname, children, visitor))
File "libcst/_nodes/internal.py", line 140, in visit_iterable
new_child = child.visit(visitor)
File "libcst/_nodes/base.py", line 225, in visit
_CSTNodeSelfT, self._visit_and_replace_children(visitor)
File "libcst/_nodes/statement.py", line 331, in _visit_and_replace_children
value=visit_required(self, "value", self.value, visitor),
File "libcst/_nodes/internal.py", line 81, in visit_required
result = node.visit(visitor)
File "libcst/_nodes/base.py", line 225, in visit
_CSTNodeSelfT, self._visit_and_replace_children(visitor)
File "libcst/_nodes/expression.py", line 2343, in _visit_and_replace_children
args=visit_sequence(self, "args", self.args, visitor),
File "libcst/_nodes/internal.py", line 156, in visit_sequence
return tuple(visit_iterable(parent, fieldname, children, visitor))
File "libcst/_nodes/internal.py", line 140, in visit_iterable
new_child = child.visit(visitor)
File "libcst/_nodes/base.py", line 234, in visit
leave_result = visitor.on_leave(self, with_updated_children)
File "libcst/matchers/_visitors.py", line 510, in on_leave
self._matchers, getattr(self, f"leave_{type(original_node).__name__}", None)
File "libcst/matchers/_visitors.py", line 421, in _should_allow_visit
all_matchers, obj
File "libcst/matchers/_visitors.py", line 399, in _all_positive_matchers_true
if all_matchers[matcher] is None: Oddly this also only happens if I'm transforming multiple files. |
Can you point me at a more complete repro? I assume this is using your dummy change, but anything else? Against what target? I'm wondering if this is a latent issue with spawn, but if so we should be able to repro on linux too. |
Full script - just replacing the lambda with
|
Alright, spent another half-hour on this while waiting for an OS update to finish. The good news is I can repro on Linux. https://gist.github.com/thatch/a7b45eb23309a14cc78b8e42a58aff66 The middling news is, I think it's probably just a missing The bad news is I don't yet understand which one. I see in the repr your QualnameMatcher is a different id at least. I did try to set The way I "fixed" this in bowler was avoiding processes entirely -- search for "in_process" in https://github.com/facebookincubator/Bowler/blob/master/bowler/tool.py -- suboptimal performance, but works until I sort out a better way. What are your thoughts about doing something similar here? |
For HypothesisWorks/hypothesis#2712 I've already gone to a different approach - because I want to run multiple transformations on each file, I have a Of course I'd still like the codemod to be usable via |
I think this will be fixed by #1204. |
I have a MVP for HypothesisWorks/hypothesis#2705, but discovered that on Windows it can only format a single file at a time. The underlying problem is that
multiprocessing
on Windows works viaspawn
(vsfork
on Linux), and lambdas cannot be pickled but are practically required to use matchers. Related to #294 in that running tests on Windows would presumably detect this too?It's impractical to write a top-level function for each of the fifty-ish qualnames we want to handle, and unfortunately
functools.partial
has the same problem as lambdas.The obvious workaround is to give up some performance and run in a single process on Windows. Unfortunately that doesn't work either because
--jobs=1
still opens a process pool...The text was updated successfully, but these errors were encountered: