Commit 68f384a9 authored by Kirill Smelkov's avatar Kirill Smelkov

*: Replace imp with importlib on py3

@Qubitium notes (https://github.com/navytux/pygolang/issues/1):

    Python 3.12 no longer support the imp module (fully deprecated) with note to use importlib as replacement.

    Please support python 3.12 by migrating from imp code to importlib. Thanks.

and indeed, even trying to build pygolang fails on py3.12:

    (py312.venv) kirr@deca:~/src/tools/go/pygolang-master$ python setup.py build_ext -i
    Traceback (most recent call last):
      File "/home/kirr/src/tools/go/pygolang-master/setup.py", line 40, in <module>
        exec(readfile('trun'), trun)
      File "<string>", line 41, in <module>
    ModuleNotFoundError: No module named 'imp'

-> Rework the code to use importlib instead, but keep using imp on py2
where there is practically no importlib functionality.

/reported-by @Qubitium (github)
/reviewed-by @jerome
/reviewed-on nexedi/pygolang!23
parent 6446a0be
# Copyright (C) 2018-2019 Nexedi SA and Contributors. # Copyright (C) 2018-2024 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com> # Kirill Smelkov <kirr@nexedi.com>
# #
# This program is free software: you can Use, Study, Modify and Redistribute # This program is free software: you can Use, Study, Modify and Redistribute
...@@ -34,11 +34,7 @@ from __future__ import print_function, absolute_import ...@@ -34,11 +34,7 @@ from __future__ import print_function, absolute_import
import os, os.path import os, os.path
import sys import sys
import six
import warnings
with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning)
import imp
# _gopathv returns $GOPATH vector. # _gopathv returns $GOPATH vector.
def _gopathv(): def _gopathv():
...@@ -51,11 +47,25 @@ def _gopathv(): ...@@ -51,11 +47,25 @@ def _gopathv():
# gimport imports python module or package from fully-qualified module name under $GOPATH. # gimport imports python module or package from fully-qualified module name under $GOPATH.
def gimport(name): def gimport(name):
imp.acquire_lock() _gimport_lock()
try: try:
return _gimport(name) return _gimport(name)
finally: finally:
imp.release_lock() _gimport_unlock()
# on py2 there is global import lock
# on py3 we need to organize our own gimport synchronization
if six.PY2:
import imp
_gimport_lock = imp.acquire_lock
_gimport_unlock = imp.release_lock
else:
from importlib import machinery as imp_machinery
from importlib import util as imp_util
from golang import sync
_gimport_mu = sync.Mutex()
_gimport_lock = _gimport_mu.lock
_gimport_unlock = _gimport_mu.unlock
def _gimport(name): def _gimport(name):
# we will register imported module into sys.modules with adjusted path. # we will register imported module into sys.modules with adjusted path.
...@@ -93,4 +103,16 @@ def _gimport(name): ...@@ -93,4 +103,16 @@ def _gimport(name):
# https://stackoverflow.com/a/67692 # https://stackoverflow.com/a/67692
return _imp_load_source(modname, modpath)
def _imp_load_source(modname, modpath):
if six.PY2:
return imp.load_source(modname, modpath) return imp.load_source(modname, modpath)
# https://docs.python.org/3/whatsnew/3.12.html#imp
loader = imp_machinery.SourceFileLoader(modname, modpath)
spec = imp_util.spec_from_file_location(modname, modpath, loader=loader)
mod = imp_util.module_from_spec(spec)
sys.modules[modname] = mod
loader.exec_module(mod)
return mod
#!/usr/bin/env python #!/usr/bin/env python
# Copyright (C) 2019-2020 Nexedi SA and Contributors. # Copyright (C) 2019-2024 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com> # Kirill Smelkov <kirr@nexedi.com>
# #
# This program is free software: you can Use, Study, Modify and Redistribute # This program is free software: you can Use, Study, Modify and Redistribute
...@@ -34,12 +34,13 @@ trun cares to run python with LD_PRELOAD set appropriately to /path/to/libtsan.s ...@@ -34,12 +34,13 @@ trun cares to run python with LD_PRELOAD set appropriately to /path/to/libtsan.s
from __future__ import print_function, absolute_import from __future__ import print_function, absolute_import
import os, sys, re, subprocess, pkgutil import os, sys, re, subprocess, types
import warnings
with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning)
import imp
PY3 = (bytes is not str) PY3 = (bytes is not str)
if PY3:
from importlib import machinery as imp_machinery
else:
import imp, pkgutil
# env_prepend prepends value to ${name} environment variable. # env_prepend prepends value to ${name} environment variable.
# #
...@@ -64,10 +65,13 @@ def grep1(pattern, text): # -> re.Match|None ...@@ -64,10 +65,13 @@ def grep1(pattern, text): # -> re.Match|None
# to import e.g. golang.pyx.build, or locate golang._golang, without built/working golang. # to import e.g. golang.pyx.build, or locate golang._golang, without built/working golang.
def ximport_empty_golangmod(): def ximport_empty_golangmod():
assert 'golang' not in sys.modules assert 'golang' not in sys.modules
golang = imp.new_module('golang') golang = types.ModuleType('golang')
golang.__package__ = 'golang' golang.__package__ = 'golang'
golang.__path__ = ['golang'] golang.__path__ = ['golang']
golang.__file__ = 'golang/__init__.py' golang.__file__ = 'golang/__init__.py'
if PY3:
golang.__loader__ = imp_machinery.SourceFileLoader('golang', 'golang/__init__.py')
else:
golang.__loader__ = pkgutil.ImpLoader('golang', None, 'golang/__init__.py', golang.__loader__ = pkgutil.ImpLoader('golang', None, 'golang/__init__.py',
[None, None, imp.PY_SOURCE]) [None, None, imp.PY_SOURCE])
sys.modules['golang'] = golang sys.modules['golang'] = golang
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment