Skip to content

MNT: Compatibility with Python 3.11 - #13614

Merged
pllim merged 8 commits into
astropy:mainfrom
Cadair:311_testing
Sep 14, 2022
Merged

pllim merged 8 commits into
astropy:mainfrom
Cadair:311_testing

Conversation

@Cadair

@Cadair Cadair commented Sep 8, 2022 •

Copy link
Copy Markdown
Member

Fix #13522

Fix #13224

@github-actions

github-actions Bot commented Sep 8, 2022

Copy link
Copy Markdown
Contributor

👋 Thank you for your draft pull request! Do you know that you can use [ci skip] or [skip ci] in your commit messages to skip running continuous integration tests until you are ready?

@mhvk

mhvk commented Sep 8, 2022

Copy link
Copy Markdown
Contributor

Good to try, though scipy is not installing, so I guess this needs a bit more time!?

@Cadair

Cadair commented Sep 9, 2022

Copy link
Copy Markdown
Member Author

Ok, after building scipy from source I have got actual errors in our test suite that are presumably down to Python 3.11:

 FAILED ../../.tox/py311-test-devdeps/lib/python3.11/site-packages/astropy/coordinates/tests/test_pickle.py::test_simple_object[0-StaticMatrixTransform-args6-kwargs6-False]
FAILED ../../.tox/py311-test-devdeps/lib/python3.11/site-packages/astropy/coordinates/tests/test_pickle.py::test_simple_object[1-StaticMatrixTransform-args6-kwargs6-False]
FAILED ../../.tox/py311-test-devdeps/lib/python3.11/site-packages/astropy/coordinates/tests/test_pickle.py::test_simple_object[-1-StaticMatrixTransform-args6-kwargs6-False]
FAILED ../../.tox/py311-test-devdeps/lib/python3.11/site-packages/astropy/cosmology/flrw/tests/test_base.py::TestFLRW::test_name
FAILED ../../.tox/py311-test-devdeps/lib/python3.11/site-packages/astropy/cosmology/flrw/tests/test_lambdacdm.py::TestLambdaCDM::test_name
FAILED ../../.tox/py311-test-devdeps/lib/python3.11/site-packages/astropy/cosmology/flrw/tests/test_lambdacdm.py::TestFlatLambdaCDM::test_name
FAILED ../../.tox/py311-test-devdeps/lib/python3.11/site-packages/astropy/cosmology/flrw/tests/test_w0cdm.py::TestwCDM::test_name
FAILED ../../.tox/py311-test-devdeps/lib/python3.11/site-packages/astropy/cosmology/flrw/tests/test_w0cdm.py::TestFlatwCDM::test_name
FAILED ../../.tox/py311-test-devdeps/lib/python3.11/site-packages/astropy/cosmology/flrw/tests/test_w0wacdm.py::Testw0waCDM::test_name
FAILED ../../.tox/py311-test-devdeps/lib/python3.11/site-packages/astropy/cosmology/flrw/tests/test_w0wacdm.py::TestFlatw0waCDM::test_name
FAILED ../../.tox/py311-test-devdeps/lib/python3.11/site-packages/astropy/cosmology/flrw/tests/test_w0wzcdm.py::Testw0wzCDM::test_name
FAILED ../../.tox/py311-test-devdeps/lib/python3.11/site-packages/astropy/cosmology/flrw/tests/test_wpwazpcdm.py::TestwpwaCDM::test_name
FAILED ../../.tox/py311-test-devdeps/lib/python3.11/site-packages/astropy/cosmology/tests/test_core.py::TestCosmology::test_name
FAILED ../../.tox/py311-test-devdeps/lib/python3.11/site-packages/astropy/table/tests/test_pprint.py::TestColumnsShowHide::test_remove[pprint_exclude_names]
FAILED ../../.tox/py311-test-devdeps/lib/python3.11/site-packages/astropy/table/tests/test_pprint.py::TestColumnsShowHide::test_remove[pprint_include_names]
FAILED ../../.tox/py311-test-devdeps/lib/python3.11/site-packages/astropy/time/tests/test_mask.py::test_mask_not_writeable

So that's errors in coordinates @eteq @adrn @eerovaher, time @mhvk @taldcroft, cosmology @astropy/cosmology and table

@pllim

pllim commented Sep 9, 2022 •

Copy link
Copy Markdown
Member

astropy/coordinates/tests/test_pickle.py

>       dict_a = a.__getstate__() if hasattr(a, '__getstate__') else a.__dict__
E       TypeError: unbound method object.__getstate__() needs an argument

https://docs.python.org/3.11/library/pickle.html#object.getstate

Changed in version 3.11: Added the default implementation of the __getstate__() method in the object class.

cosmology

Maybe just a matter of changing the expected error message for Python 3.11? Or maybe this is a symptom of something else, not sure.

        with pytest.raises(AttributeError, match="can't set"):
>           cosmo.name = None
E           AttributeError: property 'name' of 'SubFLRW' object has no setter

table/tests/test_pprint.py

Looks like del is broken?

        t = self.t
        t_hide_show = getattr(t, attr)
        t_hide_show.set(['a', 'b'])
        del t['a']
>       assert t_hide_show() == ('b',)
E       AssertionError: assert ('a', 'b') == ('b',)
E         At index 0 diff: 'a' != 'b'
E         Left contains one more item: 'b'
E         Full diff:
E         - ('b',)
E         + ('a', 'b')

astropy/time/tests/test_mask.py

The error message changed. Maybe same problem as cosmology above.

        t = Time('2000:001')
        with pytest.raises(AttributeError) as err:
            t.mask = True
>       assert "can't set attribute" in str(err.value)
E       assert "can't set attribute" in "property 'mask' of 'Time' object has no setter"

@nstarman

nstarman commented Sep 9, 2022

Copy link
Copy Markdown
Member

cosmology

Maybe just a matter of changing the expected error message for Python 3.11? Or maybe this is a symptom of something else, not sure.

        with pytest.raises(AttributeError, match="can't set"):
>           cosmo.name = None
E           AttributeError: property 'name' of 'SubFLRW' object has no setter

@pllim. That appears to be the case. property appears to have changed its error message.

@Cadair

Cadair commented Sep 9, 2022

Copy link
Copy Markdown
Member Author

I am very happy for people to push to this PR if we want to use it as the place to address all these issues.

@mhvk

mhvk commented Sep 9, 2022

Copy link
Copy Markdown
Contributor

@nstarman - if you have a chance to fix the cosmology error message change, could you do the time one too?

@nstarman

nstarman commented Sep 9, 2022

Copy link
Copy Markdown
Member

@nstarman - if you have a chance to fix the cosmology error message change, could you do the time one too?

Cadair#24

@dhomeier

dhomeier commented Sep 10, 2022 •

Copy link
Copy Markdown
Contributor

Maybe just a matter of changing the expected error message for Python 3.11? Or maybe this is a symptom of something else, not sure.

No, seems to be all: python/cpython#31311

So in principle they could be all dealt with by defining a custom _no_setter error string depending on sys.version_info >= (3, 11) or not. Is that something that could go into astropy.tests.helper?

@dhomeier

Copy link
Copy Markdown
Contributor

https://docs.python.org/3.11/library/pickle.html#object.__getstate__

Changed in version 3.11: Added the default implementation of the __getstate__() method in the object class.

So previously

dict_a = a.__getstate__() if hasattr(a, '__getstate__') else a.__dict__

was simply falling back to a.__dict__.
Should it check now if a is a class, rather than an instance thereof (how?) and then call either a().__getstate__() or a.__getstate__(a)?

@taldcroft

Copy link
Copy Markdown
Member

See #13637 for discussion of the test_pprint problem.

@pllim

pllim commented Sep 11, 2022

Copy link
Copy Markdown
Member

Not sure what is going on. I don't see the Python 3.11 job run after merging Nathan's fix.

@pep8speaks

pep8speaks commented Sep 12, 2022 •

Copy link
Copy Markdown

Hello @Cadair 👋! It looks like you've made some changes in your pull request, so I've checked the code again for style.

There are no PEP8 style issues with this pull request - thanks! 🎉

Comment last updated at 2022-09-13 14:14:26 UTC

@pllim

pllim commented Sep 12, 2022

Copy link
Copy Markdown
Member

Less failures now.

  • The time warning message just needs to be updated like cosmology.
  • The scipy deprecation warning is unrelated to Python 3.11.

So, the remaining compatibility issue we need to figure out is the __getstate__ usage in astropy/coordinates/tests/test_pickle.py. @adrn ?

@adrn

adrn commented Sep 12, 2022

Copy link
Copy Markdown
Member

It looks like the coordinates failure actually comes from calling astropy.tests.helper.check_pickling_recovery(), see the first line of:

dict_a = a.__getstate__() if hasattr(a, '__getstate__') else a.__dict__

I don't have time to look at this today but that is where I would start.

@dhomeier

dhomeier commented Sep 12, 2022 •

Copy link
Copy Markdown
Contributor

It looks like the coordinates failure actually comes from calling astropy.tests.helper.check_pickling_recovery(), see the first line of:

Yes, see #13614 (comment).
Just not sure about the best way to treat classes vs. class instances here.

@nstarman

nstarman commented Sep 12, 2022 •

Copy link
Copy Markdown
Member

Should it check now if a is a class, rather than an instance thereof (how?) and then call either a().__getstate__() or a.__getstate__(a)?

https://docs.python.org/3.8/library/inspect.html#inspect.isclass ? Is this what you mean?

@dhomeier

Copy link
Copy Markdown
Contributor

Should it check now if a is a class, rather than an instance thereof (how?) and then call either a().__getstate__() or a.__getstate__(a)?

https://docs.python.org/3.8/library/inspect.html#inspect.isclass ? Is this what you mean?

Yes, thanks! As there is no general info on the correct initialisation signature for a(), this should probably fork to a.__getstate__(a).

@Cadair

Cadair commented Sep 12, 2022

Copy link
Copy Markdown
Member Author

I just rebased this to clear up the history. More pushes or PRs to main are welcome.

Comment thread astropy/tests/helper.py Outdated
Comment on lines +413 to +420
if hasattr(a, '__getstate__'):
dict_a = a.__getstate__(a) if inspect.isclass(a) else a.__getstate__()
else:
dict_a = a.__dict__

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be good to add a comment here to clarify that the hasattr check is only needed for Python < 3.11.

@dhomeier dhomeier Sep 12, 2022 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For class inputs. I don't know if the function might ever be called with some other a input that does not implement __getstate__. Could use some comment though – in theory I guess this could also be called in Python < 3.11 for some class defining their own custom __getstate__.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If Python 3.11 implemented __getstate__() in object then hasattr(a, "__getstate__") will be true for any a. The check is therefore only needed until 3.11 is the minimum supported Python version. A comment would record that it's safe to simplify once support for older versions of Python is dropped.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

some class defining their own custom __getstate__

Though obviously defining one without parameters would break stuff in 3.11+...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

OK, I misremembered, thought it was only implemented for class.
But in that case it is certainly more likely to get an a with a different __getstate__ signature – e.g. in the original example, astropy.coordinates.builtin_frames.ICRS.__getstate__ has one required argument, while astropy.coordinates.builtin_frames.ICRS().__getstate__ takes no arguments.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You mean for using some auto-refactoring tool?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

More like grep heh heh

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Well, grep should find the comment as well; humans might not ;-)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh, well, if we do it Eero's way, the code will actually error when we remove that flag from compat, so maybe that is better.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I pushed a commit that would hopefully settle this debate once and for all.

@pllim pllim mentioned this pull request Sep 12, 2022
7 of 11 tasks
@dhomeier

dhomeier commented Sep 12, 2022 •

Copy link
Copy Markdown
Contributor

This must be a new one for scipy-dev

>       warnings.warn(msg, category=DeprecationWarning,
E       DeprecationWarning: scipy.misc.ascent has been deprecated in SciPy v1.10.0; and will be completely removed in SciPy v1.12.0. Dataset methods have moved into the scipy.datasets module. Use scipy.datasets.ascent instead.

Just as a note for the final setup: this is obviously not Python 3.11 with minimal dependencies using py311-test-devdeps.

@Cadair

Cadair commented Sep 12, 2022

Copy link
Copy Markdown
Member Author

Yeah it definitely isn't, I was just merrily hacking away at the CI to get it down to one job.

Comment thread astropy/time/tests/test_mask.py Outdated
@Cadair

Cadair commented Sep 14, 2022

Copy link
Copy Markdown
Member Author

I tired to group the commits into the changes, hopefully the commits all make sense by themselves now.

@pllim pllim left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM! What a beautiful collaboration. Thank you, everyone!

Stuart, thanks for getting rid of my "ooops" commit message. 😆

Comment thread docs/changes/13614.other.rst Outdated
@Cadair Cadair added the zzz 💤 merge-when-ci-passes Do not use: We have auto-merge option now. label Sep 14, 2022
@pllim
pllim merged commit 616f382 into astropy:main Sep 14, 2022
@lumberbot-app

This comment was marked as resolved.

@lumberbot-app

This comment was marked as resolved.

@Cadair
Cadair deleted the 311_testing branch September 14, 2022 13:39
@pllim

pllim commented Sep 14, 2022

Copy link
Copy Markdown
Member

Of course... autobackport would be too easy...

@pllim

pllim commented Sep 14, 2022

Copy link
Copy Markdown
Member

I will do the manual backports, FYI.

pllim added a commit to pllim/astropy that referenced this pull request Sep 14, 2022
Merge pull request astropy#13614 from Cadair/311_testing

MNT: Compatibility with Python 3.11
(cherry picked from commit 616f382)
pllim added a commit to pllim/astropy that referenced this pull request Sep 14, 2022
Merge pull request astropy#13614 from Cadair/311_testing

MNT: Compatibility with Python 3.11
(cherry picked from commit 616f382)
Comment thread tox.ini
devdeps,mpldev: git+https://github.com/matplotlib/matplotlib.git#egg=matplotlib
devdeps: scipy>=0.0.dev0
devdeps: numpy>=0.0.dev0
devdeps,mpldev: matplotlib>=0.0.dev0

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@Cadair , this picked up matplotlib 3.6.0rc2 , not a dev version. Is this supposed to happen?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

hmmm where?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

pllim added a commit that referenced this pull request Sep 15, 2022
…5.1.x

Backport PR #13614 on branch v5.1.x (MNT: Compatibility with Python 3.11)
pllim added a commit to pllim/astropy that referenced this pull request Sep 15, 2022
Merge pull request astropy#13614 from Cadair/311_testing

MNT: Compatibility with Python 3.11
(cherry picked from commit 616f382)
pllim added a commit that referenced this pull request Sep 15, 2022
…5.0.x

Backport PR #13614 on branch v5.0.x (MNT: Compatibility with Python 3.11)
@dhomeier

Copy link
Copy Markdown
Contributor

Does anyone know what the scipy==1.10.0.dev0 installed by the new devdeps resolves to? Unlike e.g. numpy>=0.0.dev0 this just installs under that label, which however is unknown to my pip, so how to figure out which commit or tag the tests are run against?

@pllim

pllim commented Nov 16, 2022

Copy link
Copy Markdown
Member

The test header should say. This is from the last successful run on main:

2022-11-16T07:15:38.6203833Z Package versions: 
2022-11-16T07:15:38.6204055Z Numpy: 1.24.0.dev0+1068.g6aacc5167
2022-11-16T07:15:38.6204634Z Scipy: 1.10.0.dev0+2188.58e90e3

@dhomeier

Copy link
Copy Markdown
Contributor

Thanks! Looked too high up, which was apparently still the header from pip.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Python 3.11 testing zzz 💤 merge-when-ci-passes Do not use: We have auto-merge option now.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Test failures with Python 3.11 TST: Test against Python 3.11

9 participants