Ticket #16675: importutils.diff

File importutils.diff, 5.8 KB (added by jezdez, 4 years ago)

diff from https://github.com/jezdez/django/compare/feature/importutils

  • django/utils/importlib.py

    diff --git a/django/utils/importlib.py b/django/utils/importlib.py
    index ef4d0e4..fe3f546 100644
    a b def import_module(name, package=None): 
    3434        name = _resolve_name(name[level:], package, level)
    3535    __import__(name)
    3636    return sys.modules[name]
     37
     38
     39def import_attribute(name, exception_handler=None):
     40    """
     41    Loads an object from an 'name', like in MIDDLEWARE_CLASSES and the likes.
     42
     43    Import paths should be: "mypackage.mymodule.MyObject". It then imports the
     44    module up until the last dot and tries to get the attribute after that dot
     45    from the imported module.
     46
     47    If the import path does not contain any dots, a TypeError is raised.
     48
     49    If the module cannot be imported, an ImportError is raised.
     50
     51    If the attribute does not exist in the module, a AttributeError is raised.
     52
     53    You can provide custom error handling using the optional exception_handler
     54    argument which gets called with the exception type, the exception value and
     55    the traceback object if there is an error during loading.
     56
     57    The exception_handler is not called if an invalid import path (one without
     58    a dot in it) is provided.
     59    """
     60    if '.' not in name:
     61        raise TypeError("'name' argument to "
     62                        "'django.utils.importlib.import_attribute' must "
     63                        "contain at least one dot.")
     64    module_name, object_name = name.rsplit('.', 1)
     65    try:
     66        module = import_module(module_name)
     67    except:
     68        if callable(exception_handler):
     69            exctype, excvalue, tb = sys.exc_info()
     70            return exception_handler(name, exctype, excvalue, tb)
     71        else:
     72            raise
     73    try:
     74        return getattr(module, object_name)
     75    except:
     76        if callable(exception_handler):
     77            exctype, excvalue, tb = sys.exc_info()
     78            return exception_handler(name, exctype, excvalue, tb)
     79        else:
     80            raise
     81
     82
     83def iter_import_attributes(names, exception_handler=None):
     84    """
     85    Calls django.contrib.load.import_attribute on all items in the iterable
     86    names and returns a generator that yields the objects to be loaded.
     87
     88    The exception_handler is propagated to import_attribute.
     89
     90    If the exception_handler does not return anything or returns None, the
     91    value is ignored.
     92    """
     93    for name in names:
     94        next = import_attribute(name, exception_handler)
     95        if next:
     96            yield next
  • new file tests/regressiontests/utils/importlib.py

    diff --git a/tests/regressiontests/utils/importlib.py b/tests/regressiontests/utils/importlib.py
    new file mode 100644
    index 0000000..bccd0ce
    - +  
     1# -*- coding: utf-8 -*-
     2from __future__ import with_statement
     3from django.contrib.auth.models import User, AnonymousUser
     4from django.test.testcases import TestCase
     5from django.utils.importlib import import_attribute, iter_import_attributes
     6   
     7
     8class LoadTests(TestCase):
     9       
     10    def test_import_attribute(self):
     11        obj = import_attribute('django.contrib.auth.models.User')
     12        self.assertEqual(obj, User)
     13       
     14    def test_import_attribute_fail_type(self):
     15        self.assertRaises(TypeError, import_attribute, 'notanimportpath')
     16       
     17    def test_import_attribute_fail_import(self):
     18        self.assertRaises(ImportError, import_attribute,
     19                          'django.contrib.auth.not_models.User')
     20       
     21    def test_import_attribute_fail_attribute(self):
     22        self.assertRaises(AttributeError, import_attribute,
     23                          'django.contrib.auth.models.NotAUser')
     24       
     25    def test_import_attribute_exception_handler(self):
     26        class MyException(Exception): pass
     27        def exc_handler(*args, **kwargs):
     28            raise MyException
     29        self.assertRaises(MyException, import_attribute,
     30                          'django.contrib.auth.models.NotAUser', exc_handler)
     31        self.assertRaises(MyException, import_attribute,
     32                          'django.contrib.auth.not_models.User', exc_handler)
     33        self.assertRaises(TypeError, import_attribute, 'notanimportpath')
     34
     35    def test_iter_import_attributes(self):
     36        import_paths = ['django.contrib.auth.models.User',
     37                        'django.contrib.auth.models.AnonymousUser']
     38        objs = list(iter_import_attributes(import_paths))
     39        self.assertEqual(len(objs), 2)
     40        self.assertEqual(objs[0], User)
     41        self.assertEqual(objs[1], AnonymousUser)
     42       
     43    def test_iter_import_attributes_propagates_exception_handler(self):
     44        class MyException(Exception): pass
     45        def exc_handler(*args, **kwargs):
     46            raise MyException
     47        gen = iter_import_attributes(['django.contrib.auth.models.User',
     48                                      'django.contrib.auth.models.NotAUser'],
     49                                      exc_handler)
     50        user = gen.next()
     51        self.assertEqual(user, User)
     52        self.assertRaises(MyException, gen.next)
     53   
     54    def test_iter_import_attributes_ignore_exceptions(self):
     55        def exc_handler(*args, **kwargs):
     56            pass
     57
     58        import_paths = ['django.contrib.auth.models.User',
     59                        'django.contrib.auth.models.NotAUser',
     60                        'django.contrib.auth.models.AnonymousUser']
     61        objs = list(iter_import_attributes(import_paths, exc_handler))
     62        self.assertEqual(len(objs), 2)
     63        self.assertEqual(objs[0], User)
     64        self.assertEqual(objs[1], AnonymousUser)
  • tests/regressiontests/utils/tests.py

    diff --git a/tests/regressiontests/utils/tests.py b/tests/regressiontests/utils/tests.py
    index e91adc9..242b7e2 100644
    a b from datetime_safe import * 
    2020from baseconv import *
    2121from jslex import *
    2222from ipv6 import *
     23from importlib import *
Back to Top