From b4273d9fd7bdb1efc215ba2b85d2236b083fe24f Mon Sep 17 00:00:00 2001 From: Jens Kleineheismann Date: Thu, 31 Oct 2019 16:57:40 +0100 Subject: [PATCH 1/3] Begin to implement #1 --- src/django_deploy/config.py | 2 +- src/django_deploy/django_settings.py | 3 + src/django_deploy/program.py | 33 +++++++-- src/django_deploy/tests/django_settings.py | 1 - src/django_deploy/tests/fake_app/__init__.py | 0 .../tests/fake_app/django_settings.py | 4 + src/django_deploy/tests/fake_app/urls.py | 2 + src/django_deploy/tests/test_program.py | 73 ++++++++++++++++--- src/django_deploy/tests/test_settings.py | 4 + src/django_deploy/tests/test_utils.py | 16 ++++ src/django_deploy/utils.py | 41 +++++++++++ 11 files changed, 161 insertions(+), 18 deletions(-) delete mode 100644 src/django_deploy/tests/django_settings.py create mode 100644 src/django_deploy/tests/fake_app/__init__.py create mode 100644 src/django_deploy/tests/fake_app/django_settings.py create mode 100644 src/django_deploy/tests/fake_app/urls.py create mode 100644 src/django_deploy/tests/test_settings.py create mode 100644 src/django_deploy/tests/test_utils.py create mode 100644 src/django_deploy/utils.py diff --git a/src/django_deploy/config.py b/src/django_deploy/config.py index 55970af..decb621 100644 --- a/src/django_deploy/config.py +++ b/src/django_deploy/config.py @@ -1 +1 @@ -DJANGO_SETTINGS_MODULE_NAME = 'main' +DJANGO_SETTINGS_DIR = 'main' diff --git a/src/django_deploy/django_settings.py b/src/django_deploy/django_settings.py index 81fcbb1..3b21247 100644 --- a/src/django_deploy/django_settings.py +++ b/src/django_deploy/django_settings.py @@ -1 +1,4 @@ # ADD_INSTALLED_APPS = ['django_deploy'] +# ADD_URLPATTERNS = [ +# {'type': 'include', 'pattern': '', 'module': 'django_deploy.urls'}, +# ] diff --git a/src/django_deploy/program.py b/src/django_deploy/program.py index efb5d9f..e1d3a92 100644 --- a/src/django_deploy/program.py +++ b/src/django_deploy/program.py @@ -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 diff --git a/src/django_deploy/tests/django_settings.py b/src/django_deploy/tests/django_settings.py deleted file mode 100644 index d4f2f21..0000000 --- a/src/django_deploy/tests/django_settings.py +++ /dev/null @@ -1 +0,0 @@ -ADD_INSTALLED_APPS = ['fake_app1', 'fake_app2'] diff --git a/src/django_deploy/tests/fake_app/__init__.py b/src/django_deploy/tests/fake_app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/django_deploy/tests/fake_app/django_settings.py b/src/django_deploy/tests/fake_app/django_settings.py new file mode 100644 index 0000000..b46f77e --- /dev/null +++ b/src/django_deploy/tests/fake_app/django_settings.py @@ -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'}, +] diff --git a/src/django_deploy/tests/fake_app/urls.py b/src/django_deploy/tests/fake_app/urls.py new file mode 100644 index 0000000..85d5294 --- /dev/null +++ b/src/django_deploy/tests/fake_app/urls.py @@ -0,0 +1,2 @@ +app_name = 'fake1' +urlpatterns = [] \ No newline at end of file diff --git a/src/django_deploy/tests/test_program.py b/src/django_deploy/tests/test_program.py index ff5196e..1ee4d9d 100644 --- a/src/django_deploy/tests/test_program.py +++ b/src/django_deploy/tests/test_program.py @@ -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)) diff --git a/src/django_deploy/tests/test_settings.py b/src/django_deploy/tests/test_settings.py new file mode 100644 index 0000000..49dbf12 --- /dev/null +++ b/src/django_deploy/tests/test_settings.py @@ -0,0 +1,4 @@ +SECRET_KEY = 'test_settings' +INSTALLED_APPS = [ + 'django_deploy.tests.fake_app', +] diff --git a/src/django_deploy/tests/test_utils.py b/src/django_deploy/tests/test_utils.py new file mode 100644 index 0000000..5229888 --- /dev/null +++ b/src/django_deploy/tests/test_utils.py @@ -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)) diff --git a/src/django_deploy/utils.py b/src/django_deploy/utils.py new file mode 100644 index 0000000..b8f6a42 --- /dev/null +++ b/src/django_deploy/utils.py @@ -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 -- 2.52.0 From 8e862334310308f1ee3a6526ad0398de9e8ced1e Mon Sep 17 00:00:00 2001 From: Jens Kleineheismann Date: Thu, 7 Nov 2019 17:01:53 +0100 Subject: [PATCH 2/3] it works. but coverage is too low. --- .pylintrc | 2 +- setup.py | 1 + src/django_deploy/program.py | 130 +++++++++++++----- .../tests/fake_app/django_settings.py | 2 +- src/django_deploy/tests/fake_app/urls.py | 3 +- src/django_deploy/tests/test_program.py | 60 ++++---- src/django_deploy/tests/test_utils.py | 16 --- src/django_deploy/utils.py | 50 +++---- tox.ini | 5 +- 9 files changed, 151 insertions(+), 118 deletions(-) delete mode 100644 src/django_deploy/tests/test_utils.py diff --git a/.pylintrc b/.pylintrc index 210b081..b70bbbb 100644 --- a/.pylintrc +++ b/.pylintrc @@ -1,7 +1,7 @@ [MASTER] persistent=no -#load-plugins=pylint_django +load-plugins=pylint_django [MESSAGES CONTROL] diff --git a/setup.py b/setup.py index dadfe32..d7c4b44 100644 --- a/setup.py +++ b/setup.py @@ -79,5 +79,6 @@ setup( }, install_requires=[ 'django', + 'mock', ], ) diff --git a/src/django_deploy/program.py b/src/django_deploy/program.py index e1d3a92..996788b 100644 --- a/src/django_deploy/program.py +++ b/src/django_deploy/program.py @@ -5,6 +5,7 @@ import os import sys from .config import DJANGO_SETTINGS_DIR +from .utils import get_root_urlconf from .version import VERSION @@ -36,18 +37,6 @@ class Program(object): # pylint: disable=too-few-public-methods return self._argparser.parse_args(argv) - @staticmethod - def _append_to_settings(project_dir, code, comment): - 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' - - text = '\n' + comment + '\n' + code + '\n' - with open(settings_file, 'a') as f: - f.write(text) - if os.path.isfile(settings_file_py2cache): - os.unlink(settings_file_py2cache) # pragma: no cover - @staticmethod def _install_django_files(project_dir, overwrite=False): if os.path.exists(project_dir): @@ -64,33 +53,63 @@ class Program(object): # pylint: disable=too-few-public-methods exitval = os.system(cmd) return exitval - def _add_installed_apps_from_app(self, project_dir, app): - settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_DIR) + @staticmethod + def _append_to_pythonfile(path, text): + py2_cache = path + 'c' + with open(path, 'a') as f: + f.write(text) + if os.path.isfile(py2_cache): + os.unlink(py2_cache) # pragma: no cover + def _append_to_settings(self, project_dir, code, comment): + settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_DIR) + settings_file = os.path.join(settings_dir, 'settings.py') + + text = '\n' + comment + '\n' + code + '\n' + return self._append_to_pythonfile(settings_file, text) + + def _append_to_urlconf(self, project_dir, code, comment): + settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_DIR) + settings_file = os.path.join(settings_dir, 'urls.py') + + text = '\n' + comment + '\n' + code + '\n' + return self._append_to_pythonfile(settings_file, text) + + def _add_installed_apps_from_app(self, project_dir, app): 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 + wanted_apps = settings_from_app.ADD_INSTALLED_APPS else: - add_apps = [] + wanted_apps = [] - if not add_apps: - sys.stdout.write('{}: do not care about INSTALLED_APPS\n'.format(app)) + if wanted_apps: + sys.stdout.write('{app}: wanted apps: {apps}\n'.format(app=app, apps=', '.join(wanted_apps))) + else: return os.EX_OK + settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_DIR) sys.path.insert(0, settings_dir) settings = importlib.import_module('settings') sys.path.pop(0) + already_apps = [] missing_apps = [] - for add_app in add_apps: - if add_app not in settings.INSTALLED_APPS: - missing_apps.append(add_app) + for wanted_app in wanted_apps: + if wanted_app in settings.INSTALLED_APPS: + already_apps.append(wanted_app) + else: + missing_apps.append(wanted_app) + + if already_apps: + sys.stdout.write('{app}: already in settings.INSTALLED_APPS:' + ' {apps}\n'.format(app=app, apps=', '.join(already_apps))) if missing_apps: - sys.stdout.write('{app}: adding {apps} to INSTALLED_APPS\n'.format(app=app, apps=missing_apps)) + sys.stdout.write('{app}: adding to settings.INSTALLED_APPS:' + ' {apps}\n'.format(app=app, apps=', '.join(missing_apps))) code = 'INSTALLED_APPS += [\n' - for add_app in missing_apps: - code += ' \'{}\',\n'.format(add_app) + for missing_app in missing_apps: + code += ' \'{}\',\n'.format(missing_app) code += ']\n' timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') comment = '### {app}: added apps with django-deploy at {timestamp}'.format(app=app, @@ -98,25 +117,68 @@ class Program(object): # pylint: disable=too-few-public-methods self._append_to_settings(project_dir, code, comment) else: - sys.stdout.write('{app}: INSTALLED_APPS is fine\n'.format(app=app)) + sys.stdout.write('{app}: all wanted apps are already in settings.INSTALLED_APPS\n'.format(app=app)) return os.EX_OK - def _add_urlpatterns_from_app(self, project_dir, app): - settings_dir = os.path.join(project_dir, DJANGO_SETTINGS_DIR) - + def _add_urlpatterns_from_app(self, project_dir, app): # pylint: disable=too-many-locals,too-many-branches settings_from_app = importlib.import_module('{}.django_settings'.format(app)) if hasattr(settings_from_app, 'ADD_URLPATTERNS'): - add_urls = settings_from_app.ADD_URLPATTERNS + wanted_urls = {} + for wanted in settings_from_app.ADD_URLPATTERNS: + wanted_urls[wanted['pattern']] = wanted + wanted_patterns = wanted_urls.keys() else: - add_urls = [] + wanted_urls = {} + wanted_patterns = [] - if not add_urls: - sys.stdout.write('{}: do not care about ROOT_URLCONF\n'.format(app)) + if wanted_urls: + sys.stdout.write('{app}: wanted urlpatterns: {urls}\n'.format(app=app, urls=', '.join(wanted_patterns))) + else: return os.EX_OK - raise NotImplementedError() - self._append_to_settings(project_dir, code, comment) + root_urlconf = get_root_urlconf(project_dir) + + already_patterns = [] + for item in root_urlconf.urlpatterns: + if hasattr(item, 'pattern'): + pattern = str(item.pattern) + else: + pattern = item.regex.pattern + if pattern in wanted_patterns: + already_patterns.append(pattern) + + missing_patterns = [pattern for pattern in wanted_patterns if pattern not in already_patterns] + + if already_patterns: + sys.stdout.write('{app}: already in urlpatterns:' + ' {urls}\n'.format(app=app, urls=', '.join(already_patterns))) + + if missing_patterns: + sys.stdout.write('{app}: adding to urlpatterns:' + ' {apps}\n'.format(app=app, apps=', '.join(missing_patterns))) + code = '' + if not hasattr(root_urlconf, 'url'): + code += 'from django.conf.urls import url\n' + if not hasattr(root_urlconf, 'include'): + code += 'from django.conf.urls import include\n' + code += 'urlpatterns += [\n' + for pattern in missing_patterns: + url = wanted_urls[pattern] + if url['type'] == 'include': + code += " url(r'{pattern}', include('{module}')),\n".format(pattern=pattern, + module=url['module']) + else: + sys.stderr.write('{app}: not a supported url type: {type}\n'.format(app=app, type=url['type'])) + code += ']\n' + timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + comment = '### {app}: added urlpatterns with django-deploy at {timestamp}'.format(app=app, + timestamp=timestamp) + self._append_to_urlconf(project_dir, code, comment) + else: + sys.stdout.write('{app}: all wanted patterns are already in urlconfig\n'.format(app=app)) + + return os.EX_OK def _merge_app(self, project_dir, app): exitval = self._add_installed_apps_from_app(project_dir, app) diff --git a/src/django_deploy/tests/fake_app/django_settings.py b/src/django_deploy/tests/fake_app/django_settings.py index b46f77e..23e6a92 100644 --- a/src/django_deploy/tests/fake_app/django_settings.py +++ b/src/django_deploy/tests/fake_app/django_settings.py @@ -1,4 +1,4 @@ ADD_INSTALLED_APPS = ['django_deploy.tests.fake_app'] ADD_URLPATTERNS = [ - {'type': 'include', 'pattern': 'fake/', 'module': 'django_deploy.tests.fake_app.urls'}, + {'type': 'include', 'pattern': '^fake/', 'module': 'django_deploy.tests.fake_app.urls'}, ] diff --git a/src/django_deploy/tests/fake_app/urls.py b/src/django_deploy/tests/fake_app/urls.py index 85d5294..0d2edeb 100644 --- a/src/django_deploy/tests/fake_app/urls.py +++ b/src/django_deploy/tests/fake_app/urls.py @@ -1,2 +1,3 @@ +# pylint: skip-file app_name = 'fake1' -urlpatterns = [] \ No newline at end of file +urlpatterns = [] diff --git a/src/django_deploy/tests/test_program.py b/src/django_deploy/tests/test_program.py index 1ee4d9d..cfdc511 100644 --- a/src/django_deploy/tests/test_program.py +++ b/src/django_deploy/tests/test_program.py @@ -4,10 +4,9 @@ import sys import unittest import pytest -from unittest import mock - from ..config import DJANGO_SETTINGS_DIR from ..program import Program +from ..utils import get_root_urlconf class MainTestCase(unittest.TestCase): @@ -83,41 +82,38 @@ class MainTestCase(unittest.TestCase): 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'] + root_urlconf = get_root_urlconf(project_dir) + + if hasattr(root_urlconf, 'path'): + expected_urlpatterns = [ + ('URLPattern', 'admin/', 'django.contrib.admin.site.urls'), + ] 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/'), + expected_urlpatterns = [ + ('URLPattern', '^admin/', 'django.contrib.admin.site.urls'), + ] + expected_urlpatterns += [ + ('URLResolver', '^fake/', 'django_deploy.tests.fake_app.urls'), ] - 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] + for i, expected in enumerate(expected_urlpatterns): 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) + real_class_name = real.__class__.__name__ + self.assertTrue(real_class_name.endswith(expected[0])) + if real_class_name == 'URLPattern': + self.assertEqual(expected[1], str(real.pattern)) + self.assertTrue(real.callback.startswith("