Skip to content
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

ENH: Prefer using visit_Constant #63

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

jhlegarreta
Copy link
Contributor

Prefer using visit_Constant instead of visit_Num and visit_Str: both were deprecated since Python 3.8.

Fixes:

tract_querier/tests/test_query_eval.py: 40 warnings
tract_querier/tests/test_query_files.py: 6527 warnings
  /opt/hostedtoolcache/Python/3.9.20/x64/lib/python3.9/ast.py:407:
 DeprecationWarning: visit_Num is deprecated; add visit_Constant
    return visitor(node)

and

tract_querier/tests/test_query_eval.py: 1 warning
tract_querier/tests/test_query_files.py: 24 warnings
  /opt/hostedtoolcache/Python/3.9.20/x64/lib/python3.9/ast.py:407:
 DeprecationWarning: visit_Str is deprecated; add visit_Constant
    return visitor(node)

raised for example in:
https://github.com/demianw/tract_querier/actions/runs/12187495803/job/33998410948?pr=61#step:6:75 and
https://github.com/demianw/tract_querier/actions/runs/12187495803/job/33998410948?pr=61#step:6:80

Documentation:
https://docs.python.org/3/library/ast.html#ast.NodeVisitor.visit_Constant

@jhlegarreta jhlegarreta force-pushed the FixAstVisitNumWarnings branch from 518c822 to 0af32a2 Compare December 5, 2024 21:20
@jhlegarreta jhlegarreta marked this pull request as draft December 5, 2024 22:04
@jhlegarreta jhlegarreta force-pushed the FixAstVisitNumWarnings branch from 0af32a2 to 8d0bee1 Compare December 5, 2024 22:25
self.tractography_spatial_indexing.
crossing_labels_tracts[node.n]
def visit_Constant(self, node):
if type(node.value) in [int, float, complex]:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is better done by isinstance(node.value, (int, float, complex)) or isinstance(node.value, numbers.Number

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure: I had first tried with isinstance(node.value, (int, float, complex)) and the if was evaluated to True for a node.value that was a string, and thus the test was failing. I will revisit as time permits.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to isinstance in e81a797. See the result of the debugging in the below comment.

node
)
def visit_Constant(self, node):
if type(node.s) == str:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this too is usually better as isinstance(node.s, str). Most probably this logic will need to be mixed with the one in line 555. Probably calling two methods, one for each type of constant

Copy link
Contributor Author

@jhlegarreta jhlegarreta Dec 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what's going on here: when debugging locally the change for EvaluateQueries seemed to work fine, but this one was either being evaluated to False for some cases or not being called at all (cannot remember) and thus the tests were failing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you happen to come up with a fix, it would be very much appreciated.

Copy link
Contributor Author

@jhlegarreta jhlegarreta Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I have digged into this a little bit more. I have used the following subset of labels (I named the file my_JHU_MNI_SS_WMPM_Type_II_subset.qry):

Fornix_column_and_body.left |= 51
Genu_of_corpus_callosum.left |= 52
Body_of_corpus_callosum.left |= 53
Splenium_of_corpus_callosum.left |= 54
Fornix_column_and_body.right |= 116
Genu_of_corpus_callosum.right |= 117
Body_of_corpus_callosum.right |= 118
Splenium_of_corpus_callosum.right |= 119

for the following subset of queries (named the file mori_queries_ssubset.qry):

import my_JHU_MNI_SS_WMPM_Type_II_subset.qry

HEMISPHERE.left |= '*.left'
HEMISPHERE.right |= '*.right'

corpus_callosum.side |= Genu_of_corpus_callosum.side or Body_of_corpus_callosum.side or Splenium_of_corpus_callosum.side

and using that file as the filename in test_query_files. It turns out that the method tract_querier.query_processor.RewritePreprocess.visit_Constant is being called when parsing the 51 part of Fornix_column_and_body.left |= 51, and since that is not a string instance, the new_node = self.visit(old_value) returned is None by the above visit_Constant block. Thus, the ast.NodeTransformer.generic_visit method will execute delattr(node, field), and the value field will get deleted. Further down the pipeline in tract_querier, at tract_querier.query_processor.EvaluateQueries.process_assignment we get an error as node.value does not exist:

E           AttributeError: 'AugAssign' object has no attribute 'value'

This does not happen in the previous implementation as tract_querier.query_processor.RewritePreprocess.visit_Str is not being called for the 51 part.

Following the above, and these:
https://github.com/python/cpython/blob/main/Lib/ast.py#L504
https://github.com/python/cpython/blame/9f9dac0a4e58d5c72aa3b644701cb155c009cb2c/Lib/ast.py#L415
following: python/cpython#81098 (comment)

adding

else:
    return self.generic_visit(node)

to tract_querier.query_processor.RewritePreprocess.visit_Constant
makes all the tests pass locally, including all test data query files.

And the CI shows that the related warnings are gone, e.g.:
https://github.com/demianw/tract_querier/actions/runs/12319259839/job/34385895407?pr=63#step:6:121
https://github.com/demianw/tract_querier/actions/runs/12319259839/job/34385896307?pr=63

The remaining warnings are related to NiBabel. x-ref PR #64.

@demianw Let me know if the solution here is satisfying enough or not. I'd like to test on in vivo human data with some results with previous versions to be completely sure that this does not change the current behavior. If you happen to have some examples, would be happy to try.

Prefer using `visit_Constant` instead of `visit_Num` and `visit_Str`:
both were deprecated since Python 3.8.

Fixes:
```
tract_querier/tests/test_query_eval.py: 40 warnings
tract_querier/tests/test_query_files.py: 6527 warnings
  /opt/hostedtoolcache/Python/3.9.20/x64/lib/python3.9/ast.py:407:
 DeprecationWarning: visit_Num is deprecated; add visit_Constant
    return visitor(node)
```

and
```
tract_querier/tests/test_query_eval.py: 1 warning
tract_querier/tests/test_query_files.py: 24 warnings
  /opt/hostedtoolcache/Python/3.9.20/x64/lib/python3.9/ast.py:407:
 DeprecationWarning: visit_Str is deprecated; add visit_Constant
    return visitor(node)
```

raised for example in:
https://github.com/demianw/tract_querier/actions/runs/12187495803/job/33998410948?pr=61#step:6:75
and
https://github.com/demianw/tract_querier/actions/runs/12187495803/job/33998410948?pr=61#step:6:80

Documentation:
https://docs.python.org/3/library/ast.html#ast.NodeVisitor.visit_Constant
@jhlegarreta jhlegarreta force-pushed the FixAstVisitNumWarnings branch from e81a797 to 795c003 Compare December 13, 2024 16:21
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.

2 participants