import argparse import datetime import importlib import os import sys from .config import DJANGO_SETTINGS_MODULE_NAME from .version import VERSION class Program(object): # pylint: disable=too-few-public-methods @staticmethod def _setup_argparser(parser): parser.add_argument('-V', '--version', action='version', version='%(prog)s ' + VERSION) parser.add_argument('-a', '--app', action='append', dest='merge_apps', metavar='MODULE', help='Merge settings from the django app MODULE\n' 'Can be used multiple times') parser.add_argument('-c', '--create', action='store_true', dest='create', help='Create the django project directory') parser.add_argument('project_dir', metavar='PATH', help='The directory, where the django project is or will be installed.') return parser def _parse_args(self, argv=None): if argv is None: argv = sys.argv[1:] if not argv: argv = () return self._argparser.parse_args(argv) @staticmethod def _install_django_files(project_dir, overwrite=False): if os.path.exists(project_dir): if not overwrite: sys.stderr.write('directory already exists: {}\n'.format(project_dir)) return os.EX_NOPERM else: os.makedirs(project_dir) settings_module = DJANGO_SETTINGS_MODULE_NAME cmd = 'django-admin startproject {name} {path}'.format(name=settings_module, path=project_dir) sys.stdout.write('Installing django files to {path}\n'.format(path=project_dir)) exitval = os.system(cmd) return exitval @staticmethod def _add_installed_apps_from_app(project_dir, app): settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_MODULE_NAME) settings_from_app = importlib.import_module('{}.django_settings'.format(app)) if hasattr(settings_from_app, 'ADD_INSTALLED_APPS'): add_apps = settings_from_app.ADD_INSTALLED_APPS else: add_apps = [] if not add_apps: sys.stdout.write('{}: do not care about INSTALLED_APPS\n'.format(app)) return os.EX_OK sys.path.insert(0, settings_dir) settings = importlib.import_module('settings') sys.path.pop(0) missing_apps = [] for app in add_apps: if app not in settings.INSTALLED_APPS: missing_apps.append(app) if missing_apps: sys.stdout.write('{app}: adding {apps} to INSTALLED_APPS\n'.format(app=app, apps=missing_apps)) comment = '### {app}: added apps with django-deploy at {timestamp}' code = 'INSTALLED_APPS += [\n' for app in missing_apps: code += ' \'{}\',\n'.format(app) code += ']\n' append_text = '\n' + comment + '\n' + code + '\n' settings_file = os.path.join(settings_dir, 'settings.py') with open(settings_file, 'a') as f: now = datetime.datetime.now() timestamp = now.strftime('%Y-%m-%d %H:%M:%S') f.write(append_text.format(app=app, timestamp=timestamp)) else: sys.stdout.write('{app}: INSTALLED_APPS is fine\n'.format(app=app)) return os.EX_OK def __init__(self): self._argparser = argparse.ArgumentParser() self._setup_argparser(self._argparser) def __call__(self, *args, **kwargs): argv = kwargs.get('argv', None) cmd_args = self._parse_args(argv) exitval = os.EX_OK if cmd_args.create: exitval = self._install_django_files(cmd_args.project_dir) if exitval != os.EX_OK: return exitval if cmd_args.merge_apps: for app in cmd_args.merge_apps: exitval = self._add_installed_apps_from_app(cmd_args.project_dir, app) if exitval != os.EX_OK: return exitval return exitval