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.
		
		
		
		
		
			
		
			
				
					69 lines
				
				2.3 KiB
			
		
		
			
		
	
	
					69 lines
				
				2.3 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								# util/_preloaded.py
							 | 
						||
| 
								 | 
							
								# Copyright (C) 2005-2022 the SQLAlchemy authors and contributors
							 | 
						||
| 
								 | 
							
								# <see AUTHORS file>
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								# This module is part of SQLAlchemy and is released under
							 | 
						||
| 
								 | 
							
								# the MIT License: https://www.opensource.org/licenses/mit-license.php
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								"""supplies the "preloaded" registry to resolve circular module imports at
							 | 
						||
| 
								 | 
							
								runtime.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								"""
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import sys
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								from . import compat
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class _ModuleRegistry:
							 | 
						||
| 
								 | 
							
								    """Registry of modules to load in a package init file.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    To avoid potential thread safety issues for imports that are deferred
							 | 
						||
| 
								 | 
							
								    in a function, like https://bugs.python.org/issue38884, these modules
							 | 
						||
| 
								 | 
							
								    are added to the system module cache by importing them after the packages
							 | 
						||
| 
								 | 
							
								    has finished initialization.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    A global instance is provided under the name :attr:`.preloaded`. Use
							 | 
						||
| 
								 | 
							
								    the function :func:`.preload_module` to register modules to load and
							 | 
						||
| 
								 | 
							
								    :meth:`.import_prefix` to load all the modules that start with the
							 | 
						||
| 
								 | 
							
								    given path.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    While the modules are loaded in the global module cache, it's advisable
							 | 
						||
| 
								 | 
							
								    to access them using :attr:`.preloaded` to ensure that it was actually
							 | 
						||
| 
								 | 
							
								    registered. Each registered module is added to the instance ``__dict__``
							 | 
						||
| 
								 | 
							
								    in the form `<package>_<module>`, omitting ``sqlalchemy`` from the package
							 | 
						||
| 
								 | 
							
								    name. Example: ``sqlalchemy.sql.util`` becomes ``preloaded.sql_util``.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __init__(self, prefix="sqlalchemy."):
							 | 
						||
| 
								 | 
							
								        self.module_registry = set()
							 | 
						||
| 
								 | 
							
								        self.prefix = prefix
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def preload_module(self, *deps):
							 | 
						||
| 
								 | 
							
								        """Adds the specified modules to the list to load.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        This method can be used both as a normal function and as a decorator.
							 | 
						||
| 
								 | 
							
								        No change is performed to the decorated object.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        self.module_registry.update(deps)
							 | 
						||
| 
								 | 
							
								        return lambda fn: fn
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def import_prefix(self, path):
							 | 
						||
| 
								 | 
							
								        """Resolve all the modules in the registry that start with the
							 | 
						||
| 
								 | 
							
								        specified path.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        for module in self.module_registry:
							 | 
						||
| 
								 | 
							
								            if self.prefix:
							 | 
						||
| 
								 | 
							
								                key = module.split(self.prefix)[-1].replace(".", "_")
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                key = module
							 | 
						||
| 
								 | 
							
								            if (
							 | 
						||
| 
								 | 
							
								                not path or module.startswith(path)
							 | 
						||
| 
								 | 
							
								            ) and key not in self.__dict__:
							 | 
						||
| 
								 | 
							
								                compat.import_(module, globals(), locals())
							 | 
						||
| 
								 | 
							
								                self.__dict__[key] = sys.modules[module]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								preloaded = _ModuleRegistry()
							 | 
						||
| 
								 | 
							
								preload_module = preloaded.preload_module
							 |