Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
ENH: switch mpl_toolkits to implicit namespace package (PEP 420)#25381
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
Uh oh!
There was an error while loading.Please reload this page.
setup.py Outdated
@@ -301,7 +301,6 @@ def make_release_tree(self, base_dir, files): | |||
package_dir={"": "lib"}, | |||
packages=find_packages("lib"), |
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.
Does this need to be changed tofind_namespace_packages
?
Thedocs for setuptools indicate that packages without__init__
will be omitted, and as mpl_toolkits no longer has a__init__
I suspect it falls into that category
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.
Good catch, I missed that ! I just updated the PR to include this. I don't have time right now to verify that it's safe to leaveinclude
andexclude
empty, but I can spend more time on it tomorrow if needed
Building the wheels as this change affects packaging |
I ran Missing
Wrongly included
|
I realized that |
https://github.com/matplotlib/matplotlib/actions/runs/4348842943 is an example run of the build-wheels on main (to save CI time we mostly do not build the wheels on every PR commit, but do build them on every merge to main and on the PRs we have the tag on). 👍 that the tinypages packaging should be excluded, that is something that exists purely for testing that the plot sphinx extension can read out parts of a .py file. |
thanks !
effectively this means that, in order to exclude |
I think we only hove one namespace package (mpl_toolkits) and I am very 👎🏻 on adding any more. Maybe we should just hard-code the one we have and leave it at that? |
That would be my preference too. Unfortunately using packages=find_packages("lib"),namespace_packages=["mpl_toolkits"], just like on the main branch, doesn't work:
I'm tended to think that's a shortcoming of |
Any reason we can't just do That adds the one implicit namespace package we want while ignoring the edgecase behavior of excludes. I mean, I may suggest a comment to indicate that it is namespace package related/that |
There is now discussion going on upstream with projects (e.g. zope and plone) who use this orders of magnitude more than we so it might be worth seeing how that shakes out. |
@tacaswell can you link those discussions here ? |
Okay, I've been digging into this (with the help of@henryiii) There are some... odd things happening through combinations of tools we use. It's not actually a problem if one source ismissing the Even on current main/releases, the Except on windows, where it is not the same version of the file, it is instead added by Delvewheel init.py contents""""""# start delvewheel patchdef_delvewheel_init_patch_1_3_3():importctypesimportosimportplatformimportsyslibs_dir=os.path.abspath(os.path.join(os.path.dirname(__file__),os.pardir,'matplotlib.libs'))is_pyinstaller=getattr(sys,'frozen',False)andhasattr(sys,'_MEIPASS')is_conda_cpython=platform.python_implementation()=='CPython'and (hasattr(ctypes.pythonapi,'Anaconda_GetVersion')or'packaged by conda-forge'insys.version)ifsys.version_info[:2]>= (3,8)andnotis_conda_cpythonorsys.version_info[:2]>= (3,10):ifnotis_pyinstalleroros.path.isdir(libs_dir):os.add_dll_directory(libs_dir)else:load_order_filepath=os.path.join(libs_dir,'.load-order-matplotlib-3.7.1')ifnotis_pyinstalleroros.path.isfile(load_order_filepath):withopen(os.path.join(libs_dir,'.load-order-matplotlib-3.7.1'))asfile:load_order=file.read().split()forlibinload_order:lib_path=os.path.join(os.path.join(libs_dir,lib))if (notis_pyinstalleroros.path.isfile(lib_path))andnotctypes.windll.kernel32.LoadLibraryExW(ctypes.c_wchar_p(lib_path),None,0x00000008):raiseOSError('Error loading {}; {}'.format(lib,ctypes.FormatError()))_delvewheel_init_patch_1_3_3()del_delvewheel_init_patch_1_3_3# end delvewheel patch By delvewheel's own docs, this behavior is problematic for namespace packages:
As, at least I'm pretty sure, we do not actually import any dlls directly within mpl-toolkits, perhaps we can configure delvewheel to ignore it? or lobby for better handling of namespace packages by upstream? So, deleting the The diff --git a/setup.py b/setup.pyindex 6d96e6b86c..4f43b2c425 100644--- a/setup.py+++ b/setup.py@@ -29,7 +29,7 @@ from pathlib import Path import shutil import subprocess-from setuptools import setup, find_packages, Distribution, Extension+from setuptools import setup, find_namespace_packages, Distribution, Extension import setuptools.command.build_ext import setuptools.command.build_py import setuptools.command.sdist@@ -301,7 +301,7 @@ setup( # Finally, pass this all along to setuptools to do the heavy lifting. ], package_dir={"": "lib"},- packages=find_packages("lib"),+ packages=find_namespace_packages("lib", exclude=["*baseline_images*", "*tinypages*", "*mpl-data*", "*web_backend*"]), namespace_packages=["mpl_toolkits"], py_modules=["pylab"], # Dummy extension to trigger build_ext, which will swap it out with This actuallydoes not change the wheels that are producedat all (but removes the removing the Ultimately, I don't even think there are that many downstreamsusing this feature, and at least one of them (basemap) is something we can control. The only other one I could find (at least via github search) ispygae/mpl_toolkits.clifford#10, which has not been touched in several years, and has not replied to@oscargus's issue opened in February. I greatly expect that if something was going to fail for users, it would have already happened, given the current state of the wheels. My leaning is to push forward down this path. |
Thank you so much@ksunden ! I've updated the PR with your suggestion. |
@@ -301,8 +301,10 @@ def make_release_tree(self, base_dir, files): | |||
], | |||
package_dir={"": "lib"}, | |||
packages=find_packages("lib"), | |||
namespace_packages=["mpl_toolkits"], | |||
packages=find_namespace_packages( |
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.
Not sure I readhttps://setuptools.pypa.io/en/latest/userguide/package_discovery.html#finding-simple-packages correctly, but could we usefind_packages(…, include=..)
? The exclude has the danger of unintentionally picking up other files we add in the future.
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.
I experimented a bit with it and so far I haven't been able to build matplotlib by supplyinginclude
instead ofexclude
. Even building an exhaustive list of all modules that should be included doesn't appear to work. I don't know if that's a bug in setuptools or if there's something I don't understand about this function.
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.
I think the key difference betweeninclude
andexclude
are a) liklihood of adding things that we want to go in each list. and b) ease of drawing the lines around the things we want included/excluded.
for a), I think it is more likely that we add python modules than folders we wish to exclude from being importable python modules (both could happen, but I'd expect python modules to be more common), so excludes are less likely to be updated
for b) I think that the things excluded appear directly next to things that want to be included, so I think it is much easier to specify exclusions.
I mean, it is just a list of strings at the end of the day, so if there is an easier way to produce the list we want, I'm not opposed, but lean towards using the tools provided to produce the lists.
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.
This will change under meson so lets not over think this.
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.
This does not make the windows situation worse and brings us inline with upstream.
Uh oh!
There was an error while loading.Please reload this page.
PR Summary
closes#25244
PR Checklist
Documentation and Tests
pytest
passes)Release Notes
.. versionadded::
directive in the docstring and documented indoc/users/next_whats_new/
.. versionchanged::
directive in the docstring and documented indoc/api/next_api_changes/
next_whats_new/README.rst
ornext_api_changes/README.rst