This commit is contained in:
@@ -1 +1 @@
|
|||||||
DJANGO_SETTINGS_MODULE_NAME = 'main'
|
DJANGO_SETTINGS_DIR = 'main'
|
||||||
|
|||||||
@@ -1 +1,4 @@
|
|||||||
# ADD_INSTALLED_APPS = ['django_deploy']
|
# ADD_INSTALLED_APPS = ['django_deploy']
|
||||||
|
# ADD_URLPATTERNS = [
|
||||||
|
# {'type': 'include', 'pattern': '', 'module': 'django_deploy.urls'},
|
||||||
|
# ]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import importlib
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from .config import DJANGO_SETTINGS_MODULE_NAME
|
from .config import DJANGO_SETTINGS_DIR
|
||||||
from .version import VERSION
|
from .version import VERSION
|
||||||
|
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ class Program(object): # pylint: disable=too-few-public-methods
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _append_to_settings(project_dir, code, comment):
|
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 = os.path.join(settings_dir, 'settings.py')
|
||||||
settings_file_py2cache = settings_file + 'c'
|
settings_file_py2cache = settings_file + 'c'
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ class Program(object): # pylint: disable=too-few-public-methods
|
|||||||
else:
|
else:
|
||||||
os.makedirs(project_dir)
|
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,
|
cmd = 'django-admin startproject {name} {path}'.format(name=settings_module,
|
||||||
path=project_dir)
|
path=project_dir)
|
||||||
sys.stdout.write('Installing django files to {path}\n'.format(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
|
return exitval
|
||||||
|
|
||||||
def _add_installed_apps_from_app(self, project_dir, app):
|
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))
|
settings_from_app = importlib.import_module('{}.django_settings'.format(app))
|
||||||
if hasattr(settings_from_app, 'ADD_INSTALLED_APPS'):
|
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
|
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):
|
def __init__(self):
|
||||||
self._argparser = argparse.ArgumentParser()
|
self._argparser = argparse.ArgumentParser()
|
||||||
self._setup_argparser(self._argparser)
|
self._setup_argparser(self._argparser)
|
||||||
@@ -116,7 +139,7 @@ class Program(object): # pylint: disable=too-few-public-methods
|
|||||||
return exitval
|
return exitval
|
||||||
if cmd_args.merge_apps:
|
if cmd_args.merge_apps:
|
||||||
for app in 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:
|
if exitval != os.EX_OK:
|
||||||
return exitval
|
return exitval
|
||||||
return exitval
|
return exitval
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
ADD_INSTALLED_APPS = ['fake_app1', 'fake_app2']
|
|
||||||
0
src/django_deploy/tests/fake_app/__init__.py
Normal file
0
src/django_deploy/tests/fake_app/__init__.py
Normal file
4
src/django_deploy/tests/fake_app/django_settings.py
Normal file
4
src/django_deploy/tests/fake_app/django_settings.py
Normal 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'},
|
||||||
|
]
|
||||||
2
src/django_deploy/tests/fake_app/urls.py
Normal file
2
src/django_deploy/tests/fake_app/urls.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
app_name = 'fake1'
|
||||||
|
urlpatterns = []
|
||||||
@@ -4,7 +4,9 @@ import sys
|
|||||||
import unittest
|
import unittest
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ..config import DJANGO_SETTINGS_MODULE_NAME
|
from unittest import mock
|
||||||
|
|
||||||
|
from ..config import DJANGO_SETTINGS_DIR
|
||||||
from ..program import Program
|
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.assertEqual(os.EX_OK, exitval, 'program() does not return os.EX_OK')
|
||||||
self.assertTrue(os.path.isdir(project_dir), 'project directory was not created')
|
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')
|
self.assertTrue(os.path.isdir(settings_dir), 'settings directory was not created')
|
||||||
settings_file = os.path.join(settings_dir, 'settings.py')
|
settings_file = os.path.join(settings_dir, 'settings.py')
|
||||||
self.assertTrue(os.path.isfile(settings_file), 'settings.py was not created')
|
self.assertTrue(os.path.isfile(settings_file), 'settings.py was not created')
|
||||||
@@ -44,6 +46,12 @@ class MainTestCase(unittest.TestCase):
|
|||||||
tmpdir = self.tmpdir
|
tmpdir = self.tmpdir
|
||||||
project_dir = os.path.join(str(tmpdir), 'env', 'django')
|
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 = [
|
expected_installed_apps = [
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
@@ -51,17 +59,10 @@ class MainTestCase(unittest.TestCase):
|
|||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'fake_app1',
|
'django_deploy.tests.fake_app',
|
||||||
'fake_app2',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
argv = ['-c', project_dir]
|
settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_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)
|
sys.path.insert(0, settings_dir)
|
||||||
settings = importlib.import_module('settings')
|
settings = importlib.import_module('settings')
|
||||||
if sys.version_info.major == 2: # pragma: no cover
|
if sys.version_info.major == 2: # pragma: no cover
|
||||||
@@ -69,4 +70,54 @@ class MainTestCase(unittest.TestCase):
|
|||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
importlib.reload(settings) # pylint: disable=no-member
|
importlib.reload(settings) # pylint: disable=no-member
|
||||||
sys.path.pop(0)
|
sys.path.pop(0)
|
||||||
|
|
||||||
self.assertListEqual(expected_installed_apps, settings.INSTALLED_APPS)
|
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))
|
||||||
|
|||||||
4
src/django_deploy/tests/test_settings.py
Normal file
4
src/django_deploy/tests/test_settings.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
SECRET_KEY = 'test_settings'
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django_deploy.tests.fake_app',
|
||||||
|
]
|
||||||
16
src/django_deploy/tests/test_utils.py
Normal file
16
src/django_deploy/tests/test_utils.py
Normal 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))
|
||||||
41
src/django_deploy/utils.py
Normal file
41
src/django_deploy/utils.py
Normal 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
|
||||||
Reference in New Issue
Block a user