Begin to implement #1
Some checks failed
buildbot/tox Build done.

This commit is contained in:
2019-10-31 16:57:40 +01:00
parent 54a708f8dd
commit b4273d9fd7
11 changed files with 161 additions and 18 deletions

View File

@@ -1 +1 @@
DJANGO_SETTINGS_MODULE_NAME = 'main'
DJANGO_SETTINGS_DIR = 'main'

View File

@@ -1 +1,4 @@
# ADD_INSTALLED_APPS = ['django_deploy']
# ADD_URLPATTERNS = [
# {'type': 'include', 'pattern': '', 'module': 'django_deploy.urls'},
# ]

View File

@@ -4,7 +4,7 @@ import importlib
import os
import sys
from .config import DJANGO_SETTINGS_MODULE_NAME
from .config import DJANGO_SETTINGS_DIR
from .version import VERSION
@@ -38,7 +38,7 @@ class Program(object): # pylint: disable=too-few-public-methods
@staticmethod
def _append_to_settings(project_dir, code, comment):
settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_MODULE_NAME)
settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_DIR)
settings_file = os.path.join(settings_dir, 'settings.py')
settings_file_py2cache = settings_file + 'c'
@@ -57,7 +57,7 @@ class Program(object): # pylint: disable=too-few-public-methods
else:
os.makedirs(project_dir)
settings_module = DJANGO_SETTINGS_MODULE_NAME
settings_module = DJANGO_SETTINGS_DIR
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))
@@ -65,7 +65,7 @@ class Program(object): # pylint: disable=too-few-public-methods
return exitval
def _add_installed_apps_from_app(self, project_dir, app):
settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_MODULE_NAME)
settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_DIR)
settings_from_app = importlib.import_module('{}.django_settings'.format(app))
if hasattr(settings_from_app, 'ADD_INSTALLED_APPS'):
@@ -102,6 +102,29 @@ class Program(object): # pylint: disable=too-few-public-methods
return os.EX_OK
def _add_urlpatterns_from_app(self, project_dir, app):
settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_DIR)
settings_from_app = importlib.import_module('{}.django_settings'.format(app))
if hasattr(settings_from_app, 'ADD_URLPATTERNS'):
add_urls = settings_from_app.ADD_URLPATTERNS
else:
add_urls = []
if not add_urls:
sys.stdout.write('{}: do not care about ROOT_URLCONF\n'.format(app))
return os.EX_OK
raise NotImplementedError()
self._append_to_settings(project_dir, code, comment)
def _merge_app(self, project_dir, app):
exitval = self._add_installed_apps_from_app(project_dir, app)
if exitval != os.EX_OK:
return exitval
exitval = self._add_urlpatterns_from_app(project_dir, app)
return exitval
def __init__(self):
self._argparser = argparse.ArgumentParser()
self._setup_argparser(self._argparser)
@@ -116,7 +139,7 @@ class Program(object): # pylint: disable=too-few-public-methods
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)
exitval = self._merge_app(cmd_args.project_dir, app)
if exitval != os.EX_OK:
return exitval
return exitval

View File

@@ -1 +0,0 @@
ADD_INSTALLED_APPS = ['fake_app1', 'fake_app2']

View File

@@ -0,0 +1,4 @@
ADD_INSTALLED_APPS = ['django_deploy.tests.fake_app']
ADD_URLPATTERNS = [
{'type': 'include', 'pattern': 'fake/', 'module': 'django_deploy.tests.fake_app.urls'},
]

View File

@@ -0,0 +1,2 @@
app_name = 'fake1'
urlpatterns = []

View File

@@ -4,7 +4,9 @@ import sys
import unittest
import pytest
from ..config import DJANGO_SETTINGS_MODULE_NAME
from unittest import mock
from ..config import DJANGO_SETTINGS_DIR
from ..program import Program
@@ -24,7 +26,7 @@ class MainTestCase(unittest.TestCase):
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)
settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_DIR)
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')
@@ -44,6 +46,12 @@ class MainTestCase(unittest.TestCase):
tmpdir = self.tmpdir
project_dir = os.path.join(str(tmpdir), 'env', 'django')
argv = ['-c', project_dir]
self._program(argv=argv)
argv = ['-a', 'django_deploy', '-a', 'django_deploy.tests.fake_app', project_dir]
self._program(argv=argv)
expected_installed_apps = [
'django.contrib.admin',
'django.contrib.auth',
@@ -51,17 +59,10 @@ class MainTestCase(unittest.TestCase):
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'fake_app1',
'fake_app2',
'django_deploy.tests.fake_app',
]
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)
settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_DIR)
sys.path.insert(0, settings_dir)
settings = importlib.import_module('settings')
if sys.version_info.major == 2: # pragma: no cover
@@ -69,4 +70,54 @@ class MainTestCase(unittest.TestCase):
else: # pragma: no cover
importlib.reload(settings) # pylint: disable=no-member
sys.path.pop(0)
self.assertListEqual(expected_installed_apps, settings.INSTALLED_APPS)
def test_merge_root_urlconf(self):
tmpdir = self.tmpdir
project_dir = os.path.join(str(tmpdir), 'env', 'django')
argv = ['-c', project_dir]
self._program(argv=argv)
argv = ['-a', 'django_deploy', '-a', 'django_deploy.tests.fake_app', project_dir]
self._program(argv=argv)
if 'django.contrib.admin' in sys.modules:
original_admin = sys.modules['django.contrib.admin']
else:
original_admin = None
mock_admin = mock.Mock()
sys.modules['django.contrib.admin'] = mock_admin
from django.urls import path
expected_urlpatterns = [
('URLPattern', 'admin/', mock_admin.site.urls),
('URLResolver', 'fake/'),
]
settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_DIR)
sys.path.insert(0, settings_dir)
root_urlconf = importlib.import_module('urls')
if sys.version_info.major == 2: # pragma: no cover
reload(root_urlconf) # pylint: disable=undefined-variable
else: # pragma: no cover
importlib.reload(root_urlconf) # pylint: disable=no-member
sys.path.pop(0)
if original_admin:
sys.modules['django.contrib.admin'] = original_admin
real_urlpatterns = root_urlconf.urlpatterns
self.assertEqual(len(expected_urlpatterns), len(real_urlpatterns))
for i in range(0, len(expected_urlpatterns)):
expected = expected_urlpatterns[i]
real = real_urlpatterns[i]
self.assertEqual(expected[0], real.__class__.__name__)
if expected[0] == 'URLPattern':
self.assertIsNotNone(real.pattern.match(expected[1]))
self.assertEqual(expected[2], real.callback)
else:
raise Exception(dir(real))

View File

@@ -0,0 +1,4 @@
SECRET_KEY = 'test_settings'
INSTALLED_APPS = [
'django_deploy.tests.fake_app',
]

View File

@@ -0,0 +1,16 @@
import unittest
from ..utils import DjangoEnvironment
class DjangoEnvironmentTestCase(unittest.TestCase):
def test_django_environment(self):
settings_module_name = 'django_deploy.tests.test_settings'
with DjangoEnvironment(settings_module_name=settings_module_name) as env:
check_attrs = [
('SECRET_KEY', 'test_settings'),
('INSTALLED_APPS', ['django_deploy.tests.fake_app']),
]
for key, value in check_attrs:
self.assertEqual(value, getattr(env.settings, key))

View File

@@ -0,0 +1,41 @@
import importlib
import os
import sys
import django
from .config import DJANGO_SETTINGS_DIR
class DjangoEnvironment(object):
def __init__(self, project_dir=None, settings_module_name=None):
self.project_dir = project_dir
if settings_module_name is not None:
self.settings_module_name = settings_module_name
else:
self.settings_module_name = '{}.settings'.format(DJANGO_SETTINGS_DIR)
self._original_sys_path = None
self._modified_sys_path = None
def __enter__(self):
if self.project_dir:
self._original_sys_path = sys.path
sys.path.insert(0, self.project_dir)
self._modified_sys_path = sys.path
print('Debug: %s' % self.settings_module_name)
os.environ['DJANGO_SETTINGS_MODULE'] = self.settings_module_name
django.setup()
from django.conf import settings
self.settings = settings
if hasattr(settings, 'ROOT_URLCONF'):
self.root_urlconf = importlib.import_module(settings.ROOT_URLCONF)
return self
def __exit__(self, *args):
if self._modified_sys_path is not None and self._original_sys_path is not None:
if sys.path == self._modified_sys_path:
sys.path = self._original_sys_path