From 18613d3600f3f359e3f07d13ffdb91c7b2450ec2 Mon Sep 17 00:00:00 2001 From: Jens Kleineheismann Date: Fri, 15 Nov 2019 17:07:10 +0100 Subject: [PATCH] Make thinks more useful Extract functionality from program.Program to api, so it can be used from other python code. And instead of adding predefined urls to root_urlconf, we should /mount/ apps into a django project. --- src/django_deploy/api.py | 37 +++++++++++++++++++++++++ src/django_deploy/exceptions.py | 23 ++++++++++++--- src/django_deploy/program.py | 29 +++++++++---------- src/django_deploy/tests/test_api.py | 27 ++++++++++++++++++ src/django_deploy/tests/test_program.py | 4 +-- 5 files changed, 98 insertions(+), 22 deletions(-) create mode 100644 src/django_deploy/api.py create mode 100644 src/django_deploy/tests/test_api.py diff --git a/src/django_deploy/api.py b/src/django_deploy/api.py new file mode 100644 index 0000000..4723548 --- /dev/null +++ b/src/django_deploy/api.py @@ -0,0 +1,37 @@ +import errno +import os +import sys + +from .config import DJANGO_SETTINGS_DIR +from .exceptions import DjangoDeployError, FatalError + + +class DjangoProject(object): + def __init__(self, project_dir): + self._project_dir = project_dir + + def create(self): + project_dir = self._project_dir + + if not os.path.exists(project_dir): + os.makedirs(project_dir) + + settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_DIR) + if os.path.exists(settings_dir): + raise DjangoDeployError('directory already exists: {}'.format(settings_dir), code=errno.EEXIST) + + cmd = 'django-admin startproject {name} {path}'.format(name=DJANGO_SETTINGS_DIR, + path=project_dir) + sys.stdout.write('Installing django files to {path}\n'.format(path=project_dir)) + exitval = os.system(cmd) + if exitval != os.EX_OK: # pragma: no cover + raise FatalError(exitval=exitval) + + def install_hooks(self): + pass + + def add_app(self, module): + pass + + def mount_app(self, module, route): + pass diff --git a/src/django_deploy/exceptions.py b/src/django_deploy/exceptions.py index 229a4c1..7304191 100644 --- a/src/django_deploy/exceptions.py +++ b/src/django_deploy/exceptions.py @@ -1,7 +1,22 @@ -class FatalError(Exception): - def __init__(self, *args, **kwargs): - self._exitval = kwargs.pop('exitval', None) - super(FatalError, self).__init__(*args, **kwargs) +class DjangoDeployError(Exception): + def __init__(self, message=None, code=None): + self._message = message + self._code = code + super(DjangoDeployError, self).__init__(message) + + @property + def message(self): + return self._message + + @property + def code(self): + return self._code + + +class FatalError(DjangoDeployError): + def __init__(self, message=None, code=None, exitval=None): + self._exitval = exitval + super(FatalError, self).__init__(message=message, code=code) @property def exitval(self): diff --git a/src/django_deploy/program.py b/src/django_deploy/program.py index 55043e8..b7dc5ea 100644 --- a/src/django_deploy/program.py +++ b/src/django_deploy/program.py @@ -3,8 +3,9 @@ import importlib import os import sys +from .api import DjangoProject from .config import DJANGO_SETTINGS_DIR, DeployedAppsConfig -from .exceptions import FatalError +from .exceptions import DjangoDeployError, FatalError from .version import VERSION @@ -63,21 +64,9 @@ class Program(object): # pylint: disable=too-few-public-methods return self._append_to_pythonfile(settings_file, text) @staticmethod - def _install_django_files(project_dir, overwrite=False): - if not os.path.exists(project_dir): - os.makedirs(project_dir) - - settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_DIR) - if os.path.exists(settings_dir) and not overwrite: - sys.stderr.write('directory already exists: {}\n'.format(settings_dir)) - raise FatalError(exitval=os.EX_NOPERM) - - cmd = 'django-admin startproject {name} {path}'.format(name=DJANGO_SETTINGS_DIR, - path=project_dir) - sys.stdout.write('Installing django files to {path}\n'.format(path=project_dir)) - exitval = os.system(cmd) - if exitval != os.EX_OK: # pragma: no cover - raise FatalError(exitval=exitval) + def _install_django_files(project_dir): + project = DjangoProject(project_dir) + project.create() @staticmethod def _install_django_deploy_files(project_dir, overwrite=False): @@ -147,5 +136,13 @@ class Program(object): # pylint: disable=too-few-public-methods for app in cmd_args.merge_apps: self._merge_app(cmd_args.project_dir, app) except FatalError as e: + if e.message: + sys.stderr.write('{}\n'.format(e.message)) exitval = e.exitval + except DjangoDeployError as e: + if e.message: + sys.stderr.write('{}\n'.format(e.message)) + elif e.code: + sys.stderr.write('{}\n'.format(os.strerror(e.code))) + exitval = os.EX_SOFTWARE return exitval diff --git a/src/django_deploy/tests/test_api.py b/src/django_deploy/tests/test_api.py new file mode 100644 index 0000000..08f19cc --- /dev/null +++ b/src/django_deploy/tests/test_api.py @@ -0,0 +1,27 @@ +import os +import unittest +import pytest + +from ..api import DjangoProject +from ..config import DJANGO_SETTINGS_DIR + + +class DjangoProjectTestCase(unittest.TestCase): + @pytest.fixture(autouse=True) + def tmpdir(self, tmpdir): # pylint: disable=method-hidden + self.tmpdir = tmpdir + + def _assert_django_project(self, project_dir): + self.assertTrue(os.path.isdir(project_dir), 'no directory: {}'.format(project_dir)) + settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_DIR) + self.assertTrue(os.path.isdir(settings_dir), 'no directory: {}'.format(settings_dir)) + settings_file = os.path.join(settings_dir, 'settings.py') + self.assertTrue(os.path.isfile(settings_file), 'no file: {}'.format(settings_file)) + manage_script = os.path.join(project_dir, 'manage.py') + self.assertTrue(os.path.isfile(manage_script), 'no file: {}'.format(manage_script)) + + def test_create(self): + project_dir = os.path.join(str(self.tmpdir), 'django') + project = DjangoProject(project_dir) + project.create() + self._assert_django_project(project_dir) diff --git a/src/django_deploy/tests/test_program.py b/src/django_deploy/tests/test_program.py index ae71d0f..f6a6e68 100644 --- a/src/django_deploy/tests/test_program.py +++ b/src/django_deploy/tests/test_program.py @@ -65,8 +65,8 @@ class ProgramTestCase(unittest.TestCase): def test_create_existing_project_dir(self): exitval = self._program(argv=['-c', self._project_dir]) - self.assertEqual(os.EX_NOPERM, exitval, 'program() does not return os.EX_NOPERM' - ' when project directory is not empty') + self.assertEqual(os.EX_SOFTWARE, exitval, 'program() does not return os.EX_SOFTWARE' + ' when project directory is not empty') def test_enable_django_deploy(self): project_dir = os.path.join(str(self.tmpdir), 'pure_django')