Repository URL to install this package:
|
Version:
2.4.1b3 ▾
|
#!/usr/bin/env python
import fileinput
import fnmatch
import os
import re
import sys
from argparse import ArgumentParser
from difflib import unified_diff
from django.core.management import ManagementUtility
# Need to use the django.utils.six version of print, to avoid a syntax error on Py2 when using print(..., end='')
from django.utils.six import print_
CURRENT_PYTHON = sys.version_info[:2]
REQUIRED_PYTHON = (3, 4)
if CURRENT_PYTHON < REQUIRED_PYTHON:
sys.stderr.write("This version of Wagtail requires Python {}.{} or above - you are running {}.{}\n".format(*(REQUIRED_PYTHON + CURRENT_PYTHON)))
sys.exit(1)
def pluralize(value, arg='s'):
return '' if value == 1 else arg
class Command:
description = None
def create_parser(self, command_name=None):
if command_name is None:
prog = None
else:
# hack the prog name as reported to ArgumentParser to include the command
prog = "%s %s" % (prog_name(), command_name)
parser = ArgumentParser(
description=getattr(self, 'description', None), add_help=False, prog=prog
)
self.add_arguments(parser)
return parser
def add_arguments(self, parser):
pass
def print_help(self, command_name):
parser = self.create_parser(command_name=command_name)
parser.print_help()
def execute(self, argv):
parser = self.create_parser()
options = parser.parse_args(sys.argv[2:])
options_dict = vars(options)
self.run(**options_dict)
class CreateProject(Command):
description = "Creates the directory structure for a new Wagtail project."
def add_arguments(self, parser):
parser.add_argument('project_name', help="Name for your Wagtail project")
parser.add_argument('dest_dir', nargs='?', help="Destination directory inside which to create the project")
def run(self, project_name=None, dest_dir=None):
# Make sure given name is not already in use by another python package/module.
try:
__import__(project_name)
except ImportError:
pass
else:
sys.exit("'%s' conflicts with the name of an existing "
"Python module and cannot be used as a project "
"name. Please try another name." % project_name)
print("Creating a Wagtail project called %(project_name)s" % {'project_name': project_name}) # noqa
# Create the project from the Wagtail template using startapp
# First find the path to Wagtail
import wagtail
wagtail_path = os.path.dirname(wagtail.__file__)
template_path = os.path.join(wagtail_path, 'project_template')
# Call django-admin startproject
utility_args = ['django-admin.py',
'startproject',
'--template=' + template_path,
'--ext=html,rst',
'--name=Dockerfile',
project_name]
if dest_dir:
utility_args.append(dest_dir)
utility = ManagementUtility(utility_args)
utility.execute()
print("Success! %(project_name)s has been created" % {'project_name': project_name}) # noqa
class UpdateModulePaths(Command):
description = "Update a Wagtail project tree to use Wagtail 2.x module paths"
REPLACEMENTS = [
(re.compile(r'\bwagtail\.wagtailcore\b'), 'wagtail.core'),
(re.compile(r'\bwagtail\.wagtailadmin\b'), 'wagtail.admin'),
(re.compile(r'\bwagtail\.wagtaildocs\b'), 'wagtail.documents'),
(re.compile(r'\bwagtail\.wagtailembeds\b'), 'wagtail.embeds'),
(re.compile(r'\bwagtail\.wagtailimages\b'), 'wagtail.images'),
(re.compile(r'\bwagtail\.wagtailsearch\b'), 'wagtail.search'),
(re.compile(r'\bwagtail\.wagtailsites\b'), 'wagtail.sites'),
(re.compile(r'\bwagtail\.wagtailsnippets\b'), 'wagtail.snippets'),
(re.compile(r'\bwagtail\.wagtailusers\b'), 'wagtail.users'),
(re.compile(r'\bwagtail\.wagtailforms\b'), 'wagtail.contrib.forms'),
(re.compile(r'\bwagtail\.wagtailredirects\b'), 'wagtail.contrib.redirects'),
(re.compile(r'\bwagtail\.contrib\.wagtailfrontendcache\b'), 'wagtail.contrib.frontend_cache'),
(re.compile(r'\bwagtail\.contrib\.wagtailroutablepage\b'), 'wagtail.contrib.routable_page'),
(re.compile(r'\bwagtail\.contrib\.wagtailsearchpromotions\b'), 'wagtail.contrib.search_promotions'),
(re.compile(r'\bwagtail\.contrib\.wagtailsitemaps\b'), 'wagtail.contrib.sitemaps'),
(re.compile(r'\bwagtail\.contrib\.wagtailstyleguide\b'), 'wagtail.contrib.styleguide'),
]
def add_arguments(self, parser):
parser.add_argument('root_path', nargs='?', help="Path to your project's root")
parser.add_argument('--list', action='store_true', dest='list_files', help="Show the list of files to change, without modifying them")
parser.add_argument('--diff', action='store_true', help="Show the changes that would be made, without modifying the files")
parser.add_argument(
'--ignore-dir', action='append', dest='ignored_dirs', metavar='NAME',
help="Ignore files in this directory"
)
parser.add_argument(
'--ignore-file', action='append', dest='ignored_patterns', metavar='NAME',
help="Ignore files with this name (supports wildcards)"
)
def run(self, root_path=None, list_files=False, diff=False, ignored_dirs=None, ignored_patterns=None):
if root_path is None:
root_path = os.getcwd()
absolute_ignored_dirs = [
os.path.abspath(dir_path) + os.sep
for dir_path in (ignored_dirs or [])
]
if ignored_patterns is None:
ignored_patterns = []
checked_file_count = 0
changed_file_count = 0
for (dirpath, dirnames, filenames) in os.walk(root_path):
dirpath_with_slash = os.path.abspath(dirpath) + os.sep
if any(dirpath_with_slash.startswith(ignored_dir) for ignored_dir in absolute_ignored_dirs):
continue
for filename in filenames:
if not filename.lower().endswith('.py'):
continue
if any(fnmatch.fnmatch(filename, pattern) for pattern in ignored_patterns):
continue
path = os.path.join(dirpath, filename)
relative_path = os.path.relpath(path, start=root_path)
checked_file_count += 1
if diff:
change_count = self._show_diff(path, relative_path=relative_path)
else:
if list_files:
change_count = self._count_changes(path)
else: # actually update
change_count = self._rewrite_file(path)
if change_count:
print("%s - %d change%s" % (relative_path, change_count, pluralize(change_count))) # NOQA
if change_count:
changed_file_count += 1
if diff or list_files:
print(
"\nChecked %d .py file%s, %d file%s to update." % (
checked_file_count, pluralize(checked_file_count),
changed_file_count, pluralize(changed_file_count)
)
) # NOQA
else:
print(
"\nChecked %d .py file%s, %d file%s updated." % (
checked_file_count, pluralize(checked_file_count),
changed_file_count, pluralize(changed_file_count)
)
) # NOQA
def _rewrite_line(self, line):
for pattern, repl in self.REPLACEMENTS:
line = re.sub(pattern, repl, line)
return line
def _show_diff(self, filename, relative_path=None):
change_count = 0
original = []
updated = []
with open(filename) as f:
for original_line in f:
original.append(original_line)
line = self._rewrite_line(original_line)
updated.append(line)
if line != original_line:
change_count += 1
if change_count:
relative_path = relative_path or filename
sys.stdout.writelines(unified_diff(
original, updated, fromfile="%s:before" % relative_path, tofile="%s:after" % relative_path
))
return change_count
def _count_changes(self, filename):
change_count = 0
with open(filename) as f:
for original_line in f:
line = self._rewrite_line(original_line)
if line != original_line:
change_count += 1
return change_count
def _rewrite_file(self, filename):
change_count = 0
with fileinput.FileInput(filename, inplace=True) as f:
for original_line in f:
line = self._rewrite_line(original_line)
print_(line, end='') # NOQA
if line != original_line:
change_count += 1
return change_count
COMMANDS = {
'start': CreateProject(),
'updatemodulepaths': UpdateModulePaths(),
}
def prog_name():
return os.path.basename(sys.argv[0])
def help_index():
print("Type '%s help <subcommand>' for help on a specific subcommand.\n" % prog_name()) # NOQA
print("Available subcommands:\n") # NOQA
for name, cmd in sorted(COMMANDS.items()):
print(" %s%s" % (name.ljust(20), cmd.description)) # NOQA
def unknown_command(command):
print("Unknown command: '%s'" % command) # NOQA
print("Type '%s help' for usage." % prog_name()) # NOQA
sys.exit(1)
def main():
try:
command_name = sys.argv[1]
except IndexError:
help_index()
return
if command_name == 'help':
try:
help_command_name = sys.argv[2]
except IndexError:
help_index()
return
try:
command = COMMANDS[help_command_name]
except KeyError:
unknown_command(help_command_name)
return
command.print_help(help_command_name)
return
try:
command = COMMANDS[command_name]
except KeyError:
unknown_command(command_name)
return
command.execute(sys.argv)
if __name__ == "__main__":
main()