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

Replace deprecated imp module with importlib #358

Closed
hugovk opened this issue Apr 29, 2023 · 4 comments
Closed

Replace deprecated imp module with importlib #358

hugovk opened this issue Apr 29, 2023 · 4 comments

Comments

@hugovk
Copy link
Member

hugovk commented Apr 29, 2023

This project uses the imp module which has been deprecated since Python 3.4 and set for removal in 3.12:

Python 3.12 is set for release on 2023-10-02 and this library is one of the top 5,000 most-downloaded from PyPI.

Please could you upgrade to use importlib? The imp docs have suggestions on what to use to replace each function and constant.

@mgorny
Copy link

mgorny commented Jul 23, 2023

Ping. This is now blocking Python 3.12 support.

@mgorny
Copy link

mgorny commented Jul 23, 2023

I'm going to give it a shot.

@mgorny
Copy link

mgorny commented Jul 23, 2023

Ok, I give up. This is the closest I've been able to come up with:

diff --git a/configurations/importer.py b/configurations/importer.py
index e3573f4..00e7728 100644
--- a/configurations/importer.py
+++ b/configurations/importer.py
@@ -1,4 +1,6 @@
 import imp
+from importlib.machinery import PathFinder
+import importlib.util
 import logging
 import os
 import sys
@@ -126,25 +128,31 @@ class ConfigurationImporter:
                                                       self.name))
                 self.logger.debug(stylize(message))
 
-    def find_module(self, fullname, path=None):
+    def find_spec(self, fullname, path=None, target=None):
         if fullname is not None and fullname == self.module:
             module = fullname.rsplit('.', 1)[-1]
-            return ConfigurationLoader(self.name,
-                                       imp.find_module(module, path))
+            spec = PathFinder.find_spec(module, path, target)
+            assert spec is not None
+            return importlib.machinery.ModuleSpec(
+                spec.name,
+                ConfigurationLoader(self.name, spec),
+                origin=spec.origin)
         return None
 
 
 class ConfigurationLoader:
 
-    def __init__(self, name, location):
+    def __init__(self, name, spec):
         self.name = name
-        self.location = location
+        self.spec = spec
 
     def load_module(self, fullname):
         if fullname in sys.modules:
             mod = sys.modules[fullname]  # pragma: no cover
         else:
-            mod = imp.load_module(fullname, *self.location)
+            mod = importlib.util.module_from_spec(self.spec)
+            sys.modules[fullname] = mod
+            self.spec.loader.exec_module(mod)
         cls_path = '{0}.{1}'.format(mod.__name__, self.name)
 
         try:

However, it fails a bunch of test cases:

$ django-cadmin test
Found 70 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.EE............FF............./tmp/django-configurations/.tox/py311-dj42/lib/python3.11/site-packages/dj_email_url.py:89: UserWarning: `smtps` scheme will be deprecated in a future version, use `submission` instead
  warnings.warn(
........................................
======================================================================
ERROR: test_inherited (tests.test_inheritance.InheritanceTests.test_inherited)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3.11/unittest/mock.py", line 1828, in _inner
    return f(*args, **kw)
           ^^^^^^^^^^^^^^
  File "/tmp/django-configurations/tests/test_inheritance.py", line 14, in test_inherited
    from tests.settings import single_inheritance
  File "/tmp/django-configurations/configurations/importer.py", line 155, in load_module
    self.spec.loader.exec_module(mod)
  File "/tmp/django-configurations/tests/settings/single_inheritance.py", line 1, in <module>
    from .base import Base
ImportError: attempted relative import with no known parent package

======================================================================
ERROR: test_inherited2 (tests.test_inheritance.InheritanceTests.test_inherited2)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3.11/unittest/mock.py", line 1828, in _inner
    return f(*args, **kw)
           ^^^^^^^^^^^^^^
  File "/tmp/django-configurations/tests/test_inheritance.py", line 24, in test_inherited2
    from tests.settings import multiple_inheritance
  File "/tmp/django-configurations/configurations/importer.py", line 155, in load_module
    self.spec.loader.exec_module(mod)
  File "/tmp/django-configurations/tests/settings/multiple_inheritance.py", line 1, in <module>
    from .single_inheritance import Inheritance as BaseInheritance
ImportError: attempted relative import with no known parent package

======================================================================
FAIL: test_repr (tests.test_main.MainTests.test_repr)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/django-configurations/tests/test_main.py", line 66, in test_repr
    self.assertEqual(repr(Test),
AssertionError: "<Configuration 'main.Test'>" != "<Configuration 'tests.settings.main.Test'>"
- <Configuration 'main.Test'>
+ <Configuration 'tests.settings.main.Test'>
?                 +++++++++++++++


======================================================================
FAIL: test_simple (tests.test_main.MainTests.test_simple)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/django-configurations/tests/test_main.py", line 30, in test_simple
    self.assertRaises(AttributeError, lambda: main.POST_SETUP_TEST_SETTING)
AssertionError: AttributeError not raised by <lambda>

----------------------------------------------------------------------
Ran 70 tests in 1.249s

FAILED (failures=2, errors=2)
Destroying test database for alias 'default'...

gump added a commit to octoenergy/django-configurations that referenced this issue Sep 8, 2023
This project uses the imp module which has been deprecated since Python 3.4 and set for removal in 3.12:
• Raised PendingDeprecationWarning since 3.4 (2014)
• Raised DeprecationWarning since 3.5 (2015)
• Updated DeprecationWarning to say removal in 3.12 since 3.10 (2021)
• Removal planned for 3.12 (2023)

This change removes the dependency on imp in favour of importlib.

Co-authored-by: @jbkkd
Inspired by: @mgorny

jazzband#358
gump added a commit to octoenergy/django-configurations that referenced this issue Sep 8, 2023
This project uses the imp module which has been deprecated since Python 3.4 and set for removal in 3.12:
• Raised PendingDeprecationWarning since 3.4 (2014)
• Raised DeprecationWarning since 3.5 (2015)
• Updated DeprecationWarning to say removal in 3.12 since 3.10 (2021)
• Removal planned for 3.12 (2023)

This change removes the dependency on imp in favour of importlib.

Co-authored-by: @jbkkd
Inspired by: @mgorny

jazzband#358
jbkkd pushed a commit that referenced this issue Sep 27, 2023
This project uses the imp module which has been deprecated since Python 3.4 and set for removal in 3.12:
• Raised PendingDeprecationWarning since 3.4 (2014)
• Raised DeprecationWarning since 3.5 (2015)
• Updated DeprecationWarning to say removal in 3.12 since 3.10 (2021)
• Removal planned for 3.12 (2023)

This change removes the dependency on imp in favour of importlib.

Co-authored-by: @jbkkd
Inspired by: @mgorny

#358
@gump
Copy link
Contributor

gump commented Sep 27, 2023

This has been resolved in #365

@gump gump closed this as completed Sep 27, 2023
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

No branches or pull requests

3 participants