def run_pyflakes_for_package(package_name, extra_ignore=None): """ If pyflakes is installed, run it across the given package name returning any warnings found. """ ignore_strings = PYFLAKES_IGNORE if extra_ignore: ignore_strings += extra_ignore try: from pyflakes.checker import Checker except ImportError: return [] warnings = [] for (root, dirs, files) in os.walk(path_for_import(package_name)): for f in files: # Ignore migrations. directory = root.split(os.sep)[-1] if not f.endswith(".py") or directory == "migrations": continue path = os.path.join(root, f) with open(path, "U") as source_file: source = source_file.read() try: compile(source, f, "exec") except (SyntaxError, IndentationError), value: info = (path, value.lineno, value.args[0]) warnings.append("Invalid syntax in %s:%d: %s" % info) result = Checker(parse(source), path) for warning in result.messages: message = unicode(warning) for ignore in ignore_strings: if ignore in message: break else: warnings.append(message)
def handle_label(self, theme_name, **options): """ Copy the templates and media files for the given theme package into the current project. """ try: theme_path = path_for_import(theme_name) except ImportError: raise CommandError("Could not import the theme: %s" % theme_name) copy_paths = ( (os.path.join(theme_path, "templates"), settings.TEMPLATE_DIRS[-1]), (os.path.join(theme_path, "media"), settings.MEDIA_ROOT), ) if options.get("interactive"): confirm = raw_input(""" Theme installation may overwrite existing template and media files. Are you sure you want to do this? Type 'yes' to continue, or 'no' to cancel: """) if confirm != "yes": raise CommandError("Theme installation cancelled.") for (path_from, path_to) in copy_paths: if os.path.exists(path_from): copy_tree(path_from, path_to)
def _run_checker_for_package(checker, package_name, extra_ignore=None): """ Runs the checker function across every Python module in the given package. """ ignore_strings = IGNORE_ERRORS if extra_ignore: ignore_strings += extra_ignore package_path = path_for_import(package_name) for (root, dirs, files) in os.walk(package_path): for f in files: # Ignore migrations. directory = root.split(os.sep)[-1] # Using native_str here avoids the dreaded UnicodeDecodeError # on Py2 with filenames with high-bit characters when # unicode_literals in effect: ext = native_str(".py") if (f == "local_settings.py" or not f.endswith(ext) or directory == "migrations"): continue for warning in checker(os.path.join(root, f)): for ignore in ignore_strings: if ignore in warning: break else: yield warning.replace(package_path, package_name, 1)
def run_pep8_for_package(package_name): """ If pep8 is installed, run it across the given package name returning any warnings or errors found. """ import pep8 package_path = path_for_import(package_name) pep8.process_options(["-r", package_path]) class Checker(pep8.Checker): """ Subclass pep8's Checker to hook into error reporting. """ def report_error(self, line_number, offset, text, check): """ Store pairs of line numbers and errors. """ self.errors.append((line_number, text.split(" ", 1)[1])) def check_all(self, *args, **kwargs): """ Assign the errors attribute and return it after running. """ self.errors = [] super(Checker, self).check_all(*args, **kwargs) return self.errors def pep8_checker(path): for line_number, text in Checker(path).check_all(): yield "%s:%s: %s" % (path, line_number, text) return _run_checker_for_package(pep8_checker, package_name)
def main(package="mezzanine", args=()): """ This is the main test function called via ``python setup.py test``. It's responsible for hacking the ``project_template`` dir into an actual project to test against. """ from mezzanine.utils.importing import path_for_import package_path = path_for_import(package) project_path = os.path.join(package_path, "project_template") os.environ["DJANGO_SETTINGS_MODULE"] = "project_name.test_settings" project_app_path = os.path.join(project_path, "project_name") local_settings_path = os.path.join(project_app_path, "local_settings.py") test_settings_path = os.path.join(project_app_path, "test_settings.py") sys.path.insert(0, package_path) sys.path.insert(0, project_path) if not os.path.exists(test_settings_path): shutil.copy(local_settings_path + ".template", test_settings_path) with open(test_settings_path, "r") as f: local_settings = f.read() with open(test_settings_path, "w") as f: test_settings = """ from . import settings globals().update(i for i in settings.__dict__.items() if i[0].isupper()) # Require the mezzanine.accounts app. We use settings.INSTALLED_APPS here so # the syntax test doesn't complain about an undefined name. if "mezzanine.accounts" not in settings.INSTALLED_APPS: INSTALLED_APPS = list(settings.INSTALLED_APPS) + ["mezzanine.accounts", "django.contrib.messages"] # Use the MD5 password hasher by default for quicker test runs. PASSWORD_HASHERS = ('django.contrib.auth.hashers.MD5PasswordHasher',) """ f.write(test_settings + local_settings) def cleanup_test_settings(): import os # Outer scope sometimes unavailable in atexit functions. for fn in [test_settings_path, test_settings_path + 'c']: try: os.remove(fn) except OSError: pass atexit.register(cleanup_test_settings) django.setup() from django.core.management.commands import test if django.VERSION < (1, 10): sys.exit(test.Command().execute(*args, verbosity=1)) sys.exit(call_command(test.Command(), *args, verbosity=1))
def handle_label(self, theme_name, **options): """ Create a new Django app and copy all available templates into it. """ super(Command, self).handle_label(theme_name, **options) # Build a unique list of template names from ``INSTALLED_APPS`` and # ``TEMPLATE_DIRS`` then determine which template files they belong # to and copy them to the theme/templates directory. templates = set() for app in settings.INSTALLED_APPS: if app.startswith("django.") or app in settings.OPTIONAL_APPS: continue templates_path = os.path.join(path_for_import(app), "templates") for (root, dirs, files) in os.walk(templates_path): for f in files: template = os.path.join(root, f)[len(templates_path):] if not template.startswith("/admin/"): templates.add(template.lstrip(os.sep)) templates_path = os.path.join(theme_name, "templates") os.mkdir(templates_path) for template in templates: path_from = unicode(template_path(template)) path_to = os.path.join(templates_path, template) try: os.makedirs(os.path.dirname(path_to)) except OSError: pass copy(path_from, path_to) copytree(settings.MEDIA_ROOT, os.path.join(theme_name, "media"))
def main(package="mezzanine"): """ This is the main test function called via ``python setup.py test``. It's responsible for hacking the ``project_template`` dir into an actual project to test against. """ from mezzanine.utils.importing import path_for_import os.environ["DJANGO_SETTINGS_MODULE"] = "project_template.settings" package_path = path_for_import(package) project_path = os.path.join(package_path, "project_template") local_settings_path = os.path.join(project_path, "local_settings.py") sys.path.insert(0, package_path) sys.path.insert(0, project_path) if not os.path.exists(local_settings_path): shutil.copy(local_settings_path + ".template", local_settings_path) from django.conf import settings apps = list(settings.INSTALLED_APPS) if "mezzanine.accounts" not in apps: apps += ["mezzanine.accounts"] with open(local_settings_path, "a") as f: f.write("INSTALLED_APPS = %s" % apps) atexit.register(lambda: os.remove(local_settings_path)) from django.core.management.commands import test sys.exit(test.Command().execute(verbosity=1))
def main(package="mezzanine"): """ This is the main test function called via ``python setup.py test``. It's responsible for hacking the ``project_template`` dir into an actual project to test against. """ from mezzanine.utils.importing import path_for_import os.environ["DJANGO_SETTINGS_MODULE"] = "project_template.test_settings" package_path = path_for_import(package) project_path = os.path.join(package_path, "project_template") local_settings_path = os.path.join(project_path, "local_settings.py") test_settings_path = os.path.join(project_path, "test_settings.py") sys.path.insert(0, package_path) sys.path.insert(0, project_path) if not os.path.exists(test_settings_path): shutil.copy(local_settings_path + ".template", test_settings_path) with open(test_settings_path, "r") as f: local_settings = f.read() with open(test_settings_path, "w") as f: test_reqs_str = """ from project_template import settings globals().update(settings.__dict__) INSTALLED_APPS = list(settings.INSTALLED_APPS) + ["mezzanine.accounts"] """ if django.VERSION >= (1, 7): test_reqs_str += "import django\ndjango.setup()" f.write(test_reqs_str + local_settings) atexit.register(lambda: os.remove(test_settings_path)) from django.core.management.commands import test sys.exit(test.Command().execute(verbosity=1))
def main(package="mezzanine"): """ This is the main test function called via ``python setup.py test``. It's responsible for hacking the ``project_template`` dir into an actual project to test against. """ from mezzanine.utils.importing import path_for_import package_path = path_for_import(package) project_path = os.path.join(package_path, "project_template") os.environ["DJANGO_SETTINGS_MODULE"] = "project_name.test_settings" project_app_path = os.path.join(project_path, "project_name") local_settings_path = os.path.join(project_app_path, "local_settings.py") test_settings_path = os.path.join(project_app_path, "test_settings.py") sys.path.insert(0, package_path) sys.path.insert(0, project_path) if not os.path.exists(test_settings_path): shutil.copy(local_settings_path + ".template", test_settings_path) with open(test_settings_path, "r") as f: local_settings = f.read() with open(test_settings_path, "w") as f: test_settings = """ from . import settings globals().update(i for i in settings.__dict__.items() if i[0].isupper()) # Require the mezzanine.accounts app. We use settings.INSTALLED_APPS here so # the syntax test doesn't complain about an undefined name. if "mezzanine.accounts" not in settings.INSTALLED_APPS: INSTALLED_APPS = list(settings.INSTALLED_APPS) + ["mezzanine.accounts"] # Use the MD5 password hasher by default for quicker test runs. PASSWORD_HASHERS = ('django.contrib.auth.hashers.MD5PasswordHasher',) """ f.write(test_settings + local_settings) def cleanup_test_settings(): import os # Outer scope sometimes unavailable in atexit functions. for fn in [test_settings_path, test_settings_path + "c"]: try: os.remove(fn) except OSError: pass atexit.register(cleanup_test_settings) django.setup() from django.core.management.commands import test sys.exit(test.Command().execute(verbosity=1))
def serve_with_theme(request, path): """ Mimics ``django.views.static.serve`` for serving files from ``MEDIA_ROOT`` during development, first checking for the file in the theme defined by the ``THEME`` setting if specified. """ theme = getattr(settings, "THEME") if theme: theme_root = os.path.join(path_for_import(theme), "media") try: return serve(request, path, document_root=theme_root) except Http404: pass return serve(request, path, document_root=settings.MEDIA_ROOT)
def build_deploy_docs(docs_path): try: from fabric.main import load_fabfile except ImportError: warn("Couldn't build fabfile.rst, fabric not installed") return project_template_path = path_for_import("mezzanine.project_template") commands = load_fabfile(os.path.join(project_template_path, "fabfile"))[1] lines = [] for name in sorted(commands.keys()): doc = commands[name].__doc__.strip().split("\n")[0] lines.append(" * ``fab %s`` - %s" % (name, doc)) with open(os.path.join(docs_path, "fabfile.rst"), "w") as f: f.write("\n".join(lines))
def _run_checker_for_package(checker, package_name): """ Runs the checker function across every Python module in the given package. """ package_path = path_for_import(package_name) for (root, dirs, files) in os.walk(package_path): for f in files: # Ignore migrations. directory = root.split(os.sep)[-1] if not f.endswith(".py") or directory == "migrations": continue for warning in checker(os.path.join(root, f)): yield warning.replace(package_path, package_name, 1)
def pytest_configure(): """ Hack the ``project_template`` dir included with Mezzanine into an actual project to test against. Based on mezzanine.bin.runtests. """ from mezzanine.utils.importing import path_for_import package_path = path_for_import("mezzanine") project_path = os.path.join(package_path, "project_template") os.environ["DJANGO_SETTINGS_MODULE"] = "project_name.test_settings" project_app_path = os.path.join(project_path, "project_name") local_settings_path = os.path.join(project_app_path, "local_settings.py") test_settings_path = os.path.join(project_app_path, "test_settings.py") sys.path.insert(0, package_path) sys.path.insert(0, project_path) if not os.path.exists(test_settings_path): shutil.copy(local_settings_path + ".template", test_settings_path) with open(test_settings_path, "r") as f: local_settings = f.read() with open(test_settings_path, "w") as f: test_settings = """ from . import settings globals().update(i for i in settings.__dict__.items() if i[0].isupper()) if "surveys" not in settings.INSTALLED_APPS: INSTALLED_APPS = list(settings.INSTALLED_APPS) + ["surveys"] ROOT_URLCONF = "surveys.tests.urls" # Use the MD5 password hasher by default for quicker test runs. PASSWORD_HASHERS = ('django.contrib.auth.hashers.MD5PasswordHasher',) """ f.write(test_settings + local_settings) def cleanup_test_settings(): import os # Outer scope sometimes unavailable in atexit functions. for fn in [test_settings_path, test_settings_path + 'c']: try: os.remove(fn) except OSError: pass atexit.register(cleanup_test_settings) django.setup()
def copy_test_to_media(module, name): """ Copies a file from Mezzanine's test data path to MEDIA_ROOT. Used in tests and demo fixtures. """ mezzanine_path = path_for_import(module) test_path = os.path.join(mezzanine_path, "static", "test", name) to_path = os.path.join(settings.MEDIA_ROOT, name) to_dir = os.path.dirname(to_path) if not os.path.exists(to_dir): os.makedirs(to_dir) if os.path.isdir(test_path): copy = copytree else: copy = copyfile copy(test_path, to_path)
def pytest_configure(): """ Hack the `project_template` dir into an actual project to test against. """ from mezzanine.utils.importing import path_for_import template_path = Path(path_for_import("mezzanine")) / "project_template" shutil.copytree(str(template_path), str(TMP_PATH)) proj_path = TMP_PATH / "project_name" local_settings = (proj_path / "local_settings.py.template").read_text() (proj_path / "test_settings.py").write_text(TEST_SETTINGS + local_settings) # Setup the environment for Django sys.path.insert(0, str(TMP_PATH)) os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project_name.test_settings") django.setup()
def runtests(): import os, sys, shutil, atexit from mezzanine.utils.importing import path_for_import os.environ["DJANGO_SETTINGS_MODULE"] = "project_template.settings" mezz_path = path_for_import("mezzanine") sys.path.insert(0, mezz_path) project_path = os.path.join(mezz_path, "project_template") local_settings_path = os.path.join(project_path, "local_settings.py") if not os.path.exists(local_settings_path): shutil.copy(local_settings_path + ".template", local_settings_path) atexit.register(lambda: os.remove(local_settings_path)) from django.core.management.commands import test sys.exit(test.Command().execute(verbosity=1))
def runtests(): import os, sys, shutil, atexit from mezzanine.utils.importing import path_for_import os.environ["DJANGO_SETTINGS_MODULE"] = "project_template.settings" mezz_path = path_for_import("mezzanine") project_path = os.path.join(mezz_path, "project_template") local_settings_path = os.path.join(project_path, "local_settings.py") sys.path.insert(0, mezz_path) sys.path.insert(0, project_path) if not os.path.exists(local_settings_path): shutil.copy(local_settings_path + ".template", local_settings_path) with open(local_settings_path, "a") as f: f.write(""" INSTALLED_APPS = ( "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.redirects", "django.contrib.sessions", "django.contrib.sites", "django.contrib.sitemaps", "django.contrib.staticfiles", "mezzanine.boot", "mezzanine.conf", "mezzanine.core", "mezzanine.generic", "mezzanine.blog", "mezzanine.forms", "mezzanine.pages", "mezzanine.galleries", "mezzanine.twitter", "mezzanine.accounts", "mezzanine.mobile", ) """) atexit.register(lambda: os.remove(local_settings_path)) from django.core.management.commands import test sys.exit(test.Command().execute(verbosity=1))
def copy_test_to_media(module, name): """ Copies a file from Mezzanine's test data path to MEDIA_ROOT. Used in tests and demo fixtures. """ mezzanine_path = path_for_import(module) test_path = os.path.join(mezzanine_path, "static", "test", name) to_path = os.path.join(settings.MEDIA_ROOT, name) to_dir = os.path.dirname(to_path) if not os.path.exists(to_dir): os.makedirs(to_dir) if os.path.isdir(test_path): copy = copytree else: copy = copyfile try: copy(test_path, to_path) except OSError: pass
def _run_checker_for_package(checker, package_name, extra_ignore=None): """ Runs the checker function across every Python module in the given package. """ ignore_strings = IGNORE_ERRORS if extra_ignore: ignore_strings += extra_ignore package_path = path_for_import(package_name) for (root, dirs, files) in os.walk(str(package_path)): for f in files: if f == "local_settings.py" or not f.endswith(".py") or root.split(os.sep)[-1] in ["migrations"]: # Ignore continue for warning in checker(os.path.join(root, f)): for ignore in ignore_strings: if ignore in warning: break else: yield warning.replace(package_path, package_name, 1)
def _run_checker_for_package(checker, package_name, extra_ignore=None): """ Runs the checker function across every Python module in the given package. """ ignore_strings = IGNORE_ERRORS if extra_ignore: ignore_strings += extra_ignore package_path = path_for_import(package_name) for (root, dirs, files) in os.walk(str(package_path)): for f in files: if (f == "local_settings.py" or not f.endswith(".py") or root.split(os.sep)[-1] in ["migrations", "south"]): # Ignore continue for warning in checker(os.path.join(root, f)): for ignore in ignore_strings: if ignore in warning: break else: yield warning.replace(package_path, package_name, 1)
def create_project(): """ Copies the contents of the project_template directory to a new directory specified as an argument to the command line. """ parser = OptionParser(usage="usage: %prog [options] project_name") parser.add_option( "-a", "--alternate", dest="alt", metavar="PACKAGE", help="Alternate package to use, containing a project_template") (options, args) = parser.parse_args() if len(args) != 1: parser.error("project_name must be specified") project_name = args[0] if project_name.startswith("-"): parser.error("project_name cannot start with '-'") project_path = os.path.join(os.getcwd(), project_name) # Ensure the given directory name doesn't clash with an existing # Python package/module. try: __import__(project_name) except ImportError: pass else: parser.error("'%s' conflicts with the name of an existing " "Python module and cannot be used as a project " "name. Please try another name." % project_name) # Create the list of packages to build from - at this stage it # should only be one or two names, mezzanine plus an alternate # package. packages = ["mezzanine"] if options.alt: packages.append(options.alt) for package_name in packages: try: __import__(package_name) except ImportError: parser.error("Could not import package '%s'" % package_name) # Build the project up copying over the project_template from # each of the packages. An alternate package will overwrite # files from Mezzanine. local_settings_path = os.path.join(project_path, "local_settings.py") for package_name in packages: package_path = path_for_import(package_name) copy_tree(os.path.join(package_path, "project_template"), project_path) move(local_settings_path + ".template", local_settings_path) # Generate a unique SECRET_KEY for the project's setttings module. with open(local_settings_path, "r") as f: data = f.read() with open(local_settings_path, "w") as f: make_key = lambda: "%s%s%s" % (uuid4(), uuid4(), uuid4()) data = data.replace("%(SECRET_KEY)s", make_key()) data = data.replace("%(NEVERCACHE_KEY)s", make_key()) f.write(data) # Clean up pyc files. for (root, dirs, files) in os.walk(project_path, False): for f in files: if f.endswith(".pyc"): os.remove(os.path.join(root, f))
def create_project(): """ Copies the contents of the project_template directory to a new directory specified as an argument to the command line. """ parser = OptionParser(usage="usage: %prog [options] project_name") parser.add_option("-a", "--alternate", dest="alt", metavar="PACKAGE", help="Alternate package to use, containing a project_template") parser.add_option("-s", "--source", dest="copy_source", default=False, action="store_true", help="Copy package source to new project") parser.add_option("-t", "--templates", dest="copy_templates", default=False, action="store_true", help="Copy templates to the project") parser.add_option("-m", "--mobiletemplates", dest="copy_mobile_templates", default=False, action="store_true", help="Copy mobile templates to the project") (options, args) = parser.parse_args() if len(args) != 1: parser.error("project_name must be specified") project_name = args[0] if project_name.startswith("-"): parser.error("project_name cannot start with '-'") project_path = os.path.join(os.getcwd(), project_name) # Ensure the given directory name doesn't clash with an existing # Python package/module. try: __import__(project_name) except ImportError: pass else: parser.error("'%s' conflicts with the name of an existing " "Python module and cannot be used as a project name. " "Please try another name." % project_name) # Create the list of packages to build from - at this stage it # should only be one or two names, mezzanine plus an alternate # package. packages = ["mezzanine"] if options.alt: packages.append(options.alt) for package_name in packages: try: __import__(package_name) except ImportError: parser.error("Could not import package '%s'" % package_name) # Build the project up copying over the project_template from # each of the packages. template_path = os.path.join(project_path, "templates") for package_name in packages: package_path = path_for_import(package_name) if options.copy_source: copy_tree(package_path, os.path.join(project_path, package_name)) copy_tree(os.path.join(package_path, "project_template"), project_path) move(os.path.join(project_path, "local_settings.py.template"), os.path.join(project_path, "local_settings.py")) if options.copy_templates: for app_dir in os.listdir(package_path): # Mobile templates handled by -m option below. if app_dir == "mobile": continue template_dir = os.path.join(package_path, app_dir, "templates") if os.path.isdir(template_dir): copy_tree(template_dir, template_path) if options.copy_mobile_templates: template_dir = os.path.join(package_path, "mobile", "templates") if os.path.isdir(template_dir): copy_tree(template_dir, template_path) # Remove admin templates from the project to allow for easier # upgrading, as these templates need not be customised. if options.copy_templates: try: rmtree(os.path.join(template_path, "admin")) except OSError: pass # Generate a unique SECREY_KEY for the project's setttings module. settings_path = os.path.join(os.getcwd(), project_name, "settings.py") with open(settings_path, "r") as f: data = f.read() with open(settings_path, "w") as f: secret_key = "%s%s%s" % (uuid4(), uuid4(), uuid4()) f.write(data.replace("%(SECRET_KEY)s", secret_key)) # Clean up pyc files. for (root, dirs, files) in os.walk(project_path, False): for f in files: if f.endswith(".pyc"): os.remove(os.path.join(root, f))
#!/usr/bin/env python # When project_template is used as the actual project during Mezzanine # development, insert the development path into sys.path so that the # development version of Mezzanine is used rather than the installed # version. import os import sys project_path = os.path.dirname(os.path.abspath(__file__)) project_dir = project_path.split(os.sep)[-1] if project_dir == "project_template": dev_path = os.path.abspath(os.path.join(project_path, "..", "..")) if dev_path not in sys.path: sys.path.insert(0, dev_path) from mezzanine.utils.importing import path_for_import mezzanine_path = path_for_import("mezzanine") assert os.path.abspath(os.path.join(mezzanine_path, "..")) == dev_path # Corrects some pathing issues in various contexts, such as cron jobs. os.chdir(project_path) for i, arg in enumerate(sys.argv): if arg.startswith("--site"): os.environ["MEZZANINE_SITE_ID"] = arg.split("=")[1] sys.argv.pop(i) from django.core.management import execute_manager try: import settings # Assumed to be in the same directory. except ImportError: import sys
def set_dynamic_settings(s): """ Called at the end of the project's settings module and is passed its globals dict for updating with some final tweaks for settings that generally aren't specified but can be given some better defaults based on other settings that have been specified. Broken out into its own function so that the code need not be replicated in the settings modules of other project-based apps that leverage Mezzanine's settings module. """ # Moves an existing list setting value to a different position. move = lambda n, k, i: s[n].insert(i, s[n].pop(s[n].index(k))) # Add a value to a list setting if not in the list. append = lambda n, k: s[n].append(k) if k not in s[n] else None s["TEMPLATE_DEBUG"] = s.get("TEMPLATE_DEBUG", s.get("DEBUG", False)) add_to_builtins("mezzanine.template.loader_tags") # Define some settings based on management command being run. management_command = sys.argv[1] if len(sys.argv) > 1 else "" # Some kind of testing is running via test or testserver. s["TESTING"] = management_command.startswith("test") # Some kind of development server is running via runserver or # runserver_plus s["DEV_SERVER"] = management_command.startswith("runserver") # Change INSTALLED_APPS and MIDDLEWARE_CLASSES to lists for # easier manipulation. s["INSTALLED_APPS"] = list(s["INSTALLED_APPS"]) s["MIDDLEWARE_CLASSES"] = list(s["MIDDLEWARE_CLASSES"]) # Set up cookie messaging if available. try: from django.contrib.messages import debug except ImportError: pass else: msg_mw = "django.contrib.messages.middleware.MessageMiddleware" append("MIDDLEWARE_CLASSES", msg_mw) if not s.get("MESSAGE_STORAGE"): storage = "django.contrib.messages.storage.cookie.CookieStorage" s["MESSAGE_STORAGE"] = storage # Setup for optional apps. if not s["TESTING"]: optional = list(s.get("OPTIONAL_APPS", [])) if s.get("USE_SOUTH"): optional.append("south") elif not s.get("USE_SOUTH", True) and "south" in s["INSTALLED_APPS"]: s["INSTALLED_APPS"].remove("south") for app in optional: if app not in s["INSTALLED_APPS"]: try: __import__(app) except ImportError: pass else: s["INSTALLED_APPS"].append(app) if "debug_toolbar" in s["INSTALLED_APPS"]: debug_mw = "debug_toolbar.middleware.DebugToolbarMiddleware" append("MIDDLEWARE_CLASSES", debug_mw) # Set up filebrowser paths. if s.get("PACKAGE_NAME_FILEBROWSER") in s["INSTALLED_APPS"]: s["FILEBROWSER_URL_FILEBROWSER_MEDIA"] = "/filebrowser/media/" fb_path = path_for_import(s["PACKAGE_NAME_FILEBROWSER"]) fb_media_path = os.path.join(fb_path, "media", "filebrowser") s["FILEBROWSER_PATH_FILEBROWSER_MEDIA"] = fb_media_path # Ensure Grappelli is after Mezzanine in app order so that # admin templates are loaded in the correct order. grappelli_name = s.get("PACKAGE_NAME_GRAPPELLI") try: move("INSTALLED_APPS", grappelli_name, len(s["INSTALLED_APPS"])) except ValueError: s["GRAPPELLI_INSTALLED"] = False else: s["GRAPPELLI_INSTALLED"] = True s.setdefault("GRAPPELLI_ADMIN_HEADLINE", "Mezzanine") s.setdefault("GRAPPELLI_ADMIN_TITLE", "Mezzanine") grappelli_path = path_for_import(grappelli_name) s["GRAPPELLI_MEDIA_PATH"] = os.path.join(grappelli_path, "media") # Adopted from django.core.management.commands.runserver # Easiest way so far to actually get all the media for # Grappelli working with the dev server is to hard-code the # host:port to ADMIN_MEDIA_PREFIX, so here we check for a # custom host:port before doing this. if s["DEV_SERVER"]: cmd = runserver.BaseRunserverCommand() parser = cmd.create_parser(*sys.argv[:2]) _, args = parser.parse_args(sys.argv[2:]) try: addrport = args[0] except IndexError: addr, port = "", runserver.DEFAULT_PORT else: try: addr, port = addrport.split(":") except ValueError: addr, port = "", addrport if not addr: addr = "127.0.0.1" parts = (addr, port, s["ADMIN_MEDIA_PREFIX"]) s["ADMIN_MEDIA_PREFIX"] = "http://%s:%s%s" % parts # Ensure admin is last in the app order so that admin templates # are loaded in the correct order. move("INSTALLED_APPS", "django.contrib.admin", len(s["INSTALLED_APPS"])) # Add missing apps if existing apps depend on them. if "mezzanine.blog" in s["INSTALLED_APPS"]: append("INSTALLED_APPS", "mezzanine.generic") if "mezzanine.generic" in s["INSTALLED_APPS"]: s["COMMENTS_APP"] = "mezzanine.generic" append("INSTALLED_APPS", "django.contrib.comments") # Ensure mezzanine.boot is first. try: move("INSTALLED_APPS", "mezzanine.boot", 0) except ValueError: pass # Caching. if not (s.get("CACHE_BACKEND") or s.get("CACHES")): s["MIDDLEWARE_CLASSES"] = [ mw for mw in s["MIDDLEWARE_CLASSES"] if not mw.endswith("UpdateCacheMiddleware") or mw.endswith("FetchFromCacheMiddleware") ] # Some settings tweaks for different DB engines. backend_path = "django.db.backends." backend_shortnames = ("postgresql_psycopg2", "postgresql", "mysql", "sqlite3", "oracle") for (key, db) in s["DATABASES"].items(): if db["ENGINE"] in backend_shortnames: s["DATABASES"][key]["ENGINE"] = backend_path + db["ENGINE"] shortname = db["ENGINE"].split(".")[-1] if shortname == "sqlite3" and os.sep not in db["NAME"]: # If the Sqlite DB name doesn't contain a path, assume # it's in the project directory and add the path to it. db_path = os.path.join(s.get("PROJECT_ROOT", ""), db["NAME"]) s["DATABASES"][key]["NAME"] = db_path elif shortname == "mysql": # Required MySQL collation for tests. s["DATABASES"][key]["TEST_COLLATION"] = "utf8_general_ci" elif shortname.startswith("postgresql") and not s.get("TIME_ZONE", 1): # Specifying a blank time zone to fall back to the # system's time zone will break table creation in Postgres # so remove it. del s["TIME_ZONE"] # If a theme is defined then add its template path to the # template dirs. theme = s.get("THEME") if theme: theme_templates = os.path.join(path_for_import(theme), "templates") s["TEMPLATE_DIRS"] = (theme_templates,) + tuple(s["TEMPLATE_DIRS"]) # Remaining code is for Django 1.1 support. if VERSION >= (1, 2, 0): return # Add the dummy csrf_token template tag to builtins and remove # Django's CsrfViewMiddleware. add_to_builtins("mezzanine.core.templatetags.dummy_csrf") csrf_mw = "django.middleware.csrf.CsrfViewMiddleware" try: s["MIDDLEWARE_CLASSES"].remove(csrf_mw) except ValueError: pass # Use the single DB settings. old_db_settings_mapping = { "ENGINE": "DATABASE_ENGINE", "HOST": "DATABASE_HOST", "NAME": "DATABASE_NAME", "OPTIONS": "DATABASE_OPTIONS", "PASSWORD": "******", "PORT": "DATABASE_PORT", "USER": "******", "TEST_CHARSET": "TEST_DATABASE_CHARSET", "TEST_COLLATION": "TEST_DATABASE_COLLATION", "TEST_NAME": "TEST_DATABASE_NAME", } for (new_name, old_name) in old_db_settings_mapping.items(): value = s["DATABASES"]["default"].get(new_name) if value is not None: if new_name == "ENGINE" and value.startswith(backend_path): value = value.replace(backend_path, "", 1) s[old_name] = value # Revert to some old names. processors = list(s["TEMPLATE_CONTEXT_PROCESSORS"]) for (i, processor) in enumerate(processors): if processor == "django.contrib.auth.context_processors.auth": processors[i] = "django.core.context_processors.auth" s["TEMPLATE_CONTEXT_PROCESSORS"] = processors loaders = list(s["TEMPLATE_LOADERS"]) for (i, loader) in enumerate(loaders): if loader.startswith("django.") and loader.endswith(".Loader"): loaders[i] = loader.replace(".Loader", ".load_template_source", 1) s["TEMPLATE_LOADERS"] = loaders
def handle(self, *apps, **options): admin = options.get("admin") single_template = options.get("template") verbosity = int(options.get('verbosity', 1)) to_dir = settings.TEMPLATE_DIRS[0] templates = [] # Build a list of apps to copy templates from. if apps: # Ensure specified apps are installed. not_installed = set(apps) - set(settings.INSTALLED_APPS) if not_installed: raise CommandError("Apps are not in INSTALLED_APPS: " + ", ".join(not_installed)) else: # No apps specified - default to all in Mezzanine/Cartridge. apps = [ a for a in settings.INSTALLED_APPS if a.split(".")[0] in ("mezzanine", "cartridge") ] # Build a list of name/path pairs of all templates to copy. for app in apps: from_dir = os.path.join(path_for_import(app), "templates") if os.path.exists(from_dir): for (dirpath, dirnames, filenames) in os.walk(from_dir): for f in filenames: path = os.path.join(dirpath, f) name = path[len(from_dir) + 1:] # Bail if template isn't single template requested, # or an admin template without the admin option # specified. if single_template and name != single_template: continue if not admin and name.startswith("admin" + os.sep): continue templates.append((name, path, app)) # Copy templates. count = 0 template_src = {} for name, path, app in templates: dest = os.path.join(to_dir, name) # Prompt user to overwrite template if interactive and # template exists. if verbosity >= 2: self.stdout.write("\nCopying: %s" "\nFrom: %s" "\nTo: %s" "\n" % (name, path, dest)) if options.get("interactive") and os.path.exists(dest): if name in template_src: prev = ' [copied from %s]' % template_src[name] else: prev = '' self.stdout.write("While copying %s [from %s]:\n" % (name, app)) self.stdout.write("Template exists%s.\n" % prev) confirm = raw_input("Overwrite? (yes/no/abort): ") while True: if confirm in ("yes", "no"): break elif confirm == "abort": self.stdout.write("Aborted\n") return confirm = raw_input("Please enter either 'yes' or 'no': ") if confirm == "no": self.stdout.write("[Skipped]\n") continue try: os.makedirs(os.path.dirname(dest)) except OSError: pass shutil.copy2(path, dest) template_src[name] = app count += 1 if verbosity >= 1: s = "s" if count != 1 else "" self.stdout.write("\nCopied %s template%s\n" % (count, s))
def set_dynamic_settings(s): """ Called at the end of the project's settings module, and is passed its globals dict for updating with some final tweaks for settings that generally aren't specified, but can be given some better defaults based on other settings that have been specified. Broken out into its own function so that the code need not be replicated in the settings modules of other project-based apps that leverage Mezzanine's settings module. """ # Moves an existing list setting value to a different position. move = lambda n, k, i: s[n].insert(i, s[n].pop(s[n].index(k))) # Add a value to the end of a list setting if not in the list. append = lambda n, k: s[n].append(k) if k not in s[n] else None # Add a value to the start of a list setting if not in the list. prepend = lambda n, k: s[n].insert(0, k) if k not in s[n] else None # Remove a value from a list setting if in the list. remove = lambda n, k: s[n].remove(k) if k in s[n] else None s["TEMPLATE_DEBUG"] = s.get("TEMPLATE_DEBUG", s.get("DEBUG", False)) add_to_builtins("mezzanine.template.loader_tags") if not s.get("ALLOWED_HOSTS", []): warn("You haven't defined the ALLOWED_HOSTS settings, which " "Django requires. Will fall back to the domains " "configured as sites.") s["ALLOWED_HOSTS"] = SitesAllowedHosts() if s.get("TIME_ZONE", None) is None: tz = get_best_local_timezone() s["TIME_ZONE"] = tz warn("TIME_ZONE setting is not set, using closest match: %s" % tz) # Define some settings based on management command being run. management_command = sys.argv[1] if len(sys.argv) > 1 else "" # Some kind of testing is running via test or testserver. s["TESTING"] = management_command in ("test", "testserver") # Some kind of development server is running via runserver, # runserver_plus or harvest (lettuce) s["DEV_SERVER"] = management_command.startswith(("runserver", "harvest")) # Change tuple settings to lists for easier manipulation. s.setdefault("AUTHENTICATION_BACKENDS", defaults.AUTHENTICATION_BACKENDS) s.setdefault("STATICFILES_FINDERS", defaults.STATICFILES_FINDERS) tuple_list_settings = [ "AUTHENTICATION_BACKENDS", "INSTALLED_APPS", "MIDDLEWARE_CLASSES", "STATICFILES_FINDERS", "LANGUAGES", "TEMPLATE_CONTEXT_PROCESSORS" ] for setting in tuple_list_settings[:]: if not isinstance(s.get(setting, []), list): s[setting] = list(s[setting]) else: # Setting is already a list, so we'll exclude it from # the list of settings we'll revert back to tuples. tuple_list_settings.remove(setting) # From Mezzanine 3.1.2 and onward we added the context processor # for handling the page variable in templates - here we help # upgrading by adding it if missing, with a warning. This helper # can go away eventually. cp = "mezzanine.pages.context_processors.page" if ("mezzanine.pages" in s["INSTALLED_APPS"] and cp not in s["TEMPLATE_CONTEXT_PROCESSORS"]): warn("%s is required in the TEMPLATE_CONTEXT_PROCESSORS setting. " "Adding it now, but you should update settings.py to " "explicitly include it." % cp) append("TEMPLATE_CONTEXT_PROCESSORS", cp) # Set up cookie messaging if none defined. storage = "django.contrib.messages.storage.cookie.CookieStorage" s.setdefault("MESSAGE_STORAGE", storage) # If required, add django-modeltranslation for both tests and deployment if not s.get("USE_MODELTRANSLATION", False): remove("INSTALLED_APPS", "modeltranslation") else: try: __import__("modeltranslation") except ImportError: # django-modeltranslation is not installed, remove setting so # admin won't try to import it s["USE_MODELTRANSLATION"] = False remove("INSTALLED_APPS", "modeltranslation") warn("USE_MODETRANSLATION setting is set to True but django-" "modeltranslation is not installed. Disabling it.") else: # Force i18n so we are assured that modeltranslation is active s["USE_I18N"] = True append("INSTALLED_APPS", "modeltranslation") # Setup for optional apps. optional = list(s.get("OPTIONAL_APPS", [])) if s.get("USE_SOUTH") and VERSION < (1, 7): optional.append("south") elif not s.get("USE_SOUTH", True) and "south" in s["INSTALLED_APPS"]: s["INSTALLED_APPS"].remove("south") for app in optional: if app not in s["INSTALLED_APPS"]: try: __import__(app) except ImportError: pass else: s["INSTALLED_APPS"].append(app) if s["TESTING"]: # Following bits are work-arounds for some assumptions that # Django 1.5's tests make. # Triggers interactive superuser creation and some pyc/pyo tests # fail with standard permissions. remove("INSTALLED_APPS", "django_extensions") # To support migrations for both Django 1.7 and South, South's old # migrations for each app were moved into "app.migrations.south" # packages. Here we assign each of these to SOUTH_MIGRATION_MODULES # allowing South to find them. if "south" in s["INSTALLED_APPS"]: s.setdefault("SOUTH_MIGRATION_MODULES", {}) for app in s["INSTALLED_APPS"]: # We need to verify the path to the custom migrations # package exists for each app. We can't simply try # and import it, for some apps this causes side effects, # so we need to import something higher up to get at its # filesystem path - this can't be the actual app either, # side effects again, but we can generally import the # top-level package for apps that are contained within # one, which covers Mezzanine, Cartridge, Drum. if "." not in app: continue migrations = "%s.migrations.south" % app parts = migrations.split(".", 1) root = path_for_import(parts[0]) other = parts[1].replace(".", os.sep) if os.path.exists(os.path.join(root, other)): s["SOUTH_MIGRATION_MODULES"][app.split(".")[-1]] = migrations if "debug_toolbar" in s["INSTALLED_APPS"]: debug_mw = "debug_toolbar.middleware.DebugToolbarMiddleware" append("MIDDLEWARE_CLASSES", debug_mw) # Ensure debug_toolbar is before modeltranslation to avoid # races for configuration. move("INSTALLED_APPS", "debug_toolbar", 0) # If compressor installed, ensure it's configured and make # Mezzanine's settings available to its offline context, # since jQuery is configured via a setting. if "compressor" in s["INSTALLED_APPS"]: append("STATICFILES_FINDERS", "compressor.finders.CompressorFinder") s.setdefault( "COMPRESS_OFFLINE_CONTEXT", { "MEDIA_URL": s.get("MEDIA_URL", ""), "STATIC_URL": s.get("STATIC_URL", ""), }) def mezzanine_settings(): from mezzanine.conf import settings return settings s["COMPRESS_OFFLINE_CONTEXT"]["settings"] = mezzanine_settings # Ensure the Mezzanine auth backend is enabled if # mezzanine.accounts is being used. if "mezzanine.accounts" in s["INSTALLED_APPS"]: auth_backend = "mezzanine.core.auth_backends.MezzanineBackend" s.setdefault("AUTHENTICATION_BACKENDS", []) prepend("AUTHENTICATION_BACKENDS", auth_backend) # Ensure Grappelli is after Mezzanine in app order so that # admin templates are loaded in the correct order. grappelli_name = s.get("PACKAGE_NAME_GRAPPELLI") try: move("INSTALLED_APPS", grappelli_name, len(s["INSTALLED_APPS"])) except ValueError: s["GRAPPELLI_INSTALLED"] = False else: s["GRAPPELLI_INSTALLED"] = True # Ensure admin is at the bottom of the app order so that admin # templates are loaded in the correct order, and that staticfiles # is also at the end so its runserver can be overridden. apps = ["django.contrib.admin"] if VERSION >= (1, 7): apps += ["django.contrib.staticfiles"] for app in apps: try: move("INSTALLED_APPS", app, len(s["INSTALLED_APPS"])) except ValueError: pass # Add missing apps if existing apps depend on them. if "mezzanine.blog" in s["INSTALLED_APPS"]: append("INSTALLED_APPS", "mezzanine.generic") if "mezzanine.generic" in s["INSTALLED_APPS"]: s.setdefault("COMMENTS_APP", "mezzanine.generic") append("INSTALLED_APPS", "django_comments") # Ensure mezzanine.boot is first. try: move("INSTALLED_APPS", "mezzanine.boot", 0) except ValueError: pass # Remove caching middleware if no backend defined. if not (s.get("CACHE_BACKEND") or s.get("CACHES")): s["MIDDLEWARE_CLASSES"] = [ mw for mw in s["MIDDLEWARE_CLASSES"] if not (mw.endswith("UpdateCacheMiddleware") or mw.endswith("FetchFromCacheMiddleware")) ] # If only LANGUAGE_CODE has been defined, ensure the other required # settings for translations are configured. if (s.get("LANGUAGE_CODE") and len(s.get("LANGUAGES", [])) == 1 and s["LANGUAGE_CODE"] != s["LANGUAGES"][0][0]): s["USE_I18N"] = True s["LANGUAGES"] = [(s["LANGUAGE_CODE"], "")] # Revert tuple settings back to tuples. for setting in tuple_list_settings: s[setting] = tuple(s[setting]) # Some settings tweaks for different DB engines. for (key, db) in s["DATABASES"].items(): shortname = db["ENGINE"].split(".")[-1] if shortname == "sqlite3": # If the Sqlite DB name doesn't contain a path, assume # it's in the project directory and add the path to it. if "NAME" in db and os.sep not in db["NAME"]: db_path = os.path.join(s.get("PROJECT_ROOT", ""), db["NAME"]) s["DATABASES"][key]["NAME"] = db_path elif shortname == "mysql": # Required MySQL collation for tests. s["DATABASES"][key]["TEST_COLLATION"] = "utf8_general_ci"
import os.path from docutils.core import publish_string from docutils.writers.html4css1 import Writer,HTMLTranslator import mezzanine from mezzanine.utils.importing import path_for_import # Convert the README file from RST to HTML. writer = Writer() writer.translator_class = HTMLTranslator path = os.path.join(path_for_import("mezzanine"), "..", "README.rst") try: with open(path, "r") as f: data = f.read() except IOError: README = "" else: README = publish_string(data, writer=writer) # Grab the list items inside a blockquote after each title, and # assign them to variables for the homepage. project_context = {"version": mezzanine.__version__} for section in ("Sites Using Mezzanine", "Quotes", "Features"): items = README.split("<h2>%s</h2>" % section)[1] \ .split("<li>", 1)[1].split("</li>\n</ul>")[0] \ .split("</li>\n<li>") project_context[section.split()[0].lower()] = items
import os.path from django.conf import settings from django.template.defaultfilters import slugify from docutils.core import publish_string from docutils.writers.html4css1 import Writer, HTMLTranslator import mezzanine from mezzanine.utils.importing import path_for_import # Convert the overview documentation page from RST to HTML. writer = Writer() writer.translator_class = HTMLTranslator try: path = os.path.join(path_for_import("mezzanine"), "..", "docs", "overview.rst") with open(path, "r") as f: data = f.read() path = os.path.join(path_for_import("mezzanine"), "..", "README.rst") with open(path, "r") as f: data = data.replace(".. include:: ../README.rst", f.read()) except IOError: OVERVIEW = "" else: OVERVIEW = publish_string(data, writer=writer) # Grab the list items inside a blockquote after each title, and # assign them to variables for the homepage. project_context = {"version": mezzanine.__version__} for section in ("Sites Using Mezzanine", "Quotes", "Features"):
def create_project(): """ Copies the contents of the project_template directory to a new directory specified as an argument to the command line. """ parser = OptionParser(usage="usage: %prog [options] project_name") parser.add_option( "-a", "--alternate", dest="alt", metavar="PACKAGE", help="Alternate package to use, containing a project_template") parser.add_option("-s", "--source", dest="copy_source", default=False, action="store_true", help="Copy package source to new project") parser.add_option("-t", "--templates", dest="copy_templates", default=True, action="store_false", help="Copy templates to the project [default]") (options, args) = parser.parse_args() if len(args) != 1: parser.error("project_name must be specified") project_name = args[0] if project_name.startswith("-"): parser.error("project_name cannot start with '-'") project_path = os.path.join(os.getcwd(), project_name) # Ensure the given directory name doesn't clash with an existing # Python package/module. try: __import__(project_name) except ImportError: pass else: parser.error("'%s' conflicts with the name of an existing " "Python module and cannot be used as a project name. " "Please try another name." % project_name) # Create the list of packages to build from - at this stage it # should only be one or two names, mezzanine plus an alternate # package. packages = ["mezzanine"] if options.alt: packages.append(options.alt) for package_name in packages: try: __import__(package_name) except ImportError: parser.error("Could not import package '%s'" % package_name) # Build the project up copying over the project_template from # each of the packages. template_path = os.path.join(project_path, "templates") for package_name in packages: package_path = path_for_import(package_name) if options.copy_source: copy_tree(package_path, os.path.join(project_path, package_name)) copy_tree(os.path.join(package_path, "project_template"), project_path) move(os.path.join(project_path, "local_settings.py.template"), os.path.join(project_path, "local_settings.py")) if options.copy_templates: for app_dir in os.listdir(package_path): template_dir = os.path.join(package_path, app_dir, "templates") if os.path.isdir(template_dir): copy_tree(template_dir, template_path) # Remove admin templates from the project to allow for easier # upgrading, as these templates need not be customised. if options.copy_templates: try: rmtree(os.path.join(template_path, "admin")) except OSError: pass # Generate a unique SECREY_KEY for the project's setttings module. settings_path = os.path.join(os.getcwd(), project_name, "settings.py") with open(settings_path, "r") as f: data = f.read() with open(settings_path, "w") as f: secret_key = "%s%s%s" % (uuid4(), uuid4(), uuid4()) f.write(data.replace("%(SECRET_KEY)s", secret_key)) # Clean up pyc files. for (root, dirs, files) in os.walk(project_path, False): for f in files: if f.endswith(".pyc"): os.remove(os.path.join(root, f))
def set_dynamic_settings(s): """ Called at the end of the project's settings module and is passed its globals dict for updating with some final tweaks for settings that generally aren't specified but can be given some better defaults based on other settings that have been specified. Broken out into its own function so that the code need not be replicated in the settings modules of other project-based apps that leverage Mezzanine's settings module. """ s["TEMPLATE_DEBUG"] = s["DEBUG"] add_to_builtins("mezzanine.template.loader_tags") # Define some settings based on management command being run. management_command = sys.argv[1] if len(sys.argv) > 1 else "" # Some kind of testing is running via test or testserver s["TESTING"] = management_command.startswith("test") # Some kind of development server is running via runserver or # runserver_plus s["DEV_SERVER"] = management_command.startswith("runserver") # Change INSTALLED_APPS to a list for easier manipulation. s["INSTALLED_APPS"] = list(s["INSTALLED_APPS"]) # Set up cookie messaging if none specified for Django >= 1.3 if VERSION >= (1, 3, 0): msg_mw = "django.contrib.messages.middleware.MessageMiddleware" if msg_mw not in s["MIDDLEWARE_CLASSES"]: s["MIDDLEWARE_CLASSES"] = tuple(s["MIDDLEWARE_CLASSES"]) s["MIDDLEWARE_CLASSES"] += (msg_mw, ) if not s.get("MESSAGE_STORAGE"): storage = "django.contrib.messages.storage.cookie.CookieStorage" s["MESSAGE_STORAGE"] = storage # Setup for optional apps. if not s["TESTING"]: optional = list(s.get("OPTIONAL_APPS", [])) if s.get("USE_SOUTH"): optional.append("south") elif not s.get("USE_SOUTH", True) and "south" in s["INSTALLED_APPS"]: s["INSTALLED_APPS"].remove("south") for app in optional: if app not in s["INSTALLED_APPS"]: try: __import__(app) except ImportError: pass else: s["INSTALLED_APPS"].append(app) if "debug_toolbar" in s["INSTALLED_APPS"]: debug_mw = "debug_toolbar.middleware.DebugToolbarMiddleware" if debug_mw not in s["MIDDLEWARE_CLASSES"]: s["MIDDLEWARE_CLASSES"] = tuple(s["MIDDLEWARE_CLASSES"]) s["MIDDLEWARE_CLASSES"] += (debug_mw, ) if s.get("PACKAGE_NAME_FILEBROWSER") in s["INSTALLED_APPS"]: s["FILEBROWSER_URL_FILEBROWSER_MEDIA"] = "/filebrowser/media/" fb_path = path_for_import(s["PACKAGE_NAME_FILEBROWSER"]) fb_media_path = os.path.join(fb_path, "media", "filebrowser") s["FILEBROWSER_PATH_FILEBROWSER_MEDIA"] = fb_media_path grappelli_name = s.get("PACKAGE_NAME_GRAPPELLI") s["GRAPPELLI_INSTALLED"] = grappelli_name in s["INSTALLED_APPS"] if s["GRAPPELLI_INSTALLED"]: # Ensure Grappelli is after Mezzanine in app order so that # admin templates are loaded in the correct order. s["INSTALLED_APPS"].remove(grappelli_name) s["INSTALLED_APPS"].append(grappelli_name) s.setdefault("GRAPPELLI_ADMIN_HEADLINE", "Mezzanine") s.setdefault("GRAPPELLI_ADMIN_TITLE", "Mezzanine") grappelli_path = path_for_import(s["PACKAGE_NAME_GRAPPELLI"]) s["GRAPPELLI_MEDIA_PATH"] = os.path.join(grappelli_path, "media") # Adopted from django.core.management.commands.runserver # Easiest way so far to actually get all the media for # Grappelli working with the dev server is to hard-code the # host:port to ADMIN_MEDIA_PREFIX, so here we check for a # custom host:port before doing this. if len(sys.argv) >= 2 and sys.argv[1] == "runserver": addrport = "" if len(sys.argv) > 2: addrport = sys.argv[2] if not addrport: addr, port = "", "8000" else: try: addr, port = addrport.split(":") except ValueError: addr, port = "", addrport if not addr: addr = "127.0.0.1" parts = (addr, port, s["ADMIN_MEDIA_PREFIX"]) s["ADMIN_MEDIA_PREFIX"] = "http://%s:%s%s" % parts # Ensure admin is last in the app order so that admin templates # are loaded in the correct order. if "django.contrib.admin" in s["INSTALLED_APPS"]: s["INSTALLED_APPS"].remove("django.contrib.admin") s["INSTALLED_APPS"].append("django.contrib.admin") # Add missing apps if existing apps depend on them. if ("mezzanine.blog" in s["INSTALLED_APPS"] and "mezzanine.generic" not in s["INSTALLED_APPS"]): s["INSTALLED_APPS"].append("mezzanine.generic") if "mezzanine.generic" in s["INSTALLED_APPS"]: s["COMMENTS_APP"] = "mezzanine.generic" if "django.contrib.comments" not in s["INSTALLED_APPS"]: s["INSTALLED_APPS"].append("django.contrib.comments") # Change INSTALLED_APPS back to a tuple. s["INSTALLED_APPS"] = tuple(s["INSTALLED_APPS"]) # Caching. if not (s.get("CACHE_BACKEND") or s.get("CACHES")): s["MIDDLEWARE_CLASSES"] = [ mw for mw in s["MIDDLEWARE_CLASSES"] if not mw.endswith("UpdateCacheMiddleware") or mw.endswith("FetchFromCacheMiddleware") ] # Some settings tweaks for different DB engines. backend_path = "django.db.backends." backend_shortnames = ( "postgresql_psycopg2", "postgresql", "mysql", "sqlite3", "oracle", ) for (key, db) in s["DATABASES"].items(): if db["ENGINE"] in backend_shortnames: s["DATABASES"][key]["ENGINE"] = backend_path + db["ENGINE"] shortname = db["ENGINE"].split(".")[-1] if shortname == "sqlite3" and os.sep not in db["NAME"]: # If the Sqlite DB name doesn't contain a path, assume # it's in the project directory and add the path to it. s["DATABASES"][key]["NAME"] = os.path.join( s.get("PROJECT_ROOT", ""), db["NAME"]) elif shortname == "mysql": # Required MySQL collation for tests. s["DATABASES"][key]["TEST_COLLATION"] = "utf8_general_ci" elif shortname.startswith("postgresql") and not s.get("TIME_ZONE", 1): # Specifying a blank time zone to fall back to the # system's time zone will break table creation in Postgres # so remove it. del s["TIME_ZONE"] # If a theme is defined then add its template path to the # template dirs. theme = s.get("THEME") if theme: theme_templates = os.path.join(path_for_import(theme), "templates") s["TEMPLATE_DIRS"] = (theme_templates, ) + tuple(s["TEMPLATE_DIRS"]) # Remaining code is for Django 1.1 support. if VERSION >= (1, 2, 0): return # Add the dummy csrf_token template tag to builtins and remove # Django's CsrfViewMiddleware. add_to_builtins("mezzanine.core.templatetags.dummy_csrf") s["MIDDLEWARE_CLASSES"] = [ mw for mw in s["MIDDLEWARE_CLASSES"] if mw != "django.middleware.csrf.CsrfViewMiddleware" ] # Use the single DB settings. old_db_settings_mapping = { "ENGINE": "DATABASE_ENGINE", "HOST": "DATABASE_HOST", "NAME": "DATABASE_NAME", "OPTIONS": "DATABASE_OPTIONS", "PASSWORD": "******", "PORT": "DATABASE_PORT", "USER": "******", "TEST_CHARSET": "TEST_DATABASE_CHARSET", "TEST_COLLATION": "TEST_DATABASE_COLLATION", "TEST_NAME": "TEST_DATABASE_NAME", } for (new_name, old_name) in old_db_settings_mapping.items(): value = s["DATABASES"]["default"].get(new_name) if value is not None: if new_name == "ENGINE" and value.startswith(backend_path): value = value.replace(backend_path, "", 1) s[old_name] = value # Revert to some old names. processors = list(s["TEMPLATE_CONTEXT_PROCESSORS"]) for (i, processor) in enumerate(processors): if processor == "django.contrib.auth.context_processors.auth": processors[i] = "django.core.context_processors.auth" s["TEMPLATE_CONTEXT_PROCESSORS"] = processors loaders = list(s["TEMPLATE_LOADERS"]) for (i, loader) in enumerate(loaders): if loader.startswith("django.") and loader.endswith(".Loader"): loaders[i] = loader.replace(".Loader", ".load_template_source", 1) s["TEMPLATE_LOADERS"] = loaders
#!/usr/bin/env python # When project_template is used as the actual project during Mezzanine # development, insert the development path into sys.path so that the # development version of Mezzanine is used rather than the installed # version. import os import sys project_path = os.path.dirname(os.path.abspath(__file__)) project_dir = project_path.split(os.sep)[-1] if project_dir == "project_template": dev_path = os.path.abspath(os.path.join(project_path, "..", "..")) if dev_path not in sys.path: sys.path.insert(0, dev_path) from mezzanine.utils.importing import path_for_import mezzanine_path = path_for_import("mezzanine") assert os.path.abspath(os.path.join(mezzanine_path, "..")) == dev_path # Corrects some pathing issues in various contexts, such as cron jobs. os.chdir(project_path) from django.core.management import execute_manager try: import settings # Assumed to be in the same directory. except ImportError, e: import sys sys.stderr.write("Error: Can't find the file 'settings.py' in the " "directory containing %r. It appears you've customized things.\n" "You'll have to run django-admin.py, passing it your settings " "module.\n(If the file settings.py does indeed exist, it's causing " "an ImportError somehow.)\n\n%s" % (__file__, e))
def set_dynamic_settings(s): """ Called at the end of the project's settings module and is passed its globals dict for updating with some final tweaks for settings that generally aren't specified but can be given some better defaults based on other settings that have been specified. Broken out into its own function so that the code need not be replicated in the settings modules of other project-based apps that leverage Mezzanine's settings module. """ s["TEMPLATE_DEBUG"] = s["DEBUG"] add_to_builtins("mezzanine.template.loader_tags") # Define some settings based on management command being run. management_command = sys.argv[1] if len(sys.argv) > 1 else "" # Some kind of testing is running via test or testserver s["TESTING"] = management_command.startswith("test") # Some kind of development server is running via runserver or runserver_plus s["DEV_SERVER"] = management_command.startswith("runserver") # Change INSTALLED_APPS to a list for easier manipulation. s["INSTALLED_APPS"] = list(s["INSTALLED_APPS"]) # Setup for optional apps. if not s["TESTING"]: for app in s.get("OPTIONAL_APPS", []): if app not in s["INSTALLED_APPS"]: try: __import__(app) except ImportError: pass else: s["INSTALLED_APPS"].append(app) if "debug_toolbar" in s["INSTALLED_APPS"]: debug_mw = "debug_toolbar.middleware.DebugToolbarMiddleware" if debug_mw not in s["MIDDLEWARE_CLASSES"]: s["MIDDLEWARE_CLASSES"] = tuple(s["MIDDLEWARE_CLASSES"]) s["MIDDLEWARE_CLASSES"] += (debug_mw,) if s.get("PACKAGE_NAME_FILEBROWSER") in s["INSTALLED_APPS"]: s["FILEBROWSER_URL_FILEBROWSER_MEDIA"] = "/filebrowser/media/" fb_path = path_for_import(s["PACKAGE_NAME_FILEBROWSER"]) fb_media_path = os.path.join(fb_path, "media", "filebrowser") s["FILEBROWSER_PATH_FILEBROWSER_MEDIA"] = fb_media_path grappelli_name = s.get("PACKAGE_NAME_GRAPPELLI") s["GRAPPELLI_INSTALLED"] = grappelli_name in s["INSTALLED_APPS"] if s["GRAPPELLI_INSTALLED"]: # Ensure Grappelli is after Mezzanine in app order so that # admin templates are loaded in the correct order. s["INSTALLED_APPS"].remove(grappelli_name) s["INSTALLED_APPS"].append(grappelli_name) s["GRAPPELLI_ADMIN_HEADLINE"] = "Mezzanine" s["GRAPPELLI_ADMIN_TITLE"] = "Mezzanine" grappelli_path = path_for_import(s["PACKAGE_NAME_GRAPPELLI"]) s["GRAPPELLI_MEDIA_PATH"] = os.path.join(grappelli_path, "media") # Adopted from django.core.management.commands.runserver # Easiest way so far to actually get all the media for Grappelli # working with the dev server is to hard-code the host:port to # ADMIN_MEDIA_PREFIX, so here we check for a custom host:port # before doing this. if len(sys.argv) >= 2 and sys.argv[1] == "runserver": addrport = "" if len(sys.argv) > 2: addrport = sys.argv[2] if not addrport: addr, port = "", "8000" else: try: addr, port = addrport.split(":") except ValueError: addr, port = "", addrport if not addr: addr = "127.0.0.1" parts = (addr, port, s["ADMIN_MEDIA_PREFIX"]) s["ADMIN_MEDIA_PREFIX"] = "http://%s:%s%s" % parts # Ensure admin is last in the app order so that admin templates # are loaded in the correct order. if "django.contrib.admin" in s["INSTALLED_APPS"]: s["INSTALLED_APPS"].remove("django.contrib.admin") s["INSTALLED_APPS"].append("django.contrib.admin") # Change INSTALLED_APPS back to a tuple. s["INSTALLED_APPS"] = tuple(s["INSTALLED_APPS"]) # Caching. if not (s.get("CACHE_BACKEND") or s.get("CACHES")): s["MIDDLEWARE_CLASSES"] = [mw for mw in s["MIDDLEWARE_CLASSES"] if not mw.endswith("UpdateCacheMiddleware") or mw.endswith("FetchFromCacheMiddleware")] # Some settings tweaks for different DB engines. backend_path = "django.db.backends." backend_shortnames = ( "postgresql_psycopg2", "postgresql", "mysql", "sqlite3", "oracle", ) for (key, db) in s["DATABASES"].items(): if db["ENGINE"] in backend_shortnames: s["DATABASES"][key]["ENGINE"] = backend_path + db["ENGINE"] shortname = db["ENGINE"].split(".")[-1] if shortname == "sqlite3" and os.sep not in db["NAME"]: # If the Sqlite DB name doesn't contain a path, assume it's # in the project directory and add the path to it. s["DATABASES"][key]["NAME"] = os.path.join( s.get("PROJECT_ROOT", ""), db["NAME"]) elif shortname == "mysql": # Required MySQL collation for tests. s["DATABASES"][key]["TEST_COLLATION"] = "utf8_general_ci" elif shortname.startswith("postgresql") and not s.get("TIME_ZONE", 1): # Specifying a blank time zone to fall back to the system's # time zone will break table creation in Postgres so remove it. del s["TIME_ZONE"] # If a theme is defined then add its template path to the template dirs. theme = s.get("THEME") if theme: theme_templates = os.path.join(path_for_import(theme), "templates") s["TEMPLATE_DIRS"] = (theme_templates,) + tuple(s["TEMPLATE_DIRS"]) # Remaining code is for Django 1.1 support. if VERSION >= (1, 2, 0): return # Add the dummy csrf_token template tag to builtins and remove # Django's CsrfViewMiddleware. add_to_builtins("mezzanine.core.templatetags.dummy_csrf") s["MIDDLEWARE_CLASSES"] = [mw for mw in s["MIDDLEWARE_CLASSES"] if mw != "django.middleware.csrf.CsrfViewMiddleware"] # Use the single DB settings. old_db_settings_mapping = { "ENGINE": "DATABASE_ENGINE", "HOST": "DATABASE_HOST", "NAME": "DATABASE_NAME", "OPTIONS": "DATABASE_OPTIONS", "PASSWORD": "******", "PORT": "DATABASE_PORT", "USER": "******", "TEST_CHARSET": "TEST_DATABASE_CHARSET", "TEST_COLLATION": "TEST_DATABASE_COLLATION", "TEST_NAME": "TEST_DATABASE_NAME", } for (new_name, old_name) in old_db_settings_mapping.items(): value = s["DATABASES"]["default"].get(new_name) if value is not None: if new_name == "ENGINE" and value.startswith(backend_path): value = value.replace(backend_path, "", 1) s[old_name] = value # Revert to some old names. processors = list(s["TEMPLATE_CONTEXT_PROCESSORS"]) for (i, processor) in enumerate(processors): if processor == "django.contrib.auth.context_processors.auth": processors[i] = "django.core.context_processors.auth" s["TEMPLATE_CONTEXT_PROCESSORS"] = processors loaders = list(s["TEMPLATE_LOADERS"]) for (i, loader) in enumerate(loaders): if loader.startswith("django.") and loader.endswith(".Loader"): loaders[i] = loader.replace(".Loader", ".load_template_source", 1) s["TEMPLATE_LOADERS"] = loaders
def set_dynamic_settings(s): """ Called at the end of the project's settings module, and is passed its globals dict for updating with some final tweaks for settings that generally aren't specified, but can be given some better defaults based on other settings that have been specified. Broken out into its own function so that the code need not be replicated in the settings modules of other project-based apps that leverage Mezzanine's settings module. """ # Moves an existing list setting value to a different position. move = lambda n, k, i: s[n].insert(i, s[n].pop(s[n].index(k))) # Add a value to the end of a list setting if not in the list. append = lambda n, k: s[n].append(k) if k not in s[n] else None # Add a value to the start of a list setting if not in the list. prepend = lambda n, k: s[n].insert(0, k) if k not in s[n] else None # Remove a value from a list setting if in the list. remove = lambda n, k: s[n].remove(k) if k in s[n] else None s["TEMPLATE_DEBUG"] = s.get("TEMPLATE_DEBUG", s.get("DEBUG", False)) add_to_builtins("mezzanine.template.loader_tags") if not s.get("ALLOWED_HOSTS", []): warn("You haven't defined the ALLOWED_HOSTS settings, which " "Django requires. Will fall back to the domains " "configured as sites.") s["ALLOWED_HOSTS"] = SitesAllowedHosts() if s.get("TIME_ZONE", None) is None: tz = get_best_local_timezone() s["TIME_ZONE"] = tz warn("TIME_ZONE setting is not set, using closest match: %s" % tz) # Define some settings based on management command being run. management_command = sys.argv[1] if len(sys.argv) > 1 else "" # Some kind of testing is running via test or testserver. s["TESTING"] = management_command in ("test", "testserver") # Some kind of development server is running via runserver, # runserver_plus or harvest (lettuce) s["DEV_SERVER"] = management_command.startswith(("runserver", "harvest")) # Change tuple settings to lists for easier manipulation. s.setdefault("AUTHENTICATION_BACKENDS", defaults.AUTHENTICATION_BACKENDS) s.setdefault("STATICFILES_FINDERS", defaults.STATICFILES_FINDERS) tuple_list_settings = ["AUTHENTICATION_BACKENDS", "INSTALLED_APPS", "MIDDLEWARE_CLASSES", "STATICFILES_FINDERS", "LANGUAGES", "TEMPLATE_CONTEXT_PROCESSORS"] for setting in tuple_list_settings[:]: if not isinstance(s.get(setting, []), list): s[setting] = list(s[setting]) else: # Setting is already a list, so we'll exclude it from # the list of settings we'll revert back to tuples. tuple_list_settings.remove(setting) # From Mezzanine 3.1.2 and onward we added the context processor # for handling the page variable in templates - here we help # upgrading by adding it if missing, with a warning. This helper # can go away eventually. cp = "mezzanine.pages.context_processors.page" if ("mezzanine.pages" in s["INSTALLED_APPS"] and cp not in s["TEMPLATE_CONTEXT_PROCESSORS"]): warn("%s is required in the TEMPLATE_CONTEXT_PROCESSORS setting. " "Adding it now, but you should update settings.py to " "explicitly include it." % cp) append("TEMPLATE_CONTEXT_PROCESSORS", cp) # Set up cookie messaging if none defined. storage = "django.contrib.messages.storage.cookie.CookieStorage" s.setdefault("MESSAGE_STORAGE", storage) # If required, add django-modeltranslation for both tests and deployment if not s.get("USE_MODELTRANSLATION", False): remove("INSTALLED_APPS", "modeltranslation") else: try: __import__("modeltranslation") except ImportError: # django-modeltranslation is not installed, remove setting so # admin won't try to import it s["USE_MODELTRANSLATION"] = False remove("INSTALLED_APPS", "modeltranslation") warn("USE_MODETRANSLATION setting is set to True but django-" "modeltranslation is not installed. Disabling it.") else: # Force i18n so we are assured that modeltranslation is active s["USE_I18N"] = True append("INSTALLED_APPS", "modeltranslation") # Ensure mezzanine.pages falls before any apps that subclass the # Page model, otherwise modeltranslation doesn't work. get_pos = lambda n, k: s[n].index(k) if k in s[n] else len(s[n]) page_pos = get_pos("INSTALLED_APPS", "mezzanine.pages") subclass_pos = min([get_pos("INSTALLED_APPS", app) for app in ("mezzanine.forms", "mezzanine.gallery", "cartridge.shop")]) if page_pos > subclass_pos: move("INSTALLED_APPS", "mezzanine.pages", subclass_pos) # Setup for optional apps. optional = list(s.get("OPTIONAL_APPS", [])) if s.get("USE_SOUTH") and VERSION < (1, 7): optional.append("south") elif not s.get("USE_SOUTH", True) and "south" in s["INSTALLED_APPS"]: s["INSTALLED_APPS"].remove("south") for app in optional: if app not in s["INSTALLED_APPS"]: try: __import__(app) except ImportError: pass else: s["INSTALLED_APPS"].append(app) if s["TESTING"]: # Following bits are work-arounds for some assumptions that # Django 1.5's tests make. # Triggers interactive superuser creation and some pyc/pyo tests # fail with standard permissions. remove("INSTALLED_APPS", "django_extensions") # To support migrations for both Django 1.7 and South, South's old # migrations for each app were moved into "app.migrations.south" # packages. Here we assign each of these to SOUTH_MIGRATION_MODULES # allowing South to find them. if "south" in s["INSTALLED_APPS"]: s.setdefault("SOUTH_MIGRATION_MODULES", {}) for app in s["INSTALLED_APPS"]: # We need to verify the path to the custom migrations # package exists for each app. We can't simply try # and import it, for some apps this causes side effects, # so we need to import something higher up to get at its # filesystem path - this can't be the actual app either, # side effects again, but we can generally import the # top-level package for apps that are contained within # one, which covers Mezzanine, Cartridge, Drum. if "." not in app: continue migrations = "%s.migrations.south" % app parts = migrations.split(".", 1) root = path_for_import(parts[0]) other = parts[1].replace(".", os.sep) if os.path.exists(os.path.join(root, other)): s["SOUTH_MIGRATION_MODULES"][app.split(".")[-1]] = migrations if "debug_toolbar" in s["INSTALLED_APPS"]: debug_mw = "debug_toolbar.middleware.DebugToolbarMiddleware" append("MIDDLEWARE_CLASSES", debug_mw) # Ensure debug_toolbar is before modeltranslation to avoid # races for configuration. move("INSTALLED_APPS", "debug_toolbar", 0) # If compressor installed, ensure it's configured and make # Mezzanine's settings available to its offline context, # since jQuery is configured via a setting. if "compressor" in s["INSTALLED_APPS"]: append("STATICFILES_FINDERS", "compressor.finders.CompressorFinder") s.setdefault("COMPRESS_OFFLINE_CONTEXT", { "MEDIA_URL": s.get("MEDIA_URL", ""), "STATIC_URL": s.get("STATIC_URL", ""), }) def mezzanine_settings(): from mezzanine.conf import settings return settings s["COMPRESS_OFFLINE_CONTEXT"]["settings"] = mezzanine_settings # Ensure the Mezzanine auth backend is enabled if # mezzanine.accounts is being used. if "mezzanine.accounts" in s["INSTALLED_APPS"]: auth_backend = "mezzanine.core.auth_backends.MezzanineBackend" s.setdefault("AUTHENTICATION_BACKENDS", []) prepend("AUTHENTICATION_BACKENDS", auth_backend) # Ensure Grappelli is after Mezzanine in app order so that # admin templates are loaded in the correct order. grappelli_name = s.get("PACKAGE_NAME_GRAPPELLI") try: move("INSTALLED_APPS", grappelli_name, len(s["INSTALLED_APPS"])) except ValueError: s["GRAPPELLI_INSTALLED"] = False else: s["GRAPPELLI_INSTALLED"] = True # Ensure admin is at the bottom of the app order so that admin # templates are loaded in the correct order, and that staticfiles # is also at the end so its runserver can be overridden. apps = ["django.contrib.admin"] if VERSION >= (1, 7): apps += ["django.contrib.staticfiles"] for app in apps: try: move("INSTALLED_APPS", app, len(s["INSTALLED_APPS"])) except ValueError: pass # Add missing apps if existing apps depend on them. if "mezzanine.blog" in s["INSTALLED_APPS"]: append("INSTALLED_APPS", "mezzanine.generic") if "mezzanine.generic" in s["INSTALLED_APPS"]: s.setdefault("COMMENTS_APP", "mezzanine.generic") append("INSTALLED_APPS", "django_comments") # Ensure mezzanine.boot is first. try: move("INSTALLED_APPS", "mezzanine.boot", 0) except ValueError: pass # Remove caching middleware if no backend defined. if not (s.get("CACHE_BACKEND") or s.get("CACHES")): s["MIDDLEWARE_CLASSES"] = [mw for mw in s["MIDDLEWARE_CLASSES"] if not (mw.endswith("UpdateCacheMiddleware") or mw.endswith("FetchFromCacheMiddleware"))] # If only LANGUAGE_CODE has been defined, ensure the other required # settings for translations are configured. if (s.get("LANGUAGE_CODE") and len(s.get("LANGUAGES", [])) == 1 and s["LANGUAGE_CODE"] != s["LANGUAGES"][0][0]): s["USE_I18N"] = True s["LANGUAGES"] = [(s["LANGUAGE_CODE"], "")] # Revert tuple settings back to tuples. for setting in tuple_list_settings: s[setting] = tuple(s[setting]) # Some settings tweaks for different DB engines. for (key, db) in s["DATABASES"].items(): shortname = db["ENGINE"].split(".")[-1] if shortname == "sqlite3": # If the Sqlite DB name doesn't contain a path, assume # it's in the project directory and add the path to it. if "NAME" in db and os.sep not in db["NAME"]: db_path = os.path.join(s.get("PROJECT_ROOT", ""), db["NAME"]) s["DATABASES"][key]["NAME"] = db_path elif shortname == "mysql": # Required MySQL collation for tests. s["DATABASES"][key]["TEST_COLLATION"] = "utf8_general_ci"
def handle(self, *apps, **options): admin = options.get("admin") single_template = options.get("template") verbosity = int(options.get('verbosity', 1)) to_dir = settings.TEMPLATE_DIRS[0] templates = [] # Build a list of apps to copy templates from. if apps: # Ensure specified apps are installed. not_installed = set(apps) - set(settings.INSTALLED_APPS) if not_installed: raise CommandError("Apps are not in INSTALLED_APPS: " + ", ".join(not_installed)) else: # No apps specified - default to all in Mezzanine/Cartridge. apps = [a for a in settings.INSTALLED_APPS if a.split(".")[0] in ("mezzanine", "cartridge")] # Build a list of name/path pairs of all templates to copy. for app in apps: from_dir = os.path.join(path_for_import(app), "templates") if os.path.exists(from_dir): for (dirpath, dirnames, filenames) in os.walk(from_dir): for f in filenames: path = os.path.join(dirpath, f) name = path[len(from_dir) + 1:] # Bail if template isn't single template requested, # or an admin template without the admin option # specified. if single_template and name != single_template: continue if not admin and name.startswith("admin" + os.sep): continue templates.append((name, path, app)) # Copy templates. count = 0 template_src = {} for name, path, app in templates: dest = os.path.join(to_dir, name) # Prompt user to overwrite template if interactive and # template exists. if verbosity >= 2: self.stdout.write("\nCopying: %s" "\nFrom: %s" "\nTo: %s" "\n" % (name, path, dest)) copy = True if options.get("interactive") and os.path.exists(dest): if name in template_src: prev = ' [copied from %s]' % template_src[name] else: prev = '' self.stdout.write("While copying %s [from %s]:\n" % (name, app)) self.stdout.write("Template exists%s.\n" % prev) confirm = input("Overwrite? (yes/no/abort): ") while confirm not in ("yes", "no", "abort"): confirm = input( "Please enter either 'yes', 'no' or 'abort': ") if confirm == "abort": self.stdout.write("Aborted\n") break # exit templates copying loop elif confirm == "no": self.stdout.write("[Skipped]\n") copy = False if copy: try: os.makedirs(os.path.dirname(dest)) except OSError: pass shutil.copy2(path, dest) template_src[name] = app count += 1 if verbosity >= 1: s = "s" if count != 1 else "" self.stdout.write("\nCopied %s template%s\n" % (count, s))
def create_project(): """ Copies the contents of the project_template directory to a new directory specified as an argument to the command line. """ parser = OptionParser(usage="usage: %prog [options] project_name") parser.add_option("-a", "--alternate", dest="alt", metavar="PACKAGE", help="Alternate package to use, containing a project_template") (options, args) = parser.parse_args() if len(args) != 1: parser.error("project_name must be specified") project_name = args[0] if project_name.startswith("-"): parser.error("project_name cannot start with '-'") project_path = os.path.join(os.getcwd(), project_name) # Ensure the given directory name doesn't clash with an existing # Python package/module. try: __import__(project_name) except ImportError: pass else: parser.error("'%s' conflicts with the name of an existing " "Python module and cannot be used as a project " "name. Please try another name." % project_name) # Create the list of packages to build from - at this stage it # should only be one or two names, mezzanine plus an alternate # package. packages = ["mezzanine"] if options.alt: packages.append(options.alt) for package_name in packages: try: __import__(package_name) except ImportError: parser.error("Could not import package '%s'" % package_name) # Build the project up copying over the project_template from # each of the packages. An alternate package will overwrite # files from Mezzanine. for package_name in packages: package_path = path_for_import(package_name) copy_tree(os.path.join(package_path, "project_template"), project_path) move(os.path.join(project_path, "local_settings.py.template"), os.path.join(project_path, "local_settings.py")) # Generate a unique SECRET_KEY for the project's setttings module. settings_path = os.path.join(os.getcwd(), project_name, "local_settings.py") with open(settings_path, "r") as f: data = f.read() with open(settings_path, "w") as f: make_key = lambda: "%s%s%s" % (uuid4(), uuid4(), uuid4()) data = data.replace("%(SECRET_KEY)s", make_key()) data = data.replace("%(NEVERCACHE_KEY)s", make_key()) f.write(data) # Clean up pyc files. for (root, dirs, files) in os.walk(project_path, False): for f in files: if f.endswith(".pyc"): os.remove(os.path.join(root, f))