#24 Add support for upstream architectures' names
Merged 3 years ago by lbalhar. Opened 3 years ago by lbalhar.
rpms/ lbalhar/python3.9 archs  into  master

@@ -0,0 +1,79 @@ 

+ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001

+ From: Lumir Balhar <lbalhar@redhat.com>

+ Date: Tue, 4 Aug 2020 12:04:03 +0200

+ Subject: [PATCH] 00353: Original names for architectures with different names

+  downstream

+ 

+ Pythons in RHEL/Fedora use different names for some architectures

+ than upstream and other distros (for example ppc64 vs. powerpc64).

+ See patch 274.

+ That means that an extension built with the default upstream settings

+ (on other distro or as an manylinux wheel) cannot be found by Python

+ on RHEL/Fedora because it has a different suffix.

+ This patch adds the original names to importlib so Python is able

+ to import extensions with an original architecture name in its

+ file name.

+ 

+ WARNING: This patch has no effect on Python built with bootstrap

+ enabled because Python/importlib_external.h is not regenerated

+ and therefore Python during bootstrap contains importlib from

+ upstream without this feature. It's possible to include

+ Python/importlib_external.h to this patch but it'd make rebasing

+ a nightmare because it's basically a binary file.

+ ---

+  Lib/importlib/_bootstrap_external.py | 31 ++++++++++++++++++++++++++--

+  1 file changed, 29 insertions(+), 2 deletions(-)

+ 

+ diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py

+ index 25a3f8c0e0..db4bb4d02d 100644

+ --- a/Lib/importlib/_bootstrap_external.py

+ +++ b/Lib/importlib/_bootstrap_external.py

+ @@ -1566,7 +1566,7 @@ def _get_supported_file_loaders():

+  

+      Each item is a tuple (loader, suffixes).

+      """

+ -    extensions = ExtensionFileLoader, _imp.extension_suffixes()

+ +    extensions = ExtensionFileLoader, _alternative_architectures(_imp.extension_suffixes())

+      source = SourceFileLoader, SOURCE_SUFFIXES

+      bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES

+      return [extensions, source, bytecode]

+ @@ -1622,7 +1622,7 @@ def _setup(_bootstrap_module):

+  

+      # Constants

+      setattr(self_module, '_relax_case', _make_relax_case())

+ -    EXTENSION_SUFFIXES.extend(_imp.extension_suffixes())

+ +    EXTENSION_SUFFIXES.extend(_alternative_architectures(_imp.extension_suffixes()))

+      if builtin_os == 'nt':

+          SOURCE_SUFFIXES.append('.pyw')

+          if '_d.pyd' in EXTENSION_SUFFIXES:

+ @@ -1635,3 +1635,30 @@ def _install(_bootstrap_module):

+      supported_loaders = _get_supported_file_loaders()

+      sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders)])

+      sys.meta_path.append(PathFinder)

+ +

+ +

+ +_ARCH_MAP = {

+ +    "-arm-linux-gnueabi.": "-arm-linux-gnueabihf.",

+ +    "-armeb-linux-gnueabi.": "-armeb-linux-gnueabihf.",

+ +    "-mips64-linux-gnu.": "-mips64-linux-gnuabi64.",

+ +    "-mips64el-linux-gnu.": "-mips64el-linux-gnuabi64.",

+ +    "-ppc-linux-gnu.": "-powerpc-linux-gnu.",

+ +    "-ppc-linux-gnuspe.": "-powerpc-linux-gnuspe.",

+ +    "-ppc64-linux-gnu.": "-powerpc64-linux-gnu.",

+ +    "-ppc64le-linux-gnu.": "-powerpc64le-linux-gnu.",

+ +}

+ +

+ +

+ +def _alternative_architectures(suffixes):

+ +    """Add a suffix with an alternative architecture name

+ +    to the list of suffixes so an extension built with

+ +    the default (upstream) setting is loadable with our Pythons

+ +    """

+ +

+ +    for suffix in suffixes:

+ +        for original, alternative in _ARCH_MAP.items():

+ +            if original in suffix:

+ +                suffixes.append(suffix.replace(original, alternative))

+ +                return suffixes

+ +

+ +    return suffixes

file modified
+25 -1
@@ -17,7 +17,7 @@ 

  %global prerel b5

  %global upstream_version %{general_version}%{?prerel}

  Version: %{general_version}%{?prerel:~%{prerel}}

- Release: 4%{?dist}

+ Release: 5%{?dist}

  License: Python

  

  
@@ -305,6 +305,27 @@ 

  # Ideally, we should talk to upstream and explain why we don't want this

  Patch328: 00328-pyc-timestamp-invalidation-mode.patch

  

+ # 00353 # f3c11e227c715450b3c1e945a5004e84cce41a58

+ # Original names for architectures with different names downstream

+ #

+ # Pythons in RHEL/Fedora use different names for some architectures

+ # than upstream and other distros (for example ppc64 vs. powerpc64).

+ # See patch 274.

+ # That means that an extension built with the default upstream settings

+ # (on other distro or as an manylinux wheel) cannot be found by Python

+ # on RHEL/Fedora because it has a different suffix.

+ # This patch adds the original names to importlib so Python is able

+ # to import extensions with an original architecture name in its

+ # file name.

+ #

+ # WARNING: This patch has no effect on Python built with bootstrap

+ # enabled because Python/importlib_external.h is not regenerated

+ # and therefore Python during bootstrap contains importlib from

+ # upstream without this feature. It's possible to include

+ # Python/importlib_external.h to this patch but it'd make rebasing

+ # a nightmare because it's basically a binary file.

+ Patch353: 00353-Original-names-for-architectures-with-different-name.patch

+ 

  # (New patches go here ^^^)

  #

  # When adding new patches to "python" and "python3" in Fedora, EL, etc.,
@@ -1613,6 +1634,9 @@ 

  # ======================================================

  

  %changelog

+ * Mon Aug 03 2020 Lumír Balhar <lbalhar@redhat.com> - 3.9.0~b5-5

+ - Add support for upstream architectures' names (patch 353)

+ 

  * Thu Jul 30 2020 Miro Hrončok <mhroncok@redhat.com> - 3.9.0~b5-4

  - Make python3-libs installable without python3

    Resolves: rhbz#1862082

Pythons in RHEL/Fedora use different names for some architectures
than upstream and other distros (for example ppc64 vs. powerpc64).
See patch 274.
That means that an extension built with the default upstream settings
(on other distro or as an manylinux wheel) cannot be found by Python
on RHEL/Fedora because it has a different suffix.
This patch adds the original names to importlib so Python is able
to import extensions with an original architecture name in its
file name.

Tested on ppc64le with a wheel from simple-manylinux-demo:

# pip3 install simple-manylinux-demo
WARNING: Running pip install with root privileges is generally not a good idea. Try `pip3 install --user` instead.
Collecting simple-manylinux-demo
  Downloading simple_manylinux_demo-1.0-cp39-cp39-manylinux2014_ppc64le.whl (17 kB)
Installing collected packages: simple-manylinux-demo
Successfully installed simple-manylinux-demo-1.0
# default Python
# python3 -m unittest discover dummyextension.tests
E
======================================================================
ERROR: dummyextension.tests.test_extension (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: dummyextension.tests.test_extension
Traceback (most recent call last):
  File "/usr/lib64/python3.9/unittest/loader.py", line 436, in _find_test_path
    module = self._get_module_from_name(name)
  File "/usr/lib64/python3.9/unittest/loader.py", line 377, in _get_module_from_name
    __import__(name)
  File "/usr/local/lib64/python3.9/site-packages/dummyextension/tests/test_extension.py", line 2, in <module>
    from dummyextension.extension import hello
ModuleNotFoundError: No module named 'dummyextension.extension'


----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (errors=1)
# ll /usr/local/lib64/python3.9/site-packages/dummyextension/
total 88
-rwxr-xr-x. 1 root root 88832 Aug  3 04:14 extension.cpython-39-powerpc64le-linux-gnu.so
-rw-r--r--. 1 root root     0 Aug  3 04:14 __init__.py
drwxr-xr-x. 2 root root    37 Aug  3 04:14 __pycache__
drwxr-xr-x. 3 root root    69 Aug  3 04:14 tests
# Patched version
# python3 -m unittest discover dummyextension.tests
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
# New loader registered for the longer name
>>> import sys
>>> sys.path_importer_cache
{'/usr/lib64/python39.zip': None, '/usr/lib64/python3.9': FileFinder('/usr/lib64/python3.9'), '/usr/lib64/python3.9/encodings': FileFinder('/usr/lib64/python3.9/encodings'), '/usr/lib64/python3.9/lib-dynload': FileFinder('/usr/lib64/python3.9/lib-dynload'), '/usr/local/lib64/python3.9/site-packages': FileFinder('/usr/local/lib64/python3.9/site-packages'), '/usr/lib64/python3.9/site-packages': FileFinder('/usr/lib64/python3.9/site-packages'), '/usr/lib/python3.9/site-packages': FileFinder('/usr/lib/python3.9/site-packages'), '/root': FileFinder('/root')}
>>> ff = sys.path_importer_cache['/usr/lib64/python3.9/site-packages']
>>> ff._loaders
[('.cpython-39-ppc64le-linux-gnu.so', <class '_frozen_importlib_external.ExtensionFileLoader'>), ('.abi3.so', <class '_frozen_importlib_external.ExtensionFileLoader'>), ('.so', <class '_frozen_importlib_external.ExtensionFileLoader'>), ('.cpython-39-powerpc64le-linux-gnu.so', <class '_frozen_importlib_external.ExtensionFileLoader'>), ('.py', <class '_frozen_importlib_external.SourceFileLoader'>), ('.pyc', <class '_frozen_importlib_external.SourcelessFileLoader'>)]

This might be also implemented on C level somewhere around _PyImport_DynLoadFiletab but I think that this version is much clearer and easy to understand.

Could you please open the PR in https://github.com/fedora-python/cpython for easier patch review? Please make sure the patch has a subject line that starts with 00353:. Than, you can use importpatches to convert the commit to the patch here.

rebased onto 6694f12c757feda58b212191aaa5ffbce9922cc1

3 years ago

Rebased with the latest patch from GH.

rebased onto 898f743

3 years ago

Added a warning about zero effect of this patch during a bootstrap build.

Build succeeded.

Scratch build: https://koji.fedoraproject.org/koji/taskinfo?taskID=48705001

Verification:

# pip3 install simple-manylinux-demo
WARNING: Running pip install with root privileges is generally not a good idea. Try `pip3 install --user` instead.
Collecting simple-manylinux-demo
  Downloading simple_manylinux_demo-1.0-cp39-cp39-manylinux2014_ppc64le.whl (17 kB)
Installing collected packages: simple-manylinux-demo
Successfully installed simple-manylinux-demo-1.0

# old
# python3
Python 3.9.0b5 (heads/master-dirty:591e14c, Jul 30 2020, 00:00:00) 
[GCC 10.2.1 20200723 (Red Hat 10.2.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import dummyextension.extension
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'dummyextension.extension'

# new
# python3
Python 3.9.0b5 (heads/master-dirty:b53d3c6, Aug  3 2020, 00:00:00) 
[GCC 10.2.1 20200723 (Red Hat 10.2.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import dummyextension.extension
>>> import sys
>>> ff = sys.path_importer_cache['/usr/lib64/python3.9']
>>> ff._loaders
[('.cpython-39-ppc64le-linux-gnu.so', <class '_frozen_importlib_external.ExtensionFileLoader'>), ('.abi3.so', <class '_frozen_importlib_external.ExtensionFileLoader'>), ('.so', <class '_frozen_importlib_external.ExtensionFileLoader'>), ('.cpython-39-powerpc64le-linux-gnu.so', <class '_frozen_importlib_external.ExtensionFileLoader'>), ('.py', <class '_frozen_importlib_external.SourceFileLoader'>), ('.pyc', <class '_frozen_importlib_external.SourcelessFileLoader'>)]

Pull-Request has been merged by lbalhar

3 years ago