Add preliminary django support to PyInstaller

git-svn-id: http://svn.pyinstaller.org/trunk@717 8dd32b29-ccff-0310-8a9a-9233e24343b1
This commit is contained in:
duplo
2009-10-08 07:46:41 +00:00
parent 0a59b6d15e
commit f0bc04af05
14 changed files with 344 additions and 0 deletions
+1
View File
@@ -234,6 +234,7 @@ class Analysis(Target):
if pathex:
for path in pathex:
self.pathex.append(absnormpath(path))
sys.pathex = pathex[:]
self.hookspath = hookspath
self.excludes = excludes
self.scripts = TOC()
+54
View File
@@ -0,0 +1,54 @@
# Copyright (C) 2009, Lorenzo Berni
# Based on previous work under copyright (c) 2001, 2002 McMillan Enterprises, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import os
if not os.environ.get("DJANGO_SETTINGS_MODULE"):
os.environ["DJANGO_SETTINGS_MODULE"] = "settings"
from django.conf import settings
hiddenimports = list(settings.AUTHENTICATION_BACKENDS) + \
[settings.DEFAULT_FILE_STORAGE] + \
list(settings.FILE_UPLOAD_HANDLERS) + \
list(settings.INSTALLED_APPS) + \
list(settings.MIDDLEWARE_CLASSES) + \
list(settings.TEMPLATE_CONTEXT_PROCESSORS) + \
list(settings.TEMPLATE_LOADERS) + \
[settings.ROOT_URLCONF]
def find_url_callbacks(urls_module):
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
from django.core.urlresolvers import RegexURLPattern, RegexURLResolver
base_module_name = ".".join(os.environ.get("DJANGO_SETTINGS_MODULE", "settings").split(".")[:-1])
if base_module_name:
base_module = __import__(base_module_name, {}, {}, ["urls"])
urls = base_module.urls
else:
import urls
hiddenimports += find_url_callbacks(urls)
print repr(sorted(set(hiddenimports)))
View File
+33
View File
@@ -0,0 +1,33 @@
# Copyright (C) 2009, Lorenzo Berni
# Based on previous work under copyright (c) 2001, 2002 McMillan Enterprises, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import os
import glob
def hook(mod):
global hiddenimports
modpath = mod.__path__[0]
hiddenimports = []
for fn in glob.glob('%s/backends/*.py' % modpath):
fn = os.path.basename(fn)
fn = os.path.splitext(fn)[0]
hiddenimports.append('django.contrib.sessions.backends.' + fn)
return mod
+33
View File
@@ -0,0 +1,33 @@
# Copyright (C) 2009, Lorenzo Berni
# Based on previous work under copyright (c) 2001, 2002 McMillan Enterprises, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import os
import glob
def hook(mod):
global hiddenimports
modpath = mod.__path__[0]
hiddenimports = []
for fn in glob.glob('%s/backends/*.py' % modpath):
fn = os.path.basename(fn)
fn = os.path.splitext(fn)[0]
hiddenimports.append('django.core.cache.backends.' + fn)
return mod
+31
View File
@@ -0,0 +1,31 @@
# Copyright (C) 2009, Lorenzo Berni
# Based on previous work under copyright (c) 2001, 2002 McMillan Enterprises, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
# django.core.mail uses part of the email package.
# Problem is: when using runserver with autoreload mode, the thread that
# checks fore changed files unwillingly trigger further imports within
# the email package because of the LazyImporter in email (used in 2.5 for
# backward compatibility).
# We then need to name those modules as hidden imports, otherwise at
# runtime the autoreload thread will complain with a traceback.
hiddenimports = [
'email.mime.message',
'email.mime.image',
'email.mime.text',
'email.mime.multipart',
'email.mime.audio'
]
+34
View File
@@ -0,0 +1,34 @@
# Copyright (C) 2009, Lorenzo Berni
# Based on previous work under copyright (c) 2001, 2002 McMillan Enterprises, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import os
import glob
def hook(mod):
global hiddenimports
modpath = mod.__path__[0]
hiddenimports = []
for fn in glob.glob('%s/commands/*.py' % modpath):
fn = os.path.basename(fn)
fn = os.path.splitext(fn)[0]
hiddenimports.append('django.core.management.commands.' + fn)
return mod
View File
+33
View File
@@ -0,0 +1,33 @@
# Copyright (C) 2009, Lorenzo Berni
# Based on previous work under copyright (c) 2001, 2002 McMillan Enterprises, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import os
import glob
def hook(mod):
global hiddenimports
modpath = mod.__path__[0]
hiddenimports = []
for fn in glob.glob('%s/*' % modpath):
if os.path.isdir(fn):
fn = os.path.basename(fn)
hiddenimports.append('django.db.backends.' + fn + '.base')
return mod
View File
+48
View File
@@ -0,0 +1,48 @@
# Copyright (C) 2009, Lorenzo Berni
# Based on previous work under copyright (c) 2001, 2002 McMillan Enterprises, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
from hookutils import django_dottedstring_imports, find_django_root
import glob
import sys
import os
python_path = os.environ.get("PYTHONPATH")
if python_path:
python_path = os.pathsep.join([python_path] + sys.pathex)
else:
python_path = os.pathsep.join(sys.pathex)
django_root_dirs = []
for path in python_path.split(os.pathsep):
django_root_dirs += find_django_root(path)
if not django_root_dirs:
raise RuntimeError("No django root directory found. Please check your pathex definition in the project spec file.")
if django_root_dirs[0] in sys.pathex:
raise RuntimeError("The django root directory is defined in the pathex. You have to define the parent directory instead of the django root directory.")
os.environ["PYTHONPATH"] = python_path
hiddenimports = []
for django_root_dir in django_root_dirs:
hiddenimports += django_dottedstring_imports(django_root_dir)
+22
View File
@@ -1,5 +1,7 @@
#!/usr/bin/env python
import os
def exec_statement(stat):
"""Executes a Python statement in an externally spawned interpreter, and
returns anything that was emitted in the standard output as a single string.
@@ -53,3 +55,23 @@ def qwt_numeric_support():
return eval(exec_statement("from PyQt4 import Qwt5; print hasattr(Qwt5, 'toNumeric')"))
def qwt_numarray_support():
return eval(exec_statement("from PyQt4 import Qwt5; print hasattr(Qwt5, 'toNumarray')"))
def django_dottedstring_imports(django_root_dir):
package_name = os.path.basename(django_root_dir)
os.environ["DJANGO_SETTINGS_MODULE"] = "%s.settings" %package_name
return eval(exec_statement("execfile(r'%s')" %os.path.join(os.path.dirname(__file__), "django-import-finder.py")))
def find_django_root(dir):
entities = os.listdir(dir)
if "manage.py" in entities and "settings.py" in entities and "urls.py" in entities:
return dir
else:
django_root_directories = []
for entity in entities:
path_to_analyze = os.path.join(dir, entity)
if os.path.isdir(path_to_analyze):
dir_entities = os.listdir(path_to_analyze)
if "manage.py" in dir_entities and "settings.py" in dir_entities and "urls.py" in dir_entities:
django_root_directories.append(path_to_analyze)
return django_root_directories
+1
View File
@@ -6,4 +6,5 @@
'PyQt4': ['support/rthooks/pyi_rth_qt4plugins.py'],
'matplotlib': ['support/rthooks/pyi_rth_mpldata.py'],
'babel': ['support/rthooks/pyi_rth_babel.py'],
'django': ['support/rthooks/pyi_rth_django.py'],
}
+54
View File
@@ -0,0 +1,54 @@
# Copyright (C) 2009, Lorenzo Berni
# Based on previous work under copyright (c) 2001, 2002 McMillan Enterprises, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import os
import sys
if "_MEIPASS2" in os.environ:
d = os.environ["_MEIPASS2"]
else:
d = os.path.dirname(sys.argv[0])
import django.core.management
import django.utils.autoreload
def _setup_environ(settings_mod, original_settings_path=None):
project_name = settings_mod.__name__.split(".")[0]
settings_name = "settings"
if original_settings_path:
os.environ['DJANGO_SETTINGS_MODULE'] = original_settings_path
else:
os.environ['DJANGO_SETTINGS_MODULE'] = '%s.%s' % (project_name, settings_name)
project_module = __import__(project_name, {}, {}, [''])
return d
def _find_commands(_):
return """cleanup compilemessages createcachetable dbshell shell runfcgi runserver startproject""".split()
old_restart_with_reloader = django.utils.autoreload.restart_with_reloader
def _restart_with_reloader(*args):
import sys
a0 = sys.argv.pop(0)
try:
return old_restart_with_reloader(*args)
finally:
sys.argv.insert(0, a0)
django.core.management.setup_environ = _setup_environ
django.core.management.find_commands = _find_commands
django.utils.autoreload.restart_with_reloader = _restart_with_reloader