INIT
This commit is contained in:
1
src/django_deploy/__init__.py
Normal file
1
src/django_deploy/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .main import main
|
||||
1
src/django_deploy/config.py
Normal file
1
src/django_deploy/config.py
Normal file
@@ -0,0 +1 @@
|
||||
DJANGO_SETTINGS_MODULE_NAME = 'main'
|
||||
1
src/django_deploy/django_settings.py
Normal file
1
src/django_deploy/django_settings.py
Normal file
@@ -0,0 +1 @@
|
||||
# ADD_INSTALLED_APPS = ['django_deploy']
|
||||
9
src/django_deploy/main.py
Normal file
9
src/django_deploy/main.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import sys
|
||||
|
||||
from .program import Program
|
||||
|
||||
|
||||
def main(*args, **kwargs):
|
||||
program = Program()
|
||||
exitval = program(*args, **kwargs)
|
||||
sys.exit(exitval)
|
||||
114
src/django_deploy/program.py
Normal file
114
src/django_deploy/program.py
Normal file
@@ -0,0 +1,114 @@
|
||||
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
|
||||
0
src/django_deploy/tests/__init__.py
Normal file
0
src/django_deploy/tests/__init__.py
Normal file
1
src/django_deploy/tests/django_settings.py
Normal file
1
src/django_deploy/tests/django_settings.py
Normal file
@@ -0,0 +1 @@
|
||||
ADD_INSTALLED_APPS = ['fake_app1', 'fake_app2']
|
||||
37
src/django_deploy/tests/test_main.py
Normal file
37
src/django_deploy/tests/test_main.py
Normal file
@@ -0,0 +1,37 @@
|
||||
import os
|
||||
import unittest
|
||||
import pytest
|
||||
|
||||
from .. import main
|
||||
|
||||
|
||||
class MainTestCase(unittest.TestCase):
|
||||
@pytest.fixture(autouse=True)
|
||||
def capsys(self, capsys): # pylint: disable=method-hidden
|
||||
self.capsys = capsys
|
||||
|
||||
def test_main_without_arguments(self):
|
||||
exitval = os.EX_SOFTWARE
|
||||
try:
|
||||
main()
|
||||
except SystemExit as e:
|
||||
exitval = e.code
|
||||
finally:
|
||||
captured = self.capsys.readouterr()
|
||||
|
||||
is_usage = captured.err.startswith('usage:')
|
||||
self.assertTrue(is_usage, 'main() does not produce usage text')
|
||||
self.assertNotEqual(os.EX_OK, exitval)
|
||||
|
||||
def test_main_help(self):
|
||||
exitval = os.EX_SOFTWARE
|
||||
try:
|
||||
main(argv=['-h'])
|
||||
except SystemExit as e:
|
||||
exitval = e.code
|
||||
finally:
|
||||
captured = self.capsys.readouterr()
|
||||
|
||||
is_usage = captured.out.startswith('usage:')
|
||||
self.assertTrue(is_usage, 'main() does not produce usage text')
|
||||
self.assertEqual(os.EX_OK, exitval)
|
||||
69
src/django_deploy/tests/test_program.py
Normal file
69
src/django_deploy/tests/test_program.py
Normal file
@@ -0,0 +1,69 @@
|
||||
import importlib
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import pytest
|
||||
|
||||
from ..config import DJANGO_SETTINGS_MODULE_NAME
|
||||
from ..program import Program
|
||||
|
||||
|
||||
class MainTestCase(unittest.TestCase):
|
||||
@pytest.fixture(autouse=True)
|
||||
def tmpdir(self, tmpdir): # pylint: disable=method-hidden
|
||||
self.tmpdir = tmpdir
|
||||
|
||||
def setUp(self):
|
||||
self._program = Program()
|
||||
|
||||
def test_create(self):
|
||||
tmpdir = self.tmpdir
|
||||
project_dir = os.path.join(str(tmpdir), 'env', 'django')
|
||||
|
||||
exitval = self._program(argv=['-c', project_dir])
|
||||
|
||||
self.assertEqual(os.EX_OK, exitval, 'program() does not return os.EX_OK')
|
||||
self.assertTrue(os.path.isdir(project_dir), 'project directory was not created')
|
||||
settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_MODULE_NAME)
|
||||
self.assertTrue(os.path.isdir(settings_dir), 'settings directory was not created')
|
||||
settings_file = os.path.join(settings_dir, 'settings.py')
|
||||
self.assertTrue(os.path.isfile(settings_file), 'settings.py was not created')
|
||||
manage_script = os.path.join(project_dir, 'manage.py')
|
||||
self.assertTrue(os.path.isfile(manage_script), 'manage.py was not created')
|
||||
|
||||
def test_create_dont_overwrite(self):
|
||||
tmpdir = self.tmpdir
|
||||
project_dir = os.path.join(str(tmpdir), 'env', 'django')
|
||||
|
||||
self._program(argv=['--create', project_dir])
|
||||
exitval = self._program(argv=['--create', project_dir])
|
||||
|
||||
self.assertEqual(os.EX_NOPERM, exitval, 'second call to program() does not exit with os.EX_NOPERM')
|
||||
|
||||
def test_merge_installed_apps(self):
|
||||
tmpdir = self.tmpdir
|
||||
project_dir = os.path.join(str(tmpdir), 'env', 'django')
|
||||
|
||||
expected_installed_apps = [
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'fake_app1',
|
||||
'fake_app2',
|
||||
]
|
||||
|
||||
argv = ['-c', project_dir]
|
||||
self._program(argv=argv)
|
||||
|
||||
argv = ['-a', 'django_deploy', '-a', 'django_deploy.tests', project_dir]
|
||||
self._program(argv=argv)
|
||||
|
||||
settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_MODULE_NAME)
|
||||
sys.path.insert(0, settings_dir)
|
||||
settings = importlib.import_module('settings')
|
||||
importlib.reload(settings)
|
||||
sys.path.pop(0)
|
||||
self.assertListEqual(expected_installed_apps, settings.INSTALLED_APPS)
|
||||
1
src/django_deploy/version.py
Normal file
1
src/django_deploy/version.py
Normal file
@@ -0,0 +1 @@
|
||||
VERSION = '0.1.dev0'
|
||||
Reference in New Issue
Block a user