You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

module_loading.py 6.1 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import copy
  2. import os
  3. import sys
  4. from importlib import import_module
  5. from django.utils import six
  6. def import_string(dotted_path):
  7. """
  8. Import a dotted module path and return the attribute/class designated by the
  9. last name in the path. Raise ImportError if the import failed.
  10. """
  11. try:
  12. module_path, class_name = dotted_path.rsplit('.', 1)
  13. except ValueError:
  14. msg = "%s doesn't look like a module path" % dotted_path
  15. six.reraise(ImportError, ImportError(msg), sys.exc_info()[2])
  16. module = import_module(module_path)
  17. try:
  18. return getattr(module, class_name)
  19. except AttributeError:
  20. msg = 'Module "%s" does not define a "%s" attribute/class' % (
  21. module_path, class_name)
  22. six.reraise(ImportError, ImportError(msg), sys.exc_info()[2])
  23. def autodiscover_modules(*args, **kwargs):
  24. """
  25. Auto-discover INSTALLED_APPS modules and fail silently when
  26. not present. This forces an import on them to register any admin bits they
  27. may want.
  28. You may provide a register_to keyword parameter as a way to access a
  29. registry. This register_to object must have a _registry instance variable
  30. to access it.
  31. """
  32. from django.apps import apps
  33. register_to = kwargs.get('register_to')
  34. for app_config in apps.get_app_configs():
  35. for module_to_search in args:
  36. # Attempt to import the app's module.
  37. try:
  38. if register_to:
  39. before_import_registry = copy.copy(register_to._registry)
  40. import_module('%s.%s' % (app_config.name, module_to_search))
  41. except:
  42. # Reset the registry to the state before the last import
  43. # as this import will have to reoccur on the next request and
  44. # this could raise NotRegistered and AlreadyRegistered
  45. # exceptions (see #8245).
  46. if register_to:
  47. register_to._registry = before_import_registry
  48. # Decide whether to bubble up this error. If the app just
  49. # doesn't have the module in question, we can ignore the error
  50. # attempting to import it, otherwise we want it to bubble up.
  51. if module_has_submodule(app_config.module, module_to_search):
  52. raise
  53. if six.PY3:
  54. from importlib.util import find_spec as importlib_find
  55. def module_has_submodule(package, module_name):
  56. """See if 'module' is in 'package'."""
  57. try:
  58. package_name = package.__name__
  59. package_path = package.__path__
  60. except AttributeError:
  61. # package isn't a package.
  62. return False
  63. full_module_name = package_name + '.' + module_name
  64. return importlib_find(full_module_name, package_path) is not None
  65. else:
  66. import imp
  67. def module_has_submodule(package, module_name):
  68. """See if 'module' is in 'package'."""
  69. name = ".".join([package.__name__, module_name])
  70. try:
  71. # None indicates a cached miss; see mark_miss() in Python/import.c.
  72. return sys.modules[name] is not None
  73. except KeyError:
  74. pass
  75. try:
  76. package_path = package.__path__ # No __path__, then not a package.
  77. except AttributeError:
  78. # Since the remainder of this function assumes that we're dealing with
  79. # a package (module with a __path__), so if it's not, then bail here.
  80. return False
  81. for finder in sys.meta_path:
  82. if finder.find_module(name, package_path):
  83. return True
  84. for entry in package_path:
  85. try:
  86. # Try the cached finder.
  87. finder = sys.path_importer_cache[entry]
  88. if finder is None:
  89. # Implicit import machinery should be used.
  90. try:
  91. file_, _, _ = imp.find_module(module_name, [entry])
  92. if file_:
  93. file_.close()
  94. return True
  95. except ImportError:
  96. continue
  97. # Else see if the finder knows of a loader.
  98. elif finder.find_module(name):
  99. return True
  100. else:
  101. continue
  102. except KeyError:
  103. # No cached finder, so try and make one.
  104. for hook in sys.path_hooks:
  105. try:
  106. finder = hook(entry)
  107. # XXX Could cache in sys.path_importer_cache
  108. if finder.find_module(name):
  109. return True
  110. else:
  111. # Once a finder is found, stop the search.
  112. break
  113. except ImportError:
  114. # Continue the search for a finder.
  115. continue
  116. else:
  117. # No finder found.
  118. # Try the implicit import machinery if searching a directory.
  119. if os.path.isdir(entry):
  120. try:
  121. file_, _, _ = imp.find_module(module_name, [entry])
  122. if file_:
  123. file_.close()
  124. return True
  125. except ImportError:
  126. pass
  127. # XXX Could insert None or NullImporter
  128. else:
  129. # Exhausted the search, so the module cannot be found.
  130. return False
  131. def module_dir(module):
  132. """
  133. Find the name of the directory that contains a module, if possible.
  134. Raise ValueError otherwise, e.g. for namespace packages that are split
  135. over several directories.
  136. """
  137. # Convert to list because _NamespacePath does not support indexing on 3.3.
  138. paths = list(getattr(module, '__path__', []))
  139. if len(paths) == 1:
  140. return paths[0]
  141. else:
  142. filename = getattr(module, '__file__', None)
  143. if filename is not None:
  144. return os.path.dirname(filename)
  145. raise ValueError("Cannot determine directory containing %s" % module)