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

Support pkgsrc variation #16

Closed
0-wiz-0 opened this issue Aug 31, 2020 · 18 comments · Fixed by #69
Closed

Support pkgsrc variation #16

0-wiz-0 opened this issue Aug 31, 2020 · 18 comments · Fixed by #69

Comments

@0-wiz-0
Copy link

0-wiz-0 commented Aug 31, 2020

The switch to the included distutils that happened in 48.0.0 broke the build on NetBSD, at least in the way setuptools is built from pkgsrc:

(cd /scratch/devel/py-setuptools/work/setuptools-48.0.0/ && /usr/bin/env <some environment vars elided>  /usr/pkg/bin/python3.7 setup.py  "install"  -c -O1  --root=/scratch/devel/py-setuptools/work/.destdir)
running install
Traceback (most recent call last):
  File "/scratch/devel/py-setuptools/work/setuptools-48.0.0/setuptools/_distutils/sysconfig.py", line 460, in _init_posix
    _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0)
ModuleNotFoundError: No module named '_sysconfigdata__netbsd9_'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "setup.py", line 154, in <module>
    dist = setuptools.setup(**setup_params)
  File "/scratch/devel/py-setuptools/work/setuptools-48.0.0/setuptools/__init__.py", line 164, in setup
    return distutils.core.setup(**attrs)
  File "/scratch/devel/py-setuptools/work/setuptools-48.0.0/setuptools/_distutils/core.py", line 148, in setup
    dist.run_commands()
  File "/scratch/devel/py-setuptools/work/setuptools-48.0.0/setuptools/_distutils/dist.py", line 967, in run_commands
    self.run_command(cmd)
  File "/scratch/devel/py-setuptools/work/setuptools-48.0.0/setuptools/_distutils/dist.py", line 985, in run_command
    cmd_obj.ensure_finalized()
  File "/scratch/devel/py-setuptools/work/setuptools-48.0.0/setuptools/_distutils/cmd.py", line 107, in ensure_finalized
    self.finalize_options()
  File "/scratch/devel/py-setuptools/work/setuptools-48.0.0/setuptools/command/install.py", line 38, in finalize_options
    orig.install.finalize_options(self)
  File "/scratch/devel/py-setuptools/work/setuptools-48.0.0/setuptools/_distutils/command/install.py", line 298, in finalize_options
    (prefix, exec_prefix) = get_config_vars('prefix', 'exec_prefix')
  File "/scratch/devel/py-setuptools/work/setuptools-48.0.0/setuptools/_distutils/sysconfig.py", line 504, in get_config_vars
    func()
  File "/scratch/devel/py-setuptools/work/setuptools-48.0.0/setuptools/_distutils/sysconfig.py", line 464, in _init_posix
    '_sysconfigdata', globals(), locals(), ['build_time_vars'], 0)
ModuleNotFoundError: No module named '_sysconfigdata'
*** Error code 1

setuptools 47.3.2 works when built the same way.

@jaraco
Copy link
Member

jaraco commented Sep 1, 2020

@0-wiz-0 I don't have a NetBSD environment. Can you inspect the CPython distutils code (ideally 3.9, or 3.8) and determine what's different about the stdlib distutils that it doesn't encounter the error you're getting with the Setuptools-hosted copy? Can you confirm the error is the same with Setuptools 50.0.1?

@0-wiz-0
Copy link
Author

0-wiz-0 commented Sep 1, 2020

Thanks for the idea of comparing to the CPython copy of distutils. There were no obvious differences, but pkgsrc has two patches for CPython's distutils:

https://github.com/NetBSD/pkgsrc/blob/trunk/lang/python38/patches/patch-Lib_distutils_sysconfig.py
https://github.com/NetBSD/pkgsrc/blob/trunk/lang/python38/patches/patch-Lib_distutils_unixccompiler.py

50.0.1 is broken in the same way as above, but when I apply these two patches to it, it builds fine.
(I'm not sure what we should do about these patches in general, so all this FYI for now.)

@jaraco
Copy link
Member

jaraco commented Sep 13, 2020

Thanks for confirming. I'm going to transfer this issue to the distutils project (which Setuptools 48 incorporates).

My recommendation is that we reach out to the maintainers of those patches and ask them to devise a suitable replacement, something that achieves the differential behavior, but only when appropriate (for NetBSD or some other factor in NetBSD). How does that sound?

@jaraco jaraco transferred this issue from pypa/setuptools Sep 13, 2020
@jaraco jaraco changed the title setuptools>=48 broken on NetBSD Support NetBSD variation Sep 13, 2020
@0-wiz-0
Copy link
Author

0-wiz-0 commented Sep 28, 2020

Perhaps we should re-title this again.
The patches I referenced are the ones used by pkgsrc, the portable packaging system that originates on NetBSD.
On NetBSD it is the default, but there are also big package repositories built for Illumos and macOS; it also works on Linux and many other current operating and not so current systems.

The patches referenced above are used to make the list of files that get installed the same on all these supported operating systems.

Perhaps the correct solution is just carrying similar patches in the pkgsrc setuptools package.

@jaraco
Copy link
Member

jaraco commented Nov 13, 2021

In #68, I'm working on a technique that would enable downstream packagers to monkeypatch. Perhaps that technique could also be applied to enable pkgsrc to include tweaks to the behavior.

Perhaps the correct solution is just carrying similar patches in the pkgsrc setuptools package.

I'd like to avoid that. Once Setuptools has successfully adopted distutils (can use it by default), the project plans to do some refactoring and clean up a lot of the duplication and monkeypatching that's going on. The project does not intend to keep a stable internal implementation suitable for patching.

@jaraco jaraco changed the title Support NetBSD variation Support pkgsrc variation Nov 13, 2021
jaraco added a commit that referenced this issue Nov 13, 2021
jaraco added a commit that referenced this issue Nov 13, 2021
jaraco added a commit that referenced this issue Nov 13, 2021
@jaraco
Copy link
Member

jaraco commented Nov 13, 2021

In 6d7976c, I've drafted hooks that would allow a project like pkgsrc to provide a _distutils_system_mod module that does the following:

# _distutils_system_mod

import distutils.sysconfig


vars(distutils.sysconfig).update(
    _makefile_tmpl='config-{python_ver}{build_flags}',
    _sysconfig_name_tmpl='_sysconfigdata_{platform}',
)

That would obviate the first patch for sysconfig.

Looking at the patch for unixcompiler, it appears to me that patch is no longer relevant and the need for it was likely addressed in #55.

@0-wiz-0
Copy link
Author

0-wiz-0 commented Nov 22, 2021

@jaraco Thanks for the example _distutils_system_mod file. Where do I need to put this?

@jaraco
Copy link
Member

jaraco commented Nov 22, 2021

You can put the module anywhere on sys.path, probably in site-packages, but feel free to use whatever creative mechanism you wish. This is the code that imports it and that code will only be invoked when a late setuptools is present with SETUPTOOLS_USE_DISTUTILS=local set (to become the default in the near future).

@0-wiz-0
Copy link
Author

0-wiz-0 commented Nov 23, 2021

distutils by default is installed by the python package, so I thought I'd have to modify that. But the version that's in python 3.9.9 does not have this code yet.
So then I thought that I should modify the distutils that's included in setuptools (since that includes the new try: statement). But I don't want to install a file into the global sys.path before I install setuptools (it's fine for me to do it during the installation of setuptools). So where in the setuptools source or build directory should I put it?
I tried setuptools/_distutils_system_mod, setuptools/_distutils/_distutils_system_mod, build/lib/setuptools/_distutils_system_mod, and build/lib/setuptools/_distutils/_distutils_system_mod, now I'm out of ideas.

@jaraco
Copy link
Member

jaraco commented Nov 23, 2021

I can see how my description was incomplete and led to the confusion. _distutils_system_mod should be a top-level module, independent of any package. So I'd put it in setuptools/../ or any other path that appears on sys.path. The reason it is independent of the setuptools package is because it's a hook, meant to be managed by the system packager (in this case pkgsrc), and supplied in advance of any installation of setuptools and affecting any and all installations of setuptools>=59.2.

The goal of this hook is to allow system packagers to avoid having to monkeypatch distutils at all and to instead provide hooks to enable the platform-specific customizations.

So, I would recommend that _distutils_system_mod be part of the Python package for pkgsrc, present with any installation of Python.

@0-wiz-0
Copy link
Author

0-wiz-0 commented Nov 24, 2021

I put the file from above into /usr/pkg/lib/python3.9/site-packages/_distutils_system_mod.py and tried building setuptools-59.2.0 with SETUPTOOLS_USE_DISTUTILS=local, and got:

Traceback (most recent call last):
  File "/scratch/devel/py-setuptools/work/setuptools-59.2.0/setup.py", line 7, in <module>
    import setuptools
  File "/scratch/devel/py-setuptools/work/setuptools-59.2.0/setuptools/__init__.py", line 242, in <module>
    monkey.patch_all()
  File "/scratch/devel/py-setuptools/work/setuptools-59.2.0/setuptools/monkey.py", line 99, in patch_all
    patch_for_msvc_specialized_compiler()
  File "/scratch/devel/py-setuptools/work/setuptools-59.2.0/setuptools/monkey.py", line 136, in patch_for_msvc_specialized_compiler
    msvc = import_module('setuptools.msvc')
  File "/usr/pkg/lib/python3.9/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "/scratch/devel/py-setuptools/work/setuptools-59.2.0/setuptools/msvc.py", line 57, in <module>
    distutils.errors.DistutilsPlatformError,
AttributeError: module 'distutils' has no attribute 'errors'

@jaraco
Copy link
Member

jaraco commented Nov 25, 2021

Oh, that's interesting. I suspect you've found a bug. But I don't yet understand it. Looking at setuptools.msvc, I see import distutils.errors earlier, so I'm not even sure how that error could be possible. Probably some artifact of the monkey-patching trickery going on. I'll see if I can replicate the failure.

@jaraco
Copy link
Member

jaraco commented Nov 26, 2021

Attempting to replicate the issue on my macOS machine, I find that it's working as expected:

draft $ cat > _distutils_system_mod.py
import distutils.sysconfig


vars(distutils.sysconfig).update(
    _makefile_tmpl='config-{python_ver}{build_flags}',
    _sysconfig_name_tmpl='_sysconfigdata_{platform}',
)
draft $ $SETUPTOOLS_USE_DISTUTILS='local' pip-run setuptools -- -c "import setuptools"
Collecting setuptools
  Using cached setuptools-59.2.0-py3-none-any.whl (952 kB)
Installing collected packages: setuptools
Successfully installed setuptools-59.2.0
Traceback (most recent call last):
  File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-rzxf1g2c/setuptools/_distutils/sysconfig.py", line 488, in _init_posix
    _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0)
ModuleNotFoundError: No module named '_sysconfigdata_darwin'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-rzxf1g2c/setuptools/__init__.py", line 18, in <module>
    from setuptools.dist import Distribution
  File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-rzxf1g2c/setuptools/dist.py", line 37, in <module>
    import setuptools.command
  File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-rzxf1g2c/setuptools/command/__init__.py", line 1, in <module>
    from distutils.command.bdist import bdist
  File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-rzxf1g2c/setuptools/_distutils/command/bdist.py", line 24, in <module>
    class bdist(Command):
  File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-rzxf1g2c/setuptools/_distutils/command/bdist.py", line 32, in bdist
    "(default: %s)" % get_platform()),
  File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-rzxf1g2c/setuptools/_distutils/util.py", line 110, in get_platform
    return get_host_platform()
  File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-rzxf1g2c/setuptools/_distutils/util.py", line 95, in get_host_platform
    distutils.sysconfig.get_config_vars(),
  File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-rzxf1g2c/setuptools/_distutils/sysconfig.py", line 532, in get_config_vars
    func()
  File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-rzxf1g2c/setuptools/_distutils/sysconfig.py", line 491, in _init_posix
    _temp = __import__(
ModuleNotFoundError: No module named '_sysconfigdata'
draft $ cat > _distutils_system_mod.py
import distutils.sysconfig


vars(distutils.sysconfig).update()
draft $ $SETUPTOOLS_USE_DISTUTILS='local' pip-run setuptools -- -c "import setuptools"
Collecting setuptools
  Using cached setuptools-59.2.0-py3-none-any.whl (952 kB)
Installing collected packages: setuptools
Successfully installed setuptools-59.2.0

I'll need to figure out what other factors are relevant.

@jaraco
Copy link
Member

jaraco commented Nov 26, 2021

Aha. I was able to elicit a similar, but slightly different error by attempting to run setup.py on a source checkout of setuptools:

setuptools main $ $SETUPTOOLS_USE_DISTUTILS='local' $PYTHONPATH=/users/jaraco/draft py -3.9 setup.py egg_info
Traceback (most recent call last):
  File "/Users/jaraco/code/public/pypa/setuptools/setup.py", line 7, in <module>
    import setuptools
  File "/Users/jaraco/code/public/pypa/setuptools/setuptools/__init__.py", line 18, in <module>
    from setuptools.dist import Distribution
  File "/Users/jaraco/code/public/pypa/setuptools/setuptools/dist.py", line 37, in <module>
    import setuptools.command
  File "/Users/jaraco/code/public/pypa/setuptools/setuptools/command/__init__.py", line 1, in <module>
    from distutils.command.bdist import bdist
  File "/Users/jaraco/code/public/pypa/setuptools/setuptools/_distutils/command/bdist.py", line 24, in <module>
    class bdist(Command):
  File "/Users/jaraco/code/public/pypa/setuptools/setuptools/_distutils/command/bdist.py", line 32, in bdist
    "(default: %s)" % get_platform()),
  File "/Users/jaraco/code/public/pypa/setuptools/setuptools/_distutils/util.py", line 110, in get_platform
    return get_host_platform()
  File "/Users/jaraco/code/public/pypa/setuptools/setuptools/_distutils/util.py", line 95, in get_host_platform
    distutils.sysconfig.get_config_vars(),
AttributeError: module 'distutils' has no attribute 'sysconfig'

I should be able to use that to track down the cause.

@jaraco
Copy link
Member

jaraco commented Nov 26, 2021

It seems the issue is that distutils.sysconfig is being loaded from the stdlib, even though the distutils hack has an explicit check that submodules are loaded from the locally-bundled copy. That's a bug in Setuptools' distutils hack.

@jaraco
Copy link
Member

jaraco commented Nov 26, 2021

Please consider testing against https://github.com/pypa/setuptools/tree/bugfix/2906-distutils-race. In my testing, it addresses the issue.

@jaraco
Copy link
Member

jaraco commented Nov 26, 2021

Setuptools 59.3.0 is releasing now and should contain the fix.

@0-wiz-0
Copy link
Author

0-wiz-0 commented Nov 26, 2021

I can confirm that 59.3.0 works for me with _distutils_system_mod.py from above and SETUPTOOLS_USE_DISTUTILS=local.

Thank you very much!

lazka added a commit to lazka/distutils that referenced this issue Dec 26, 2021
Instead of guessing the filename just refer to the stdlib.

This also removes the hook added in pypa#16, but

1) It was never implemented by the distro requesting it:
   https://github.com/NetBSD/pkgsrc/blob/586097714897b1b4d4a9e0a32c1658a1335442b7/devel/py-setuptools/Makefile#L28
2) The stdlib version should hopefully return a proper result

Also adds a small test cehcking that the file exists on Unix platforms
lazka added a commit to lazka/distutils that referenced this issue Dec 26, 2021
Instead of guessing the filename just refer to the stdlib.

This also removes the "_makefile_tmpl" hook added in pypa#16, but

1) It was never implemented by the distro requesting it from what I can see:
   https://github.com/NetBSD/pkgsrc/blob/586097714897b1b4d4a9e0a32c1658a1335442b7/devel/py-setuptools/Makefile#L28
2) The stdlib version should hopefully return a proper result

Also adds a small test checking that the file exists on Unix platforms
lazka added a commit to lazka/distutils that referenced this issue Dec 27, 2021
Instead of guessing the filename just refer to the stdlib.

This also removes the "_makefile_tmpl" hook added in pypa#16, but

1) It was never implemented by the distro requesting it from what I can see:
   https://github.com/NetBSD/pkgsrc/blob/586097714897b1b4d4a9/devel/py-setuptools/Makefile#L28
2) The stdlib version should return a proper result as it is patched by the distro requesting the change:
   https://github.com/NetBSD/pkgsrc/blob/6efa5763ec447864a7d4/lang/python38/patches/patch-Lib_sysconfig.py

Also adds a small test checking that the file exists on Unix platforms
lazka added a commit to lazka/distutils that referenced this issue Dec 27, 2021
Instead of guessing the filename just refer to the stdlib.

This also removes the "_makefile_tmpl" hook added in pypa#16, but

1) It was never implemented by the distro requesting it from what I can see:
   https://github.com/NetBSD/pkgsrc/blob/586097714897b1b4d4a9/devel/py-setuptools/Makefile#L28
2) The stdlib version should return a proper result as it is patched by the distro requesting the change:
   https://github.com/NetBSD/pkgsrc/blob/6efa5763ec447864a7d4/lang/python38/patches/patch-Lib_sysconfig.py

Also adds a small test checking that the file exists on Unix platforms
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 a pull request may close this issue.

2 participants