From e67a589c4240fe0d422efeb09d5a91f26f8e624a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Stolcman?= Date: Tue, 10 Nov 2020 10:51:01 +0100 Subject: [PATCH] hooks: django: allow multiple settings modules (#5267) --- PyInstaller/hooks/hook-django.py | 8 ++-- PyInstaller/utils/hooks/django.py | 5 ++- .../hooks/subproc/django_import_finder.py | 43 +++++-------------- news/5267.hooks.rst | 1 + 4 files changed, 20 insertions(+), 37 deletions(-) create mode 100644 news/5267.hooks.rst diff --git a/PyInstaller/hooks/hook-django.py b/PyInstaller/hooks/hook-django.py index 3a4cf15df9..d7e9b43eb4 100644 --- a/PyInstaller/hooks/hook-django.py +++ b/PyInstaller/hooks/hook-django.py @@ -10,7 +10,7 @@ #----------------------------------------------------------------------------- -# Tested with django 1.8. +# Tested with django 2.2 import sys @@ -40,10 +40,12 @@ # Include main django modules - settings.py, urls.py, wsgi.py. # Without them the django server won't run. package_name = os.path.basename(root_dir) + default_settings_module = f'{package_name}.settings' + settings_module = os.environ.get('DJANGO_SETTINGS_MODULE', default_settings_module) hiddenimports += [ # TODO Consider including 'mysite.settings.py' in source code as a data files. # Since users might need to edit this file. - package_name + '.settings', + settings_module, package_name + '.urls', package_name + '.wsgi', ] @@ -67,7 +69,7 @@ 'django.contrib.sites.migrations', ] # Include migration scripts of Django-based apps too. - installed_apps = eval(get_module_attribute(package_name + '.settings', 'INSTALLED_APPS')) + installed_apps = eval(get_module_attribute(settings_module, 'INSTALLED_APPS')) migration_modules.extend(set(app + '.migrations' for app in installed_apps)) # Copy migration files. for mod in migration_modules: diff --git a/PyInstaller/utils/hooks/django.py b/PyInstaller/utils/hooks/django.py index d2664aba3e..5ba6b3b43c 100644 --- a/PyInstaller/utils/hooks/django.py +++ b/PyInstaller/utils/hooks/django.py @@ -34,8 +34,9 @@ def django_dottedstring_imports(django_root_dir): # module. pths.append(django_root_dir) - package_name = os.path.basename(django_root_dir) + '.settings' - env = {'DJANGO_SETTINGS_MODULE': package_name, + default_settings_module = os.path.basename(django_root_dir) + '.settings' + settings_module = os.environ.get('DJANGO_SETTINGS_MODULE', default_settings_module) + env = {'DJANGO_SETTINGS_MODULE': settings_module, 'PYTHONPATH': os.pathsep.join(pths)} ret = eval_script('django_import_finder.py', env=env) diff --git a/PyInstaller/utils/hooks/subproc/django_import_finder.py b/PyInstaller/utils/hooks/subproc/django_import_finder.py index 695f311c47..6b8506651f 100644 --- a/PyInstaller/utils/hooks/subproc/django_import_finder.py +++ b/PyInstaller/utils/hooks/subproc/django_import_finder.py @@ -16,7 +16,7 @@ NOTE: With newer version of Django this is most likely the part of PyInstaller that will be broken. -Tested with Django 1.8. +Tested with Django 2.2 """ @@ -34,10 +34,16 @@ from PyInstaller.utils.hooks import collect_submodules -hiddenimports = list(settings.INSTALLED_APPS) + \ - list(settings.TEMPLATE_CONTEXT_PROCESSORS) + \ - list(settings.TEMPLATE_LOADERS) + \ - [settings.ROOT_URLCONF] +hiddenimports = list(settings.INSTALLED_APPS) + +# do not fail script when settings does not have such attributes +if hasattr(settings, 'TEMPLATE_CONTEXT_PROCESSORS'): + hiddenimports += list(settings.TEMPLATE_CONTEXT_PROCESSORS) + +if hasattr(settings, 'TEMPLATE_LOADERS'): + hiddenimports += list(settings.TEMPLATE_LOADERS) + +hiddenimports += [settings.ROOT_URLCONF] def _remove_class(class_name): @@ -78,21 +84,6 @@ def _remove_class(class_name): hiddenimports.append(v['ENGINE']) -def find_url_callbacks(urls_module): - if isinstance(urls_module, list): - urlpatterns = urls_module - hid_list = [] - else: - urlpatterns = urls_module.urlpatterns - hid_list = [urls_module.__name__] - for pattern in urlpatterns: - if isinstance(pattern, RegexURLPattern): - hid_list.append(pattern.callback.__module__) - elif isinstance(pattern, RegexURLResolver): - hid_list += find_url_callbacks(pattern.urlconf_module) - return hid_list - - # Add templatetags and context processors for each installed app. for app in settings.INSTALLED_APPS: app_templatetag_module = app + '.templatetags' @@ -101,18 +92,6 @@ def find_url_callbacks(urls_module): hiddenimports += collect_submodules(app_templatetag_module) hiddenimports.append(app_ctx_proc_module) - -from django.core.urlresolvers import RegexURLPattern, RegexURLResolver - - -# Construct base module name - without 'settings' suffix. -base_module_name = '.'.join(os.environ['DJANGO_SETTINGS_MODULE'].split('.')[0:-1]) -base_module = __import__(base_module_name, {}, {}, ["urls"]) -urls = base_module.urls - -# Find url imports. -hiddenimports += find_url_callbacks(urls) - # Deduplicate imports. hiddenimports = list(set(hiddenimports)) diff --git a/news/5267.hooks.rst b/news/5267.hooks.rst new file mode 100644 index 0000000000..de8e124ff3 --- /dev/null +++ b/news/5267.hooks.rst @@ -0,0 +1 @@ +Enable overriding Django settings path by `DJANGO_SETTINGS_MODULE` environment variable.