diff options
author | django-bot <ops@djangoproject.com> | 2022-02-03 20:24:19 +0100 |
---|---|---|
committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2022-02-07 20:37:05 +0100 |
commit | 9c19aff7c7561e3a82978a272ecdaad40dda5c00 (patch) | |
tree | f0506b668a013d0063e5fba3dbf4863b466713ba /tests/utils_tests | |
parent | f68fa8b45dfac545cfc4111d4e52804c86db68d3 (diff) | |
download | django-9c19aff7c7561e3a82978a272ecdaad40dda5c00.tar.gz |
Refs #33476 -- Reformatted code with Black.
Diffstat (limited to 'tests/utils_tests')
41 files changed, 2638 insertions, 1855 deletions
diff --git a/tests/utils_tests/test_archive.py b/tests/utils_tests/test_archive.py index 10f8e56198..8cd107063f 100644 --- a/tests/utils_tests/test_archive.py +++ b/tests/utils_tests/test_archive.py @@ -10,21 +10,22 @@ from django.utils import archive try: import bz2 # NOQA + HAS_BZ2 = True except ImportError: HAS_BZ2 = False try: import lzma # NOQA + HAS_LZMA = True except ImportError: HAS_LZMA = False class TestArchive(unittest.TestCase): - def setUp(self): - self.testdir = os.path.join(os.path.dirname(__file__), 'archives') + self.testdir = os.path.join(os.path.dirname(__file__), "archives") self.old_cwd = os.getcwd() os.chdir(self.testdir) @@ -35,20 +36,25 @@ class TestArchive(unittest.TestCase): with os.scandir(self.testdir) as entries: for entry in entries: with self.subTest(entry.name), tempfile.TemporaryDirectory() as tmpdir: - if ( - (entry.name.endswith('.bz2') and not HAS_BZ2) or - (entry.name.endswith(('.lzma', '.xz')) and not HAS_LZMA) + if (entry.name.endswith(".bz2") and not HAS_BZ2) or ( + entry.name.endswith((".lzma", ".xz")) and not HAS_LZMA ): continue archive.extract(entry.path, tmpdir) - self.assertTrue(os.path.isfile(os.path.join(tmpdir, '1'))) - self.assertTrue(os.path.isfile(os.path.join(tmpdir, '2'))) - self.assertTrue(os.path.isfile(os.path.join(tmpdir, 'foo', '1'))) - self.assertTrue(os.path.isfile(os.path.join(tmpdir, 'foo', '2'))) - self.assertTrue(os.path.isfile(os.path.join(tmpdir, 'foo', 'bar', '1'))) - self.assertTrue(os.path.isfile(os.path.join(tmpdir, 'foo', 'bar', '2'))) + self.assertTrue(os.path.isfile(os.path.join(tmpdir, "1"))) + self.assertTrue(os.path.isfile(os.path.join(tmpdir, "2"))) + self.assertTrue(os.path.isfile(os.path.join(tmpdir, "foo", "1"))) + self.assertTrue(os.path.isfile(os.path.join(tmpdir, "foo", "2"))) + self.assertTrue( + os.path.isfile(os.path.join(tmpdir, "foo", "bar", "1")) + ) + self.assertTrue( + os.path.isfile(os.path.join(tmpdir, "foo", "bar", "2")) + ) - @unittest.skipIf(sys.platform == 'win32', 'Python on Windows has a limited os.chmod().') + @unittest.skipIf( + sys.platform == "win32", "Python on Windows has a limited os.chmod()." + ) def test_extract_file_permissions(self): """archive.extract() preserves file permissions.""" mask = stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO @@ -57,33 +63,33 @@ class TestArchive(unittest.TestCase): with os.scandir(self.testdir) as entries: for entry in entries: if ( - entry.name.startswith('leadpath_') or - (entry.name.endswith('.bz2') and not HAS_BZ2) or - (entry.name.endswith(('.lzma', '.xz')) and not HAS_LZMA) + entry.name.startswith("leadpath_") + or (entry.name.endswith(".bz2") and not HAS_BZ2) + or (entry.name.endswith((".lzma", ".xz")) and not HAS_LZMA) ): continue with self.subTest(entry.name), tempfile.TemporaryDirectory() as tmpdir: archive.extract(entry.path, tmpdir) # An executable file in the archive has executable # permissions. - filepath = os.path.join(tmpdir, 'executable') + filepath = os.path.join(tmpdir, "executable") self.assertEqual(os.stat(filepath).st_mode & mask, 0o775) # A file is readable even if permission data is missing. - filepath = os.path.join(tmpdir, 'no_permissions') + filepath = os.path.join(tmpdir, "no_permissions") self.assertEqual(os.stat(filepath).st_mode & mask, 0o666 & ~umask) class TestArchiveInvalid(SimpleTestCase): def test_extract_function_traversal(self): - archives_dir = os.path.join(os.path.dirname(__file__), 'traversal_archives') + archives_dir = os.path.join(os.path.dirname(__file__), "traversal_archives") tests = [ - ('traversal.tar', '..'), - ('traversal_absolute.tar', '/tmp/evil.py'), + ("traversal.tar", ".."), + ("traversal_absolute.tar", "/tmp/evil.py"), ] - if sys.platform == 'win32': + if sys.platform == "win32": tests += [ - ('traversal_disk_win.tar', 'd:evil.py'), - ('traversal_disk_win.zip', 'd:evil.py'), + ("traversal_disk_win.tar", "d:evil.py"), + ("traversal_disk_win.zip", "d:evil.py"), ] msg = "Archive contains invalid path: '%s'" for entry, invalid_path in tests: diff --git a/tests/utils_tests/test_autoreload.py b/tests/utils_tests/test_autoreload.py index 9b318722c0..c50d141cf3 100644 --- a/tests/utils_tests/test_autoreload.py +++ b/tests/utils_tests/test_autoreload.py @@ -26,7 +26,8 @@ from django.test.utils import extend_sys_path from django.utils import autoreload from django.utils.autoreload import WatchmanUnavailable -from .test_module import __main__ as test_main, main_module as test_main_module +from .test_module import __main__ as test_main +from .test_module import main_module as test_main_module from .utils import on_macos_with_hfs @@ -45,18 +46,26 @@ class TestIterModulesAndFiles(SimpleTestCase): resolved_filename = filename.resolve(strict=True) self.clear_autoreload_caches() # Test uncached access - self.assertIn(resolved_filename, list(autoreload.iter_all_python_module_files())) + self.assertIn( + resolved_filename, list(autoreload.iter_all_python_module_files()) + ) # Test cached access - self.assertIn(resolved_filename, list(autoreload.iter_all_python_module_files())) + self.assertIn( + resolved_filename, list(autoreload.iter_all_python_module_files()) + ) self.assertEqual(autoreload.iter_modules_and_files.cache_info().hits, 1) def assertFileNotFound(self, filename): resolved_filename = filename.resolve(strict=True) self.clear_autoreload_caches() # Test uncached access - self.assertNotIn(resolved_filename, list(autoreload.iter_all_python_module_files())) + self.assertNotIn( + resolved_filename, list(autoreload.iter_all_python_module_files()) + ) # Test cached access - self.assertNotIn(resolved_filename, list(autoreload.iter_all_python_module_files())) + self.assertNotIn( + resolved_filename, list(autoreload.iter_all_python_module_files()) + ) self.assertEqual(autoreload.iter_modules_and_files.cache_info().hits, 1) def temporary_file(self, filename): @@ -72,11 +81,11 @@ class TestIterModulesAndFiles(SimpleTestCase): """ When a file is added, it's returned by iter_all_python_module_files(). """ - filename = self.temporary_file('test_deleted_removed_module.py') + filename = self.temporary_file("test_deleted_removed_module.py") filename.touch() with extend_sys_path(str(filename.parent)): - self.import_and_cleanup('test_deleted_removed_module') + self.import_and_cleanup("test_deleted_removed_module") self.assertFileFound(filename.absolute()) @@ -85,13 +94,13 @@ class TestIterModulesAndFiles(SimpleTestCase): When a file containing an error is imported in a function wrapped by check_errors(), gen_filenames() returns it. """ - filename = self.temporary_file('test_syntax_error.py') + filename = self.temporary_file("test_syntax_error.py") filename.write_text("Ceci n'est pas du Python.") with extend_sys_path(str(filename.parent)): try: with self.assertRaises(SyntaxError): - autoreload.check_errors(import_module)('test_syntax_error') + autoreload.check_errors(import_module)("test_syntax_error") finally: autoreload._exception = None self.assertFileFound(filename) @@ -101,12 +110,12 @@ class TestIterModulesAndFiles(SimpleTestCase): Since Python may raise arbitrary exceptions when importing code, check_errors() must catch Exception, not just some subclasses. """ - filename = self.temporary_file('test_exception.py') - filename.write_text('raise Exception') + filename = self.temporary_file("test_exception.py") + filename.write_text("raise Exception") with extend_sys_path(str(filename.parent)): try: with self.assertRaises(Exception): - autoreload.check_errors(import_module)('test_exception') + autoreload.check_errors(import_module)("test_exception") finally: autoreload._exception = None self.assertFileFound(filename) @@ -116,48 +125,54 @@ class TestIterModulesAndFiles(SimpleTestCase): Modules imported from zipped files have their archive location included in the result. """ - zip_file = self.temporary_file('zip_import.zip') - with zipfile.ZipFile(str(zip_file), 'w', zipfile.ZIP_DEFLATED) as zipf: - zipf.writestr('test_zipped_file.py', '') + zip_file = self.temporary_file("zip_import.zip") + with zipfile.ZipFile(str(zip_file), "w", zipfile.ZIP_DEFLATED) as zipf: + zipf.writestr("test_zipped_file.py", "") with extend_sys_path(str(zip_file)): - self.import_and_cleanup('test_zipped_file') + self.import_and_cleanup("test_zipped_file") self.assertFileFound(zip_file) def test_bytecode_conversion_to_source(self): """.pyc and .pyo files are included in the files list.""" - filename = self.temporary_file('test_compiled.py') + filename = self.temporary_file("test_compiled.py") filename.touch() - compiled_file = Path(py_compile.compile(str(filename), str(filename.with_suffix('.pyc')))) + compiled_file = Path( + py_compile.compile(str(filename), str(filename.with_suffix(".pyc"))) + ) filename.unlink() with extend_sys_path(str(compiled_file.parent)): - self.import_and_cleanup('test_compiled') + self.import_and_cleanup("test_compiled") self.assertFileFound(compiled_file) def test_weakref_in_sys_module(self): """iter_all_python_module_file() ignores weakref modules.""" time_proxy = weakref.proxy(time) - sys.modules['time_proxy'] = time_proxy - self.addCleanup(lambda: sys.modules.pop('time_proxy', None)) + sys.modules["time_proxy"] = time_proxy + self.addCleanup(lambda: sys.modules.pop("time_proxy", None)) list(autoreload.iter_all_python_module_files()) # No crash. def test_module_without_spec(self): - module = types.ModuleType('test_module') + module = types.ModuleType("test_module") del module.__spec__ - self.assertEqual(autoreload.iter_modules_and_files((module,), frozenset()), frozenset()) + self.assertEqual( + autoreload.iter_modules_and_files((module,), frozenset()), frozenset() + ) def test_main_module_is_resolved(self): - main_module = sys.modules['__main__'] + main_module = sys.modules["__main__"] self.assertFileFound(Path(main_module.__file__)) def test_main_module_without_file_is_not_resolved(self): - fake_main = types.ModuleType('__main__') - self.assertEqual(autoreload.iter_modules_and_files((fake_main,), frozenset()), frozenset()) + fake_main = types.ModuleType("__main__") + self.assertEqual( + autoreload.iter_modules_and_files((fake_main,), frozenset()), frozenset() + ) def test_path_with_embedded_null_bytes(self): for path in ( - 'embedded_null_byte\x00.py', - 'di\x00rectory/embedded_null_byte.py', + "embedded_null_byte\x00.py", + "di\x00rectory/embedded_null_byte.py", ): with self.subTest(path=path): self.assertEqual( @@ -167,108 +182,105 @@ class TestIterModulesAndFiles(SimpleTestCase): class TestChildArguments(SimpleTestCase): - @mock.patch.dict(sys.modules, {'__main__': django.__main__}) - @mock.patch('sys.argv', [django.__main__.__file__, 'runserver']) - @mock.patch('sys.warnoptions', []) - @mock.patch('sys._xoptions', {}) + @mock.patch.dict(sys.modules, {"__main__": django.__main__}) + @mock.patch("sys.argv", [django.__main__.__file__, "runserver"]) + @mock.patch("sys.warnoptions", []) + @mock.patch("sys._xoptions", {}) def test_run_as_module(self): self.assertEqual( autoreload.get_child_arguments(), - [sys.executable, '-m', 'django', 'runserver'] + [sys.executable, "-m", "django", "runserver"], ) - @mock.patch.dict(sys.modules, {'__main__': test_main}) - @mock.patch('sys.argv', [test_main.__file__, 'runserver']) - @mock.patch('sys.warnoptions', []) - @mock.patch('sys._xoptions', {}) + @mock.patch.dict(sys.modules, {"__main__": test_main}) + @mock.patch("sys.argv", [test_main.__file__, "runserver"]) + @mock.patch("sys.warnoptions", []) + @mock.patch("sys._xoptions", {}) def test_run_as_non_django_module(self): self.assertEqual( autoreload.get_child_arguments(), - [sys.executable, '-m', 'utils_tests.test_module', 'runserver'], + [sys.executable, "-m", "utils_tests.test_module", "runserver"], ) - @mock.patch.dict(sys.modules, {'__main__': test_main_module}) - @mock.patch('sys.argv', [test_main.__file__, 'runserver']) - @mock.patch('sys.warnoptions', []) - @mock.patch('sys._xoptions', {}) + @mock.patch.dict(sys.modules, {"__main__": test_main_module}) + @mock.patch("sys.argv", [test_main.__file__, "runserver"]) + @mock.patch("sys.warnoptions", []) + @mock.patch("sys._xoptions", {}) def test_run_as_non_django_module_non_package(self): self.assertEqual( autoreload.get_child_arguments(), - [sys.executable, '-m', 'utils_tests.test_module.main_module', 'runserver'], + [sys.executable, "-m", "utils_tests.test_module.main_module", "runserver"], ) - @mock.patch('__main__.__spec__', None) - @mock.patch('sys.argv', [__file__, 'runserver']) - @mock.patch('sys.warnoptions', ['error']) - @mock.patch('sys._xoptions', {}) + @mock.patch("__main__.__spec__", None) + @mock.patch("sys.argv", [__file__, "runserver"]) + @mock.patch("sys.warnoptions", ["error"]) + @mock.patch("sys._xoptions", {}) def test_warnoptions(self): self.assertEqual( autoreload.get_child_arguments(), - [sys.executable, '-Werror', __file__, 'runserver'] + [sys.executable, "-Werror", __file__, "runserver"], ) - @mock.patch('sys.argv', [__file__, 'runserver']) - @mock.patch('sys.warnoptions', []) - @mock.patch('sys._xoptions', {'utf8': True, 'a': 'b'}) + @mock.patch("sys.argv", [__file__, "runserver"]) + @mock.patch("sys.warnoptions", []) + @mock.patch("sys._xoptions", {"utf8": True, "a": "b"}) def test_xoptions(self): self.assertEqual( autoreload.get_child_arguments(), - [sys.executable, '-Xutf8', '-Xa=b', __file__, 'runserver'], + [sys.executable, "-Xutf8", "-Xa=b", __file__, "runserver"], ) - @mock.patch('__main__.__spec__', None) - @mock.patch('sys.warnoptions', []) + @mock.patch("__main__.__spec__", None) + @mock.patch("sys.warnoptions", []) def test_exe_fallback(self): with tempfile.TemporaryDirectory() as tmpdir: - exe_path = Path(tmpdir) / 'django-admin.exe' + exe_path = Path(tmpdir) / "django-admin.exe" exe_path.touch() - with mock.patch('sys.argv', [exe_path.with_suffix(''), 'runserver']): + with mock.patch("sys.argv", [exe_path.with_suffix(""), "runserver"]): self.assertEqual( - autoreload.get_child_arguments(), - [exe_path, 'runserver'] + autoreload.get_child_arguments(), [exe_path, "runserver"] ) - @mock.patch('__main__.__spec__', None) - @mock.patch('sys.warnoptions', []) - @mock.patch('sys._xoptions', {}) + @mock.patch("__main__.__spec__", None) + @mock.patch("sys.warnoptions", []) + @mock.patch("sys._xoptions", {}) def test_entrypoint_fallback(self): with tempfile.TemporaryDirectory() as tmpdir: - script_path = Path(tmpdir) / 'django-admin-script.py' + script_path = Path(tmpdir) / "django-admin-script.py" script_path.touch() - with mock.patch('sys.argv', [script_path.with_name('django-admin'), 'runserver']): + with mock.patch( + "sys.argv", [script_path.with_name("django-admin"), "runserver"] + ): self.assertEqual( autoreload.get_child_arguments(), - [sys.executable, script_path, 'runserver'] + [sys.executable, script_path, "runserver"], ) - @mock.patch('__main__.__spec__', None) - @mock.patch('sys.argv', ['does-not-exist', 'runserver']) - @mock.patch('sys.warnoptions', []) + @mock.patch("__main__.__spec__", None) + @mock.patch("sys.argv", ["does-not-exist", "runserver"]) + @mock.patch("sys.warnoptions", []) def test_raises_runtimeerror(self): - msg = 'Script does-not-exist does not exist.' + msg = "Script does-not-exist does not exist." with self.assertRaisesMessage(RuntimeError, msg): autoreload.get_child_arguments() - @mock.patch('sys.argv', [__file__, 'runserver']) - @mock.patch('sys.warnoptions', []) - @mock.patch('sys._xoptions', {}) + @mock.patch("sys.argv", [__file__, "runserver"]) + @mock.patch("sys.warnoptions", []) + @mock.patch("sys._xoptions", {}) def test_module_no_spec(self): - module = types.ModuleType('test_module') + module = types.ModuleType("test_module") del module.__spec__ - with mock.patch.dict(sys.modules, {'__main__': module}): + with mock.patch.dict(sys.modules, {"__main__": module}): self.assertEqual( autoreload.get_child_arguments(), - [sys.executable, __file__, 'runserver'] + [sys.executable, __file__, "runserver"], ) class TestUtilities(SimpleTestCase): def test_is_django_module(self): - for module, expected in ( - (zoneinfo, False), - (sys, False), - (autoreload, True) - ): + for module, expected in ((zoneinfo, False), (sys, False), (autoreload, True)): with self.subTest(module=module): self.assertIs(autoreload.is_django_module(module), expected) @@ -276,7 +288,7 @@ class TestUtilities(SimpleTestCase): for module, expected in ( (zoneinfo.__file__, False), (contextlib.__file__, False), - (autoreload.__file__, True) + (autoreload.__file__, True), ): with self.subTest(module=module): self.assertIs(autoreload.is_django_path(module), expected) @@ -285,20 +297,20 @@ class TestUtilities(SimpleTestCase): class TestCommonRoots(SimpleTestCase): def test_common_roots(self): paths = ( - Path('/first/second'), - Path('/first/second/third'), - Path('/first/'), - Path('/root/first/'), + Path("/first/second"), + Path("/first/second/third"), + Path("/first/"), + Path("/root/first/"), ) results = autoreload.common_roots(paths) - self.assertCountEqual(results, [Path('/first/'), Path('/root/first/')]) + self.assertCountEqual(results, [Path("/first/"), Path("/root/first/")]) class TestSysPathDirectories(SimpleTestCase): def setUp(self): self._directory = tempfile.TemporaryDirectory() self.directory = Path(self._directory.name).resolve(strict=True).absolute() - self.file = self.directory / 'test' + self.file = self.directory / "test" self.file.touch() def tearDown(self): @@ -310,7 +322,7 @@ class TestSysPathDirectories(SimpleTestCase): self.assertIn(self.file.parent, paths) def test_sys_paths_non_existing(self): - nonexistent_file = Path(self.directory.name) / 'does_not_exist' + nonexistent_file = Path(self.directory.name) / "does_not_exist" with extend_sys_path(str(nonexistent_file)): paths = list(autoreload.sys_path_directories()) self.assertNotIn(nonexistent_file, paths) @@ -327,12 +339,12 @@ class TestSysPathDirectories(SimpleTestCase): class GetReloaderTests(SimpleTestCase): - @mock.patch('django.utils.autoreload.WatchmanReloader') + @mock.patch("django.utils.autoreload.WatchmanReloader") def test_watchman_unavailable(self, mocked_watchman): mocked_watchman.check_availability.side_effect = WatchmanUnavailable self.assertIsInstance(autoreload.get_reloader(), autoreload.StatReloader) - @mock.patch.object(autoreload.WatchmanReloader, 'check_availability') + @mock.patch.object(autoreload.WatchmanReloader, "check_availability") def test_watchman_available(self, mocked_available): # If WatchmanUnavailable isn't raised, Watchman will be chosen. mocked_available.return_value = None @@ -341,35 +353,35 @@ class GetReloaderTests(SimpleTestCase): class RunWithReloaderTests(SimpleTestCase): - @mock.patch.dict(os.environ, {autoreload.DJANGO_AUTORELOAD_ENV: 'true'}) - @mock.patch('django.utils.autoreload.get_reloader') + @mock.patch.dict(os.environ, {autoreload.DJANGO_AUTORELOAD_ENV: "true"}) + @mock.patch("django.utils.autoreload.get_reloader") def test_swallows_keyboard_interrupt(self, mocked_get_reloader): mocked_get_reloader.side_effect = KeyboardInterrupt() autoreload.run_with_reloader(lambda: None) # No exception - @mock.patch.dict(os.environ, {autoreload.DJANGO_AUTORELOAD_ENV: 'false'}) - @mock.patch('django.utils.autoreload.restart_with_reloader') + @mock.patch.dict(os.environ, {autoreload.DJANGO_AUTORELOAD_ENV: "false"}) + @mock.patch("django.utils.autoreload.restart_with_reloader") def test_calls_sys_exit(self, mocked_restart_reloader): mocked_restart_reloader.return_value = 1 with self.assertRaises(SystemExit) as exc: autoreload.run_with_reloader(lambda: None) self.assertEqual(exc.exception.code, 1) - @mock.patch.dict(os.environ, {autoreload.DJANGO_AUTORELOAD_ENV: 'true'}) - @mock.patch('django.utils.autoreload.start_django') - @mock.patch('django.utils.autoreload.get_reloader') + @mock.patch.dict(os.environ, {autoreload.DJANGO_AUTORELOAD_ENV: "true"}) + @mock.patch("django.utils.autoreload.start_django") + @mock.patch("django.utils.autoreload.get_reloader") def test_calls_start_django(self, mocked_reloader, mocked_start_django): mocked_reloader.return_value = mock.sentinel.RELOADER autoreload.run_with_reloader(mock.sentinel.METHOD) self.assertEqual(mocked_start_django.call_count, 1) self.assertSequenceEqual( mocked_start_django.call_args[0], - [mock.sentinel.RELOADER, mock.sentinel.METHOD] + [mock.sentinel.RELOADER, mock.sentinel.METHOD], ) class StartDjangoTests(SimpleTestCase): - @mock.patch('django.utils.autoreload.StatReloader') + @mock.patch("django.utils.autoreload.StatReloader") def test_watchman_becomes_unavailable(self, mocked_stat): mocked_stat.should_stop.return_value = True fake_reloader = mock.MagicMock() @@ -379,21 +391,21 @@ class StartDjangoTests(SimpleTestCase): autoreload.start_django(fake_reloader, lambda: None) self.assertEqual(mocked_stat.call_count, 1) - @mock.patch('django.utils.autoreload.ensure_echo_on') + @mock.patch("django.utils.autoreload.ensure_echo_on") def test_echo_on_called(self, mocked_echo): fake_reloader = mock.MagicMock() autoreload.start_django(fake_reloader, lambda: None) self.assertEqual(mocked_echo.call_count, 1) - @mock.patch('django.utils.autoreload.check_errors') + @mock.patch("django.utils.autoreload.check_errors") def test_check_errors_called(self, mocked_check_errors): fake_method = mock.MagicMock(return_value=None) fake_reloader = mock.MagicMock() autoreload.start_django(fake_reloader, fake_method) self.assertCountEqual(mocked_check_errors.call_args[0], [fake_method]) - @mock.patch('threading.Thread') - @mock.patch('django.utils.autoreload.check_errors') + @mock.patch("threading.Thread") + @mock.patch("django.utils.autoreload.check_errors") def test_starts_thread_with_args(self, mocked_check_errors, mocked_thread): fake_reloader = mock.MagicMock() fake_main_func = mock.MagicMock() @@ -404,7 +416,12 @@ class StartDjangoTests(SimpleTestCase): self.assertEqual(mocked_thread.call_count, 1) self.assertEqual( mocked_thread.call_args[1], - {'target': fake_main_func, 'args': (123,), 'kwargs': {'abc': 123}, 'name': 'django-main-thread'} + { + "target": fake_main_func, + "args": (123,), + "kwargs": {"abc": 123}, + "name": "django-main-thread", + }, ) self.assertIs(fake_thread.daemon, True) self.assertTrue(fake_thread.start.called) @@ -414,7 +431,7 @@ class TestCheckErrors(SimpleTestCase): def test_mutates_error_files(self): fake_method = mock.MagicMock(side_effect=RuntimeError()) wrapped = autoreload.check_errors(fake_method) - with mock.patch.object(autoreload, '_error_files') as mocked_error_files: + with mock.patch.object(autoreload, "_error_files") as mocked_error_files: try: with self.assertRaises(RuntimeError): wrapped() @@ -424,7 +441,7 @@ class TestCheckErrors(SimpleTestCase): class TestRaiseLastException(SimpleTestCase): - @mock.patch('django.utils.autoreload._exception', None) + @mock.patch("django.utils.autoreload._exception", None) def test_no_exception(self): # Should raise no exception if _exception is None autoreload.raise_last_exception() @@ -435,12 +452,12 @@ class TestRaiseLastException(SimpleTestCase): # Create an exception try: - raise MyException('Test Message') + raise MyException("Test Message") except MyException: exc_info = sys.exc_info() - with mock.patch('django.utils.autoreload._exception', exc_info): - with self.assertRaisesMessage(MyException, 'Test Message'): + with mock.patch("django.utils.autoreload._exception", exc_info): + with self.assertRaisesMessage(MyException, "Test Message"): autoreload.raise_last_exception() def test_raises_custom_exception(self): @@ -448,14 +465,15 @@ class TestRaiseLastException(SimpleTestCase): def __init__(self, msg, extra_context): super().__init__(msg) self.extra_context = extra_context + # Create an exception. try: - raise MyException('Test Message', 'extra context') + raise MyException("Test Message", "extra context") except MyException: exc_info = sys.exc_info() - with mock.patch('django.utils.autoreload._exception', exc_info): - with self.assertRaisesMessage(MyException, 'Test Message'): + with mock.patch("django.utils.autoreload._exception", exc_info): + with self.assertRaisesMessage(MyException, "Test Message"): autoreload.raise_last_exception() def test_raises_exception_with_context(self): @@ -467,7 +485,7 @@ class TestRaiseLastException(SimpleTestCase): except Exception: exc_info = sys.exc_info() - with mock.patch('django.utils.autoreload._exception', exc_info): + with mock.patch("django.utils.autoreload._exception", exc_info): with self.assertRaises(Exception) as cm: autoreload.raise_last_exception() self.assertEqual(cm.exception.args[0], 1) @@ -475,15 +493,18 @@ class TestRaiseLastException(SimpleTestCase): class RestartWithReloaderTests(SimpleTestCase): - executable = '/usr/bin/python' + executable = "/usr/bin/python" def patch_autoreload(self, argv): - patch_call = mock.patch('django.utils.autoreload.subprocess.run', return_value=CompletedProcess(argv, 0)) + patch_call = mock.patch( + "django.utils.autoreload.subprocess.run", + return_value=CompletedProcess(argv, 0), + ) patches = [ - mock.patch('django.utils.autoreload.sys.argv', argv), - mock.patch('django.utils.autoreload.sys.executable', self.executable), - mock.patch('django.utils.autoreload.sys.warnoptions', ['all']), - mock.patch('django.utils.autoreload.sys._xoptions', {}), + mock.patch("django.utils.autoreload.sys.argv", argv), + mock.patch("django.utils.autoreload.sys.executable", self.executable), + mock.patch("django.utils.autoreload.sys.warnoptions", ["all"]), + mock.patch("django.utils.autoreload.sys._xoptions", {}), ] for p in patches: p.start() @@ -494,27 +515,30 @@ class RestartWithReloaderTests(SimpleTestCase): def test_manage_py(self): with tempfile.TemporaryDirectory() as temp_dir: - script = Path(temp_dir) / 'manage.py' + script = Path(temp_dir) / "manage.py" script.touch() - argv = [str(script), 'runserver'] + argv = [str(script), "runserver"] mock_call = self.patch_autoreload(argv) - with mock.patch('__main__.__spec__', None): + with mock.patch("__main__.__spec__", None): autoreload.restart_with_reloader() self.assertEqual(mock_call.call_count, 1) self.assertEqual( mock_call.call_args[0][0], - [self.executable, '-Wall'] + argv, + [self.executable, "-Wall"] + argv, ) def test_python_m_django(self): - main = '/usr/lib/pythonX.Y/site-packages/django/__main__.py' - argv = [main, 'runserver'] + main = "/usr/lib/pythonX.Y/site-packages/django/__main__.py" + argv = [main, "runserver"] mock_call = self.patch_autoreload(argv) - with mock.patch('django.__main__.__file__', main): - with mock.patch.dict(sys.modules, {'__main__': django.__main__}): + with mock.patch("django.__main__.__file__", main): + with mock.patch.dict(sys.modules, {"__main__": django.__main__}): autoreload.restart_with_reloader() self.assertEqual(mock_call.call_count, 1) - self.assertEqual(mock_call.call_args[0][0], [self.executable, '-Wall', '-m', 'django'] + argv[1:]) + self.assertEqual( + mock_call.call_args[0][0], + [self.executable, "-Wall", "-m", "django"] + argv[1:], + ) class ReloaderTests(SimpleTestCase): @@ -523,8 +547,8 @@ class ReloaderTests(SimpleTestCase): def setUp(self): self._tempdir = tempfile.TemporaryDirectory() self.tempdir = Path(self._tempdir.name).resolve(strict=True).absolute() - self.existing_file = self.ensure_file(self.tempdir / 'test.py') - self.nonexistent_file = (self.tempdir / 'does_not_exist.py').absolute() + self.existing_file = self.ensure_file(self.tempdir / "test.py") + self.nonexistent_file = (self.tempdir / "does_not_exist.py").absolute() self.reloader = self.RELOADER_CLS() def tearDown(self): @@ -558,80 +582,96 @@ class ReloaderTests(SimpleTestCase): class IntegrationTests: - @mock.patch('django.utils.autoreload.BaseReloader.notify_file_changed') - @mock.patch('django.utils.autoreload.iter_all_python_module_files', return_value=frozenset()) + @mock.patch("django.utils.autoreload.BaseReloader.notify_file_changed") + @mock.patch( + "django.utils.autoreload.iter_all_python_module_files", return_value=frozenset() + ) def test_glob(self, mocked_modules, notify_mock): - non_py_file = self.ensure_file(self.tempdir / 'non_py_file') - self.reloader.watch_dir(self.tempdir, '*.py') + non_py_file = self.ensure_file(self.tempdir / "non_py_file") + self.reloader.watch_dir(self.tempdir, "*.py") with self.tick_twice(): self.increment_mtime(non_py_file) self.increment_mtime(self.existing_file) self.assertEqual(notify_mock.call_count, 1) self.assertCountEqual(notify_mock.call_args[0], [self.existing_file]) - @mock.patch('django.utils.autoreload.BaseReloader.notify_file_changed') - @mock.patch('django.utils.autoreload.iter_all_python_module_files', return_value=frozenset()) + @mock.patch("django.utils.autoreload.BaseReloader.notify_file_changed") + @mock.patch( + "django.utils.autoreload.iter_all_python_module_files", return_value=frozenset() + ) def test_multiple_globs(self, mocked_modules, notify_mock): - self.ensure_file(self.tempdir / 'x.test') - self.reloader.watch_dir(self.tempdir, '*.py') - self.reloader.watch_dir(self.tempdir, '*.test') + self.ensure_file(self.tempdir / "x.test") + self.reloader.watch_dir(self.tempdir, "*.py") + self.reloader.watch_dir(self.tempdir, "*.test") with self.tick_twice(): self.increment_mtime(self.existing_file) self.assertEqual(notify_mock.call_count, 1) self.assertCountEqual(notify_mock.call_args[0], [self.existing_file]) - @mock.patch('django.utils.autoreload.BaseReloader.notify_file_changed') - @mock.patch('django.utils.autoreload.iter_all_python_module_files', return_value=frozenset()) + @mock.patch("django.utils.autoreload.BaseReloader.notify_file_changed") + @mock.patch( + "django.utils.autoreload.iter_all_python_module_files", return_value=frozenset() + ) def test_overlapping_globs(self, mocked_modules, notify_mock): - self.reloader.watch_dir(self.tempdir, '*.py') - self.reloader.watch_dir(self.tempdir, '*.p*') + self.reloader.watch_dir(self.tempdir, "*.py") + self.reloader.watch_dir(self.tempdir, "*.p*") with self.tick_twice(): self.increment_mtime(self.existing_file) self.assertEqual(notify_mock.call_count, 1) self.assertCountEqual(notify_mock.call_args[0], [self.existing_file]) - @mock.patch('django.utils.autoreload.BaseReloader.notify_file_changed') - @mock.patch('django.utils.autoreload.iter_all_python_module_files', return_value=frozenset()) + @mock.patch("django.utils.autoreload.BaseReloader.notify_file_changed") + @mock.patch( + "django.utils.autoreload.iter_all_python_module_files", return_value=frozenset() + ) def test_glob_recursive(self, mocked_modules, notify_mock): - non_py_file = self.ensure_file(self.tempdir / 'dir' / 'non_py_file') - py_file = self.ensure_file(self.tempdir / 'dir' / 'file.py') - self.reloader.watch_dir(self.tempdir, '**/*.py') + non_py_file = self.ensure_file(self.tempdir / "dir" / "non_py_file") + py_file = self.ensure_file(self.tempdir / "dir" / "file.py") + self.reloader.watch_dir(self.tempdir, "**/*.py") with self.tick_twice(): self.increment_mtime(non_py_file) self.increment_mtime(py_file) self.assertEqual(notify_mock.call_count, 1) self.assertCountEqual(notify_mock.call_args[0], [py_file]) - @mock.patch('django.utils.autoreload.BaseReloader.notify_file_changed') - @mock.patch('django.utils.autoreload.iter_all_python_module_files', return_value=frozenset()) + @mock.patch("django.utils.autoreload.BaseReloader.notify_file_changed") + @mock.patch( + "django.utils.autoreload.iter_all_python_module_files", return_value=frozenset() + ) def test_multiple_recursive_globs(self, mocked_modules, notify_mock): - non_py_file = self.ensure_file(self.tempdir / 'dir' / 'test.txt') - py_file = self.ensure_file(self.tempdir / 'dir' / 'file.py') - self.reloader.watch_dir(self.tempdir, '**/*.txt') - self.reloader.watch_dir(self.tempdir, '**/*.py') + non_py_file = self.ensure_file(self.tempdir / "dir" / "test.txt") + py_file = self.ensure_file(self.tempdir / "dir" / "file.py") + self.reloader.watch_dir(self.tempdir, "**/*.txt") + self.reloader.watch_dir(self.tempdir, "**/*.py") with self.tick_twice(): self.increment_mtime(non_py_file) self.increment_mtime(py_file) self.assertEqual(notify_mock.call_count, 2) - self.assertCountEqual(notify_mock.call_args_list, [mock.call(py_file), mock.call(non_py_file)]) + self.assertCountEqual( + notify_mock.call_args_list, [mock.call(py_file), mock.call(non_py_file)] + ) - @mock.patch('django.utils.autoreload.BaseReloader.notify_file_changed') - @mock.patch('django.utils.autoreload.iter_all_python_module_files', return_value=frozenset()) + @mock.patch("django.utils.autoreload.BaseReloader.notify_file_changed") + @mock.patch( + "django.utils.autoreload.iter_all_python_module_files", return_value=frozenset() + ) def test_nested_glob_recursive(self, mocked_modules, notify_mock): - inner_py_file = self.ensure_file(self.tempdir / 'dir' / 'file.py') - self.reloader.watch_dir(self.tempdir, '**/*.py') - self.reloader.watch_dir(inner_py_file.parent, '**/*.py') + inner_py_file = self.ensure_file(self.tempdir / "dir" / "file.py") + self.reloader.watch_dir(self.tempdir, "**/*.py") + self.reloader.watch_dir(inner_py_file.parent, "**/*.py") with self.tick_twice(): self.increment_mtime(inner_py_file) self.assertEqual(notify_mock.call_count, 1) self.assertCountEqual(notify_mock.call_args[0], [inner_py_file]) - @mock.patch('django.utils.autoreload.BaseReloader.notify_file_changed') - @mock.patch('django.utils.autoreload.iter_all_python_module_files', return_value=frozenset()) + @mock.patch("django.utils.autoreload.BaseReloader.notify_file_changed") + @mock.patch( + "django.utils.autoreload.iter_all_python_module_files", return_value=frozenset() + ) def test_overlapping_glob_recursive(self, mocked_modules, notify_mock): - py_file = self.ensure_file(self.tempdir / 'dir' / 'file.py') - self.reloader.watch_dir(self.tempdir, '**/*.p*') - self.reloader.watch_dir(self.tempdir, '**/*.py*') + py_file = self.ensure_file(self.tempdir / "dir" / "file.py") + self.reloader.watch_dir(self.tempdir, "**/*.p*") + self.reloader.watch_dir(self.tempdir, "**/*.py*") with self.tick_twice(): self.increment_mtime(py_file) self.assertEqual(notify_mock.call_count, 1) @@ -642,19 +682,19 @@ class BaseReloaderTests(ReloaderTests): RELOADER_CLS = autoreload.BaseReloader def test_watch_dir_with_unresolvable_path(self): - path = Path('unresolvable_directory') - with mock.patch.object(Path, 'absolute', side_effect=FileNotFoundError): - self.reloader.watch_dir(path, '**/*.mo') + path = Path("unresolvable_directory") + with mock.patch.object(Path, "absolute", side_effect=FileNotFoundError): + self.reloader.watch_dir(path, "**/*.mo") self.assertEqual(list(self.reloader.directory_globs), []) def test_watch_with_glob(self): - self.reloader.watch_dir(self.tempdir, '*.py') + self.reloader.watch_dir(self.tempdir, "*.py") watched_files = list(self.reloader.watched_files()) self.assertIn(self.existing_file, watched_files) def test_watch_files_with_recursive_glob(self): - inner_file = self.ensure_file(self.tempdir / 'test' / 'test.py') - self.reloader.watch_dir(self.tempdir, '**/*.py') + inner_file = self.ensure_file(self.tempdir / "test" / "test.py") + self.reloader.watch_dir(self.tempdir, "**/*.py") watched_files = list(self.reloader.watched_files()) self.assertIn(self.existing_file, watched_files) self.assertIn(inner_file, watched_files) @@ -663,7 +703,7 @@ class BaseReloaderTests(ReloaderTests): def mocked_tick(): yield - with mock.patch.object(self.reloader, 'tick', side_effect=mocked_tick) as tick: + with mock.patch.object(self.reloader, "tick", side_effect=mocked_tick) as tick: self.reloader.run_loop() self.assertEqual(tick.call_count, 1) @@ -673,7 +713,7 @@ class BaseReloaderTests(ReloaderTests): self.reloader.stop() return # Raises StopIteration - with mock.patch.object(self.reloader, 'tick', side_effect=mocked_tick) as tick: + with mock.patch.object(self.reloader, "tick", side_effect=mocked_tick) as tick: self.reloader.run_loop() self.assertEqual(tick.call_count, 1) @@ -697,7 +737,7 @@ def skip_unless_watchman_available(): try: autoreload.WatchmanReloader.check_availability() except WatchmanUnavailable as e: - return skip('Watchman unavailable: %s' % e) + return skip("Watchman unavailable: %s" % e) return lambda func: func @@ -708,33 +748,35 @@ class WatchmanReloaderTests(ReloaderTests, IntegrationTests): def setUp(self): super().setUp() # Shorten the timeout to speed up tests. - self.reloader.client_timeout = int(os.environ.get('DJANGO_WATCHMAN_TIMEOUT', 2)) + self.reloader.client_timeout = int(os.environ.get("DJANGO_WATCHMAN_TIMEOUT", 2)) def test_watch_glob_ignores_non_existing_directories_two_levels(self): - with mock.patch.object(self.reloader, '_subscribe') as mocked_subscribe: - self.reloader._watch_glob(self.tempdir / 'does_not_exist' / 'more', ['*']) + with mock.patch.object(self.reloader, "_subscribe") as mocked_subscribe: + self.reloader._watch_glob(self.tempdir / "does_not_exist" / "more", ["*"]) self.assertFalse(mocked_subscribe.called) def test_watch_glob_uses_existing_parent_directories(self): - with mock.patch.object(self.reloader, '_subscribe') as mocked_subscribe: - self.reloader._watch_glob(self.tempdir / 'does_not_exist', ['*']) + with mock.patch.object(self.reloader, "_subscribe") as mocked_subscribe: + self.reloader._watch_glob(self.tempdir / "does_not_exist", ["*"]) self.assertSequenceEqual( mocked_subscribe.call_args[0], [ - self.tempdir, 'glob-parent-does_not_exist:%s' % self.tempdir, - ['anyof', ['match', 'does_not_exist/*', 'wholename']] - ] + self.tempdir, + "glob-parent-does_not_exist:%s" % self.tempdir, + ["anyof", ["match", "does_not_exist/*", "wholename"]], + ], ) def test_watch_glob_multiple_patterns(self): - with mock.patch.object(self.reloader, '_subscribe') as mocked_subscribe: - self.reloader._watch_glob(self.tempdir, ['*', '*.py']) + with mock.patch.object(self.reloader, "_subscribe") as mocked_subscribe: + self.reloader._watch_glob(self.tempdir, ["*", "*.py"]) self.assertSequenceEqual( mocked_subscribe.call_args[0], [ - self.tempdir, 'glob:%s' % self.tempdir, - ['anyof', ['match', '*', 'wholename'], ['match', '*.py', 'wholename']] - ] + self.tempdir, + "glob:%s" % self.tempdir, + ["anyof", ["match", "*", "wholename"], ["match", "*.py", "wholename"]], + ], ) def test_watched_roots_contains_files(self): @@ -742,7 +784,7 @@ class WatchmanReloaderTests(ReloaderTests, IntegrationTests): self.assertIn(self.existing_file.parent, paths) def test_watched_roots_contains_directory_globs(self): - self.reloader.watch_dir(self.tempdir, '*.py') + self.reloader.watch_dir(self.tempdir, "*.py") paths = self.reloader.watched_roots([]) self.assertIn(self.tempdir, paths) @@ -755,42 +797,52 @@ class WatchmanReloaderTests(ReloaderTests, IntegrationTests): self.assertTrue(self.reloader.check_server_status()) def test_check_server_status_raises_error(self): - with mock.patch.object(self.reloader.client, 'query') as mocked_query: + with mock.patch.object(self.reloader.client, "query") as mocked_query: mocked_query.side_effect = Exception() with self.assertRaises(autoreload.WatchmanUnavailable): self.reloader.check_server_status() - @mock.patch('pywatchman.client') + @mock.patch("pywatchman.client") def test_check_availability(self, mocked_client): mocked_client().capabilityCheck.side_effect = Exception() - with self.assertRaisesMessage(WatchmanUnavailable, 'Cannot connect to the watchman service'): + with self.assertRaisesMessage( + WatchmanUnavailable, "Cannot connect to the watchman service" + ): self.RELOADER_CLS.check_availability() - @mock.patch('pywatchman.client') + @mock.patch("pywatchman.client") def test_check_availability_lower_version(self, mocked_client): - mocked_client().capabilityCheck.return_value = {'version': '4.8.10'} - with self.assertRaisesMessage(WatchmanUnavailable, 'Watchman 4.9 or later is required.'): + mocked_client().capabilityCheck.return_value = {"version": "4.8.10"} + with self.assertRaisesMessage( + WatchmanUnavailable, "Watchman 4.9 or later is required." + ): self.RELOADER_CLS.check_availability() def test_pywatchman_not_available(self): - with mock.patch.object(autoreload, 'pywatchman') as mocked: + with mock.patch.object(autoreload, "pywatchman") as mocked: mocked.__bool__.return_value = False - with self.assertRaisesMessage(WatchmanUnavailable, 'pywatchman not installed.'): + with self.assertRaisesMessage( + WatchmanUnavailable, "pywatchman not installed." + ): self.RELOADER_CLS.check_availability() def test_update_watches_raises_exceptions(self): class TestException(Exception): pass - with mock.patch.object(self.reloader, '_update_watches') as mocked_watches: - with mock.patch.object(self.reloader, 'check_server_status') as mocked_server_status: + with mock.patch.object(self.reloader, "_update_watches") as mocked_watches: + with mock.patch.object( + self.reloader, "check_server_status" + ) as mocked_server_status: mocked_watches.side_effect = TestException() mocked_server_status.return_value = True with self.assertRaises(TestException): self.reloader.update_watches() - self.assertIsInstance(mocked_server_status.call_args[0][0], TestException) + self.assertIsInstance( + mocked_server_status.call_args[0][0], TestException + ) - @mock.patch.dict(os.environ, {'DJANGO_WATCHMAN_TIMEOUT': '10'}) + @mock.patch.dict(os.environ, {"DJANGO_WATCHMAN_TIMEOUT": "10"}) def test_setting_timeout_from_environment_variable(self): self.assertEqual(self.RELOADER_CLS().client_timeout, 10) @@ -804,9 +856,11 @@ class StatReloaderTests(ReloaderTests, IntegrationTests): # Shorten the sleep time to speed up tests. self.reloader.SLEEP_TIME = 0.01 - @mock.patch('django.utils.autoreload.StatReloader.notify_file_changed') + @mock.patch("django.utils.autoreload.StatReloader.notify_file_changed") def test_tick_does_not_trigger_twice(self, mock_notify_file_changed): - with mock.patch.object(self.reloader, 'watched_files', return_value=[self.existing_file]): + with mock.patch.object( + self.reloader, "watched_files", return_value=[self.existing_file] + ): ticker = self.reloader.tick() next(ticker) self.increment_mtime(self.existing_file) @@ -815,19 +869,29 @@ class StatReloaderTests(ReloaderTests, IntegrationTests): self.assertEqual(mock_notify_file_changed.call_count, 1) def test_snapshot_files_ignores_missing_files(self): - with mock.patch.object(self.reloader, 'watched_files', return_value=[self.nonexistent_file]): + with mock.patch.object( + self.reloader, "watched_files", return_value=[self.nonexistent_file] + ): self.assertEqual(dict(self.reloader.snapshot_files()), {}) def test_snapshot_files_updates(self): - with mock.patch.object(self.reloader, 'watched_files', return_value=[self.existing_file]): + with mock.patch.object( + self.reloader, "watched_files", return_value=[self.existing_file] + ): snapshot1 = dict(self.reloader.snapshot_files()) self.assertIn(self.existing_file, snapshot1) self.increment_mtime(self.existing_file) snapshot2 = dict(self.reloader.snapshot_files()) - self.assertNotEqual(snapshot1[self.existing_file], snapshot2[self.existing_file]) + self.assertNotEqual( + snapshot1[self.existing_file], snapshot2[self.existing_file] + ) def test_snapshot_files_with_duplicates(self): - with mock.patch.object(self.reloader, 'watched_files', return_value=[self.existing_file, self.existing_file]): + with mock.patch.object( + self.reloader, + "watched_files", + return_value=[self.existing_file, self.existing_file], + ): snapshot = list(self.reloader.snapshot_files()) self.assertEqual(len(snapshot), 1) self.assertEqual(snapshot[0][0], self.existing_file) diff --git a/tests/utils_tests/test_baseconv.py b/tests/utils_tests/test_baseconv.py index 989e1eb0bf..5f69b65b9f 100644 --- a/tests/utils_tests/test_baseconv.py +++ b/tests/utils_tests/test_baseconv.py @@ -5,51 +5,56 @@ from django.utils.deprecation import RemovedInDjango50Warning with ignore_warnings(category=RemovedInDjango50Warning): from django.utils.baseconv import ( - BaseConverter, base2, base16, base36, base56, base62, base64, + BaseConverter, + base2, + base16, + base36, + base56, + base62, + base64, ) # RemovedInDjango50Warning class TestBaseConv(TestCase): - def test_baseconv(self): - nums = [-10 ** 10, 10 ** 10, *range(-100, 100)] + nums = [-(10**10), 10**10, *range(-100, 100)] for converter in [base2, base16, base36, base56, base62, base64]: for i in nums: self.assertEqual(i, converter.decode(converter.encode(i))) def test_base11(self): - base11 = BaseConverter('0123456789-', sign='$') - self.assertEqual(base11.encode(1234), '-22') - self.assertEqual(base11.decode('-22'), 1234) - self.assertEqual(base11.encode(-1234), '$-22') - self.assertEqual(base11.decode('$-22'), -1234) + base11 = BaseConverter("0123456789-", sign="$") + self.assertEqual(base11.encode(1234), "-22") + self.assertEqual(base11.decode("-22"), 1234) + self.assertEqual(base11.encode(-1234), "$-22") + self.assertEqual(base11.decode("$-22"), -1234) def test_base20(self): - base20 = BaseConverter('0123456789abcdefghij') - self.assertEqual(base20.encode(1234), '31e') - self.assertEqual(base20.decode('31e'), 1234) - self.assertEqual(base20.encode(-1234), '-31e') - self.assertEqual(base20.decode('-31e'), -1234) + base20 = BaseConverter("0123456789abcdefghij") + self.assertEqual(base20.encode(1234), "31e") + self.assertEqual(base20.decode("31e"), 1234) + self.assertEqual(base20.encode(-1234), "-31e") + self.assertEqual(base20.decode("-31e"), -1234) def test_base64(self): - self.assertEqual(base64.encode(1234), 'JI') - self.assertEqual(base64.decode('JI'), 1234) - self.assertEqual(base64.encode(-1234), '$JI') - self.assertEqual(base64.decode('$JI'), -1234) + self.assertEqual(base64.encode(1234), "JI") + self.assertEqual(base64.decode("JI"), 1234) + self.assertEqual(base64.encode(-1234), "$JI") + self.assertEqual(base64.decode("$JI"), -1234) def test_base7(self): - base7 = BaseConverter('cjdhel3', sign='g') - self.assertEqual(base7.encode(1234), 'hejd') - self.assertEqual(base7.decode('hejd'), 1234) - self.assertEqual(base7.encode(-1234), 'ghejd') - self.assertEqual(base7.decode('ghejd'), -1234) + base7 = BaseConverter("cjdhel3", sign="g") + self.assertEqual(base7.encode(1234), "hejd") + self.assertEqual(base7.decode("hejd"), 1234) + self.assertEqual(base7.encode(-1234), "ghejd") + self.assertEqual(base7.decode("ghejd"), -1234) def test_exception(self): with self.assertRaises(ValueError): - BaseConverter('abc', sign='a') - self.assertIsInstance(BaseConverter('abc', sign='d'), BaseConverter) + BaseConverter("abc", sign="a") + self.assertIsInstance(BaseConverter("abc", sign="d"), BaseConverter) def test_repr(self): - base7 = BaseConverter('cjdhel3', sign='g') - self.assertEqual(repr(base7), '<BaseConverter: base7 (cjdhel3)>') + base7 = BaseConverter("cjdhel3", sign="g") + self.assertEqual(repr(base7), "<BaseConverter: base7 (cjdhel3)>") diff --git a/tests/utils_tests/test_connection.py b/tests/utils_tests/test_connection.py index d763e0824d..e7d63b8d0f 100644 --- a/tests/utils_tests/test_connection.py +++ b/tests/utils_tests/test_connection.py @@ -5,6 +5,6 @@ from django.utils.connection import BaseConnectionHandler class BaseConnectionHandlerTests(SimpleTestCase): def test_create_connection(self): handler = BaseConnectionHandler() - msg = 'Subclasses must implement create_connection().' + msg = "Subclasses must implement create_connection()." with self.assertRaisesMessage(NotImplementedError, msg): handler.create_connection(None) diff --git a/tests/utils_tests/test_crypto.py b/tests/utils_tests/test_crypto.py index d6e0774bf3..3310e9231c 100644 --- a/tests/utils_tests/test_crypto.py +++ b/tests/utils_tests/test_crypto.py @@ -3,47 +3,49 @@ import unittest from django.test import SimpleTestCase from django.utils.crypto import ( - InvalidAlgorithm, constant_time_compare, pbkdf2, salted_hmac, + InvalidAlgorithm, + constant_time_compare, + pbkdf2, + salted_hmac, ) class TestUtilsCryptoMisc(SimpleTestCase): - def test_constant_time_compare(self): # It's hard to test for constant time, just test the result. - self.assertTrue(constant_time_compare(b'spam', b'spam')) - self.assertFalse(constant_time_compare(b'spam', b'eggs')) - self.assertTrue(constant_time_compare('spam', 'spam')) - self.assertFalse(constant_time_compare('spam', 'eggs')) + self.assertTrue(constant_time_compare(b"spam", b"spam")) + self.assertFalse(constant_time_compare(b"spam", b"eggs")) + self.assertTrue(constant_time_compare("spam", "spam")) + self.assertFalse(constant_time_compare("spam", "eggs")) def test_salted_hmac(self): tests = [ - ((b'salt', b'value'), {}, 'b51a2e619c43b1ca4f91d15c57455521d71d61eb'), - (('salt', 'value'), {}, 'b51a2e619c43b1ca4f91d15c57455521d71d61eb'), + ((b"salt", b"value"), {}, "b51a2e619c43b1ca4f91d15c57455521d71d61eb"), + (("salt", "value"), {}, "b51a2e619c43b1ca4f91d15c57455521d71d61eb"), ( - ('salt', 'value'), - {'secret': 'abcdefg'}, - '8bbee04ccddfa24772d1423a0ba43bd0c0e24b76', + ("salt", "value"), + {"secret": "abcdefg"}, + "8bbee04ccddfa24772d1423a0ba43bd0c0e24b76", ), ( - ('salt', 'value'), - {'secret': 'x' * hashlib.sha1().block_size}, - 'bd3749347b412b1b0a9ea65220e55767ac8e96b0', + ("salt", "value"), + {"secret": "x" * hashlib.sha1().block_size}, + "bd3749347b412b1b0a9ea65220e55767ac8e96b0", ), ( - ('salt', 'value'), - {'algorithm': 'sha256'}, - 'ee0bf789e4e009371a5372c90f73fcf17695a8439c9108b0480f14e347b3f9ec', + ("salt", "value"), + {"algorithm": "sha256"}, + "ee0bf789e4e009371a5372c90f73fcf17695a8439c9108b0480f14e347b3f9ec", ), ( - ('salt', 'value'), + ("salt", "value"), { - 'algorithm': 'blake2b', - 'secret': 'x' * hashlib.blake2b().block_size, + "algorithm": "blake2b", + "secret": "x" * hashlib.blake2b().block_size, }, - 'fc6b9800a584d40732a07fa33fb69c35211269441823bca431a143853c32f' - 'e836cf19ab881689528ede647dac412170cd5d3407b44c6d0f44630690c54' - 'ad3d58', + "fc6b9800a584d40732a07fa33fb69c35211269441823bca431a143853c32f" + "e836cf19ab881689528ede647dac412170cd5d3407b44c6d0f44630690c54" + "ad3d58", ), ] for args, kwargs, digest in tests: @@ -53,7 +55,7 @@ class TestUtilsCryptoMisc(SimpleTestCase): def test_invalid_algorithm(self): msg = "'whatever' is not an algorithm accepted by the hashlib module." with self.assertRaisesMessage(InvalidAlgorithm, msg): - salted_hmac('salt', 'value', algorithm='whatever') + salted_hmac("salt", "value", algorithm="whatever") class TestUtilsCryptoPBKDF2(unittest.TestCase): @@ -152,34 +154,44 @@ class TestUtilsCryptoPBKDF2(unittest.TestCase): "dklen": 0, "digest": hashlib.sha512, }, - "result": ("afe6c5530785b6cc6b1c6453384731bd5ee432ee" - "549fd42fb6695779ad8a1c5bf59de69c48f774ef" - "c4007d5298f9033c0241d5ab69305e7b64eceeb8d" - "834cfec"), + "result": ( + "afe6c5530785b6cc6b1c6453384731bd5ee432ee" + "549fd42fb6695779ad8a1c5bf59de69c48f774ef" + "c4007d5298f9033c0241d5ab69305e7b64eceeb8d" + "834cfec" + ), }, # Check leading zeros are not stripped (#17481) { "args": { - "password": b'\xba', + "password": b"\xba", "salt": "salt", "iterations": 1, "dklen": 20, "digest": hashlib.sha1, }, - "result": '0053d3b91a7f1e54effebd6d68771e8a6e0b2c5b', + "result": "0053d3b91a7f1e54effebd6d68771e8a6e0b2c5b", }, ] def test_public_vectors(self): for vector in self.rfc_vectors: - result = pbkdf2(**vector['args']) - self.assertEqual(result.hex(), vector['result']) + result = pbkdf2(**vector["args"]) + self.assertEqual(result.hex(), vector["result"]) def test_regression_vectors(self): for vector in self.regression_vectors: - result = pbkdf2(**vector['args']) - self.assertEqual(result.hex(), vector['result']) + result = pbkdf2(**vector["args"]) + self.assertEqual(result.hex(), vector["result"]) def test_default_hmac_alg(self): - kwargs = {'password': b'password', 'salt': b'salt', 'iterations': 1, 'dklen': 20} - self.assertEqual(pbkdf2(**kwargs), hashlib.pbkdf2_hmac(hash_name=hashlib.sha256().name, **kwargs)) + kwargs = { + "password": b"password", + "salt": b"salt", + "iterations": 1, + "dklen": 20, + } + self.assertEqual( + pbkdf2(**kwargs), + hashlib.pbkdf2_hmac(hash_name=hashlib.sha256().name, **kwargs), + ) diff --git a/tests/utils_tests/test_datastructures.py b/tests/utils_tests/test_datastructures.py index 259ebb2f7b..cfa3d8f05c 100644 --- a/tests/utils_tests/test_datastructures.py +++ b/tests/utils_tests/test_datastructures.py @@ -7,13 +7,16 @@ import pickle from django.test import SimpleTestCase from django.utils.datastructures import ( - CaseInsensitiveMapping, DictWrapper, ImmutableList, MultiValueDict, - MultiValueDictKeyError, OrderedSet, + CaseInsensitiveMapping, + DictWrapper, + ImmutableList, + MultiValueDict, + MultiValueDictKeyError, + OrderedSet, ) class OrderedSetTests(SimpleTestCase): - def test_init_with_iterable(self): s = OrderedSet([1, 2, 3]) self.assertEqual(list(s.dict.keys()), [1, 2, 3]) @@ -61,80 +64,85 @@ class OrderedSetTests(SimpleTestCase): self.assertEqual(len(s), 2) def test_repr(self): - self.assertEqual(repr(OrderedSet()), 'OrderedSet()') - self.assertEqual(repr(OrderedSet([2, 3, 2, 1])), 'OrderedSet([2, 3, 1])') + self.assertEqual(repr(OrderedSet()), "OrderedSet()") + self.assertEqual(repr(OrderedSet([2, 3, 2, 1])), "OrderedSet([2, 3, 1])") class MultiValueDictTests(SimpleTestCase): - def test_repr(self): - d = MultiValueDict({'key': 'value'}) + d = MultiValueDict({"key": "value"}) self.assertEqual(repr(d), "<MultiValueDict: {'key': 'value'}>") def test_multivaluedict(self): - d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer'], 'empty': []}) - self.assertEqual(d['name'], 'Simon') - self.assertEqual(d.get('name'), 'Simon') - self.assertEqual(d.getlist('name'), ['Adrian', 'Simon']) + d = MultiValueDict( + {"name": ["Adrian", "Simon"], "position": ["Developer"], "empty": []} + ) + self.assertEqual(d["name"], "Simon") + self.assertEqual(d.get("name"), "Simon") + self.assertEqual(d.getlist("name"), ["Adrian", "Simon"]) self.assertEqual( list(d.items()), - [('name', 'Simon'), ('position', 'Developer'), ('empty', [])] + [("name", "Simon"), ("position", "Developer"), ("empty", [])], ) self.assertEqual( list(d.lists()), - [('name', ['Adrian', 'Simon']), ('position', ['Developer']), ('empty', [])] + [("name", ["Adrian", "Simon"]), ("position", ["Developer"]), ("empty", [])], ) with self.assertRaisesMessage(MultiValueDictKeyError, "'lastname'"): - d.__getitem__('lastname') - self.assertIsNone(d.get('empty')) - self.assertEqual(d.get('empty', 'nonexistent'), 'nonexistent') - self.assertIsNone(d.get('lastname')) - self.assertEqual(d.get('lastname', 'nonexistent'), 'nonexistent') - self.assertEqual(d.getlist('lastname'), []) - self.assertEqual(d.getlist('doesnotexist', ['Adrian', 'Simon']), ['Adrian', 'Simon']) - d.setlist('lastname', ['Holovaty', 'Willison']) - self.assertEqual(d.getlist('lastname'), ['Holovaty', 'Willison']) - self.assertEqual(list(d.values()), ['Simon', 'Developer', [], 'Willison']) + d.__getitem__("lastname") + self.assertIsNone(d.get("empty")) + self.assertEqual(d.get("empty", "nonexistent"), "nonexistent") + self.assertIsNone(d.get("lastname")) + self.assertEqual(d.get("lastname", "nonexistent"), "nonexistent") + self.assertEqual(d.getlist("lastname"), []) + self.assertEqual( + d.getlist("doesnotexist", ["Adrian", "Simon"]), ["Adrian", "Simon"] + ) + d.setlist("lastname", ["Holovaty", "Willison"]) + self.assertEqual(d.getlist("lastname"), ["Holovaty", "Willison"]) + self.assertEqual(list(d.values()), ["Simon", "Developer", [], "Willison"]) def test_appendlist(self): d = MultiValueDict() - d.appendlist('name', 'Adrian') - d.appendlist('name', 'Simon') - self.assertEqual(d.getlist('name'), ['Adrian', 'Simon']) + d.appendlist("name", "Adrian") + d.appendlist("name", "Simon") + self.assertEqual(d.getlist("name"), ["Adrian", "Simon"]) def test_copy(self): for copy_func in [copy.copy, lambda d: d.copy()]: with self.subTest(copy_func): - d1 = MultiValueDict({'developers': ['Carl', 'Fred']}) - self.assertEqual(d1['developers'], 'Fred') + d1 = MultiValueDict({"developers": ["Carl", "Fred"]}) + self.assertEqual(d1["developers"], "Fred") d2 = copy_func(d1) - d2.update({'developers': 'Groucho'}) - self.assertEqual(d2['developers'], 'Groucho') - self.assertEqual(d1['developers'], 'Fred') + d2.update({"developers": "Groucho"}) + self.assertEqual(d2["developers"], "Groucho") + self.assertEqual(d1["developers"], "Fred") - d1 = MultiValueDict({'key': [[]]}) - self.assertEqual(d1['key'], []) + d1 = MultiValueDict({"key": [[]]}) + self.assertEqual(d1["key"], []) d2 = copy_func(d1) - d2['key'].append('Penguin') - self.assertEqual(d1['key'], ['Penguin']) - self.assertEqual(d2['key'], ['Penguin']) + d2["key"].append("Penguin") + self.assertEqual(d1["key"], ["Penguin"]) + self.assertEqual(d2["key"], ["Penguin"]) def test_deepcopy(self): - d1 = MultiValueDict({'a': [[123]]}) + d1 = MultiValueDict({"a": [[123]]}) d2 = copy.copy(d1) d3 = copy.deepcopy(d1) - self.assertIs(d1['a'], d2['a']) - self.assertIsNot(d1['a'], d3['a']) + self.assertIs(d1["a"], d2["a"]) + self.assertIsNot(d1["a"], d3["a"]) def test_pickle(self): - x = MultiValueDict({'a': ['1', '2'], 'b': ['3']}) + x = MultiValueDict({"a": ["1", "2"], "b": ["3"]}) self.assertEqual(x, pickle.loads(pickle.dumps(x))) def test_dict_translation(self): - mvd = MultiValueDict({ - 'devs': ['Bob', 'Joe'], - 'pm': ['Rory'], - }) + mvd = MultiValueDict( + { + "devs": ["Bob", "Joe"], + "pm": ["Rory"], + } + ) d = mvd.dict() self.assertEqual(list(d), list(mvd)) for key in mvd: @@ -143,78 +151,78 @@ class MultiValueDictTests(SimpleTestCase): self.assertEqual({}, MultiValueDict().dict()) def test_getlist_doesnt_mutate(self): - x = MultiValueDict({'a': ['1', '2'], 'b': ['3']}) - values = x.getlist('a') - values += x.getlist('b') - self.assertEqual(x.getlist('a'), ['1', '2']) + x = MultiValueDict({"a": ["1", "2"], "b": ["3"]}) + values = x.getlist("a") + values += x.getlist("b") + self.assertEqual(x.getlist("a"), ["1", "2"]) def test_internal_getlist_does_mutate(self): - x = MultiValueDict({'a': ['1', '2'], 'b': ['3']}) - values = x._getlist('a') - values += x._getlist('b') - self.assertEqual(x._getlist('a'), ['1', '2', '3']) + x = MultiValueDict({"a": ["1", "2"], "b": ["3"]}) + values = x._getlist("a") + values += x._getlist("b") + self.assertEqual(x._getlist("a"), ["1", "2", "3"]) def test_getlist_default(self): - x = MultiValueDict({'a': [1]}) + x = MultiValueDict({"a": [1]}) MISSING = object() - values = x.getlist('b', default=MISSING) + values = x.getlist("b", default=MISSING) self.assertIs(values, MISSING) def test_getlist_none_empty_values(self): - x = MultiValueDict({'a': None, 'b': []}) - self.assertIsNone(x.getlist('a')) - self.assertEqual(x.getlist('b'), []) + x = MultiValueDict({"a": None, "b": []}) + self.assertIsNone(x.getlist("a")) + self.assertEqual(x.getlist("b"), []) def test_setitem(self): - x = MultiValueDict({'a': [1, 2]}) - x['a'] = 3 - self.assertEqual(list(x.lists()), [('a', [3])]) + x = MultiValueDict({"a": [1, 2]}) + x["a"] = 3 + self.assertEqual(list(x.lists()), [("a", [3])]) def test_setdefault(self): - x = MultiValueDict({'a': [1, 2]}) - a = x.setdefault('a', 3) - b = x.setdefault('b', 3) + x = MultiValueDict({"a": [1, 2]}) + a = x.setdefault("a", 3) + b = x.setdefault("b", 3) self.assertEqual(a, 2) self.assertEqual(b, 3) - self.assertEqual(list(x.lists()), [('a', [1, 2]), ('b', [3])]) + self.assertEqual(list(x.lists()), [("a", [1, 2]), ("b", [3])]) def test_update_too_many_args(self): - x = MultiValueDict({'a': []}) - msg = 'update expected at most 1 argument, got 2' + x = MultiValueDict({"a": []}) + msg = "update expected at most 1 argument, got 2" with self.assertRaisesMessage(TypeError, msg): x.update(1, 2) def test_update_no_args(self): - x = MultiValueDict({'a': []}) + x = MultiValueDict({"a": []}) x.update() - self.assertEqual(list(x.lists()), [('a', [])]) + self.assertEqual(list(x.lists()), [("a", [])]) def test_update_dict_arg(self): - x = MultiValueDict({'a': [1], 'b': [2], 'c': [3]}) - x.update({'a': 4, 'b': 5}) - self.assertEqual(list(x.lists()), [('a', [1, 4]), ('b', [2, 5]), ('c', [3])]) + x = MultiValueDict({"a": [1], "b": [2], "c": [3]}) + x.update({"a": 4, "b": 5}) + self.assertEqual(list(x.lists()), [("a", [1, 4]), ("b", [2, 5]), ("c", [3])]) def test_update_multivaluedict_arg(self): - x = MultiValueDict({'a': [1], 'b': [2], 'c': [3]}) - x.update(MultiValueDict({'a': [4], 'b': [5]})) - self.assertEqual(list(x.lists()), [('a', [1, 4]), ('b', [2, 5]), ('c', [3])]) + x = MultiValueDict({"a": [1], "b": [2], "c": [3]}) + x.update(MultiValueDict({"a": [4], "b": [5]})) + self.assertEqual(list(x.lists()), [("a", [1, 4]), ("b", [2, 5]), ("c", [3])]) def test_update_kwargs(self): - x = MultiValueDict({'a': [1], 'b': [2], 'c': [3]}) + x = MultiValueDict({"a": [1], "b": [2], "c": [3]}) x.update(a=4, b=5) - self.assertEqual(list(x.lists()), [('a', [1, 4]), ('b', [2, 5]), ('c', [3])]) + self.assertEqual(list(x.lists()), [("a", [1, 4]), ("b", [2, 5]), ("c", [3])]) def test_update_with_empty_iterable(self): - for value in ['', b'', (), [], set(), {}]: + for value in ["", b"", (), [], set(), {}]: d = MultiValueDict() d.update(value) self.assertEqual(d, MultiValueDict()) def test_update_with_iterable_of_pairs(self): - for value in [(('a', 1),), [('a', 1)], {('a', 1)}]: + for value in [(("a", 1),), [("a", 1)], {("a", 1)}]: d = MultiValueDict() d.update(value) - self.assertEqual(d, MultiValueDict({'a': [1]})) + self.assertEqual(d, MultiValueDict({"a": [1]})) def test_update_raises_correct_exceptions(self): # MultiValueDict.update() raises equivalent exceptions to @@ -224,26 +232,27 @@ class MultiValueDictTests(SimpleTestCase): with self.subTest(value), self.assertRaises(TypeError): MultiValueDict().update(value) # Iterables of objects that cannot be unpacked raise TypeError. - for value in [b'123', b'abc', (1, 2, 3), [1, 2, 3], {1, 2, 3}]: + for value in [b"123", b"abc", (1, 2, 3), [1, 2, 3], {1, 2, 3}]: with self.subTest(value), self.assertRaises(TypeError): MultiValueDict().update(value) # Iterables of unpackable objects with incorrect number of items raise # ValueError. - for value in ['123', 'abc', ('a', 'b', 'c'), ['a', 'b', 'c'], {'a', 'b', 'c'}]: + for value in ["123", "abc", ("a", "b", "c"), ["a", "b", "c"], {"a", "b", "c"}]: with self.subTest(value), self.assertRaises(ValueError): MultiValueDict().update(value) class ImmutableListTests(SimpleTestCase): - def test_sort(self): d = ImmutableList(range(10)) # AttributeError: ImmutableList object is immutable. - with self.assertRaisesMessage(AttributeError, 'ImmutableList object is immutable.'): + with self.assertRaisesMessage( + AttributeError, "ImmutableList object is immutable." + ): d.sort() - self.assertEqual(repr(d), '(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)') + self.assertEqual(repr(d), "(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)") def test_custom_warning(self): d = ImmutableList(range(10), warning="Object is immutable!") @@ -251,64 +260,72 @@ class ImmutableListTests(SimpleTestCase): self.assertEqual(d[1], 1) # AttributeError: Object is immutable! - with self.assertRaisesMessage(AttributeError, 'Object is immutable!'): - d.__setitem__(1, 'test') + with self.assertRaisesMessage(AttributeError, "Object is immutable!"): + d.__setitem__(1, "test") class DictWrapperTests(SimpleTestCase): - def test_dictwrapper(self): def f(x): return "*%s" % x - d = DictWrapper({'a': 'a'}, f, 'xx_') + + d = DictWrapper({"a": "a"}, f, "xx_") self.assertEqual( - "Normal: %(a)s. Modified: %(xx_a)s" % d, - 'Normal: a. Modified: *a' + "Normal: %(a)s. Modified: %(xx_a)s" % d, "Normal: a. Modified: *a" ) class CaseInsensitiveMappingTests(SimpleTestCase): def setUp(self): - self.dict1 = CaseInsensitiveMapping({ - 'Accept': 'application/json', - 'content-type': 'text/html', - }) + self.dict1 = CaseInsensitiveMapping( + { + "Accept": "application/json", + "content-type": "text/html", + } + ) def test_create_with_invalid_values(self): - msg = 'dictionary update sequence element #1 has length 4; 2 is required' + msg = "dictionary update sequence element #1 has length 4; 2 is required" with self.assertRaisesMessage(ValueError, msg): - CaseInsensitiveMapping([('Key1', 'Val1'), 'Key2']) + CaseInsensitiveMapping([("Key1", "Val1"), "Key2"]) def test_create_with_invalid_key(self): - msg = 'Element key 1 invalid, only strings are allowed' + msg = "Element key 1 invalid, only strings are allowed" with self.assertRaisesMessage(ValueError, msg): - CaseInsensitiveMapping([(1, '2')]) + CaseInsensitiveMapping([(1, "2")]) def test_list(self): - self.assertEqual(list(self.dict1), ['Accept', 'content-type']) + self.assertEqual(list(self.dict1), ["Accept", "content-type"]) def test_dict(self): - self.assertEqual(dict(self.dict1), {'Accept': 'application/json', 'content-type': 'text/html'}) + self.assertEqual( + dict(self.dict1), + {"Accept": "application/json", "content-type": "text/html"}, + ) def test_repr(self): - dict1 = CaseInsensitiveMapping({'Accept': 'application/json'}) - dict2 = CaseInsensitiveMapping({'content-type': 'text/html'}) - self.assertEqual(repr(dict1), repr({'Accept': 'application/json'})) - self.assertEqual(repr(dict2), repr({'content-type': 'text/html'})) + dict1 = CaseInsensitiveMapping({"Accept": "application/json"}) + dict2 = CaseInsensitiveMapping({"content-type": "text/html"}) + self.assertEqual(repr(dict1), repr({"Accept": "application/json"})) + self.assertEqual(repr(dict2), repr({"content-type": "text/html"})) def test_str(self): - dict1 = CaseInsensitiveMapping({'Accept': 'application/json'}) - dict2 = CaseInsensitiveMapping({'content-type': 'text/html'}) - self.assertEqual(str(dict1), str({'Accept': 'application/json'})) - self.assertEqual(str(dict2), str({'content-type': 'text/html'})) + dict1 = CaseInsensitiveMapping({"Accept": "application/json"}) + dict2 = CaseInsensitiveMapping({"content-type": "text/html"}) + self.assertEqual(str(dict1), str({"Accept": "application/json"})) + self.assertEqual(str(dict2), str({"content-type": "text/html"})) def test_equal(self): - self.assertEqual(self.dict1, {'Accept': 'application/json', 'content-type': 'text/html'}) - self.assertNotEqual(self.dict1, {'accept': 'application/jso', 'Content-Type': 'text/html'}) - self.assertNotEqual(self.dict1, 'string') + self.assertEqual( + self.dict1, {"Accept": "application/json", "content-type": "text/html"} + ) + self.assertNotEqual( + self.dict1, {"accept": "application/jso", "Content-Type": "text/html"} + ) + self.assertNotEqual(self.dict1, "string") def test_items(self): - other = {'Accept': 'application/json', 'content-type': 'text/html'} + other = {"Accept": "application/json", "content-type": "text/html"} self.assertEqual(sorted(self.dict1.items()), sorted(other.items())) def test_copy(self): @@ -317,30 +334,30 @@ class CaseInsensitiveMappingTests(SimpleTestCase): self.assertEqual(copy, self.dict1) def test_getitem(self): - self.assertEqual(self.dict1['Accept'], 'application/json') - self.assertEqual(self.dict1['accept'], 'application/json') - self.assertEqual(self.dict1['aCCept'], 'application/json') - self.assertEqual(self.dict1['content-type'], 'text/html') - self.assertEqual(self.dict1['Content-Type'], 'text/html') - self.assertEqual(self.dict1['Content-type'], 'text/html') + self.assertEqual(self.dict1["Accept"], "application/json") + self.assertEqual(self.dict1["accept"], "application/json") + self.assertEqual(self.dict1["aCCept"], "application/json") + self.assertEqual(self.dict1["content-type"], "text/html") + self.assertEqual(self.dict1["Content-Type"], "text/html") + self.assertEqual(self.dict1["Content-type"], "text/html") def test_in(self): - self.assertIn('Accept', self.dict1) - self.assertIn('accept', self.dict1) - self.assertIn('aCCept', self.dict1) - self.assertIn('content-type', self.dict1) - self.assertIn('Content-Type', self.dict1) + self.assertIn("Accept", self.dict1) + self.assertIn("accept", self.dict1) + self.assertIn("aCCept", self.dict1) + self.assertIn("content-type", self.dict1) + self.assertIn("Content-Type", self.dict1) def test_del(self): - self.assertIn('Accept', self.dict1) + self.assertIn("Accept", self.dict1) msg = "'CaseInsensitiveMapping' object does not support item deletion" with self.assertRaisesMessage(TypeError, msg): - del self.dict1['Accept'] - self.assertIn('Accept', self.dict1) + del self.dict1["Accept"] + self.assertIn("Accept", self.dict1) def test_set(self): self.assertEqual(len(self.dict1), 2) msg = "'CaseInsensitiveMapping' object does not support item assignment" with self.assertRaisesMessage(TypeError, msg): - self.dict1['New Key'] = 1 + self.dict1["New Key"] = 1 self.assertEqual(len(self.dict1), 2) diff --git a/tests/utils_tests/test_dateformat.py b/tests/utils_tests/test_dateformat.py index b2bb0c2e19..4e4926c85b 100644 --- a/tests/utils_tests/test_dateformat.py +++ b/tests/utils_tests/test_dateformat.py @@ -5,27 +5,29 @@ from django.test.utils import TZ_SUPPORT, requires_tz_support from django.utils import dateformat, translation from django.utils.dateformat import format from django.utils.timezone import ( - get_default_timezone, get_fixed_timezone, make_aware, utc, + get_default_timezone, + get_fixed_timezone, + make_aware, + utc, ) -@override_settings(TIME_ZONE='Europe/Copenhagen') +@override_settings(TIME_ZONE="Europe/Copenhagen") class DateFormatTests(SimpleTestCase): - def setUp(self): self._orig_lang = translation.get_language() - translation.activate('en-us') + translation.activate("en-us") def tearDown(self): translation.activate(self._orig_lang) def test_date(self): d = date(2009, 5, 16) - self.assertEqual(date.fromtimestamp(int(format(d, 'U'))), d) + self.assertEqual(date.fromtimestamp(int(format(d, "U"))), d) def test_naive_datetime(self): dt = datetime(2009, 5, 16, 5, 30, 30) - self.assertEqual(datetime.fromtimestamp(int(format(dt, 'U'))), dt) + self.assertEqual(datetime.fromtimestamp(int(format(dt, "U"))), dt) def test_naive_ambiguous_datetime(self): # dt is ambiguous in Europe/Copenhagen. pytz raises an exception for @@ -33,99 +35,112 @@ class DateFormatTests(SimpleTestCase): dt = datetime(2015, 10, 25, 2, 30, 0) # Try all formatters that involve self.timezone. - self.assertEqual(format(dt, 'I'), '') - self.assertEqual(format(dt, 'O'), '') - self.assertEqual(format(dt, 'T'), '') - self.assertEqual(format(dt, 'Z'), '') + self.assertEqual(format(dt, "I"), "") + self.assertEqual(format(dt, "O"), "") + self.assertEqual(format(dt, "T"), "") + self.assertEqual(format(dt, "Z"), "") @requires_tz_support def test_datetime_with_local_tzinfo(self): ltz = get_default_timezone() dt = make_aware(datetime(2009, 5, 16, 5, 30, 30), ltz) - self.assertEqual(datetime.fromtimestamp(int(format(dt, 'U')), ltz), dt) - self.assertEqual(datetime.fromtimestamp(int(format(dt, 'U'))), dt.replace(tzinfo=None)) + self.assertEqual(datetime.fromtimestamp(int(format(dt, "U")), ltz), dt) + self.assertEqual( + datetime.fromtimestamp(int(format(dt, "U"))), dt.replace(tzinfo=None) + ) @requires_tz_support def test_datetime_with_tzinfo(self): tz = get_fixed_timezone(-510) ltz = get_default_timezone() dt = make_aware(datetime(2009, 5, 16, 5, 30, 30), ltz) - self.assertEqual(datetime.fromtimestamp(int(format(dt, 'U')), tz), dt) - self.assertEqual(datetime.fromtimestamp(int(format(dt, 'U')), ltz), dt) + self.assertEqual(datetime.fromtimestamp(int(format(dt, "U")), tz), dt) + self.assertEqual(datetime.fromtimestamp(int(format(dt, "U")), ltz), dt) # astimezone() is safe here because the target timezone doesn't have DST - self.assertEqual(datetime.fromtimestamp(int(format(dt, 'U'))), dt.astimezone(ltz).replace(tzinfo=None)) - self.assertEqual(datetime.fromtimestamp(int(format(dt, 'U')), tz).timetuple(), dt.astimezone(tz).timetuple()) - self.assertEqual(datetime.fromtimestamp(int(format(dt, 'U')), ltz).timetuple(), dt.astimezone(ltz).timetuple()) + self.assertEqual( + datetime.fromtimestamp(int(format(dt, "U"))), + dt.astimezone(ltz).replace(tzinfo=None), + ) + self.assertEqual( + datetime.fromtimestamp(int(format(dt, "U")), tz).timetuple(), + dt.astimezone(tz).timetuple(), + ) + self.assertEqual( + datetime.fromtimestamp(int(format(dt, "U")), ltz).timetuple(), + dt.astimezone(ltz).timetuple(), + ) def test_epoch(self): udt = datetime(1970, 1, 1, tzinfo=utc) - self.assertEqual(format(udt, 'U'), '0') + self.assertEqual(format(udt, "U"), "0") def test_empty_format(self): my_birthday = datetime(1979, 7, 8, 22, 00) - self.assertEqual(dateformat.format(my_birthday, ''), '') + self.assertEqual(dateformat.format(my_birthday, ""), "") def test_am_pm(self): morning = time(7, 00) evening = time(19, 00) - self.assertEqual(dateformat.format(morning, 'a'), 'a.m.') - self.assertEqual(dateformat.format(evening, 'a'), 'p.m.') - self.assertEqual(dateformat.format(morning, 'A'), 'AM') - self.assertEqual(dateformat.format(evening, 'A'), 'PM') + self.assertEqual(dateformat.format(morning, "a"), "a.m.") + self.assertEqual(dateformat.format(evening, "a"), "p.m.") + self.assertEqual(dateformat.format(morning, "A"), "AM") + self.assertEqual(dateformat.format(evening, "A"), "PM") def test_microsecond(self): # Regression test for #18951 dt = datetime(2009, 5, 16, microsecond=123) - self.assertEqual(dateformat.format(dt, 'u'), '000123') + self.assertEqual(dateformat.format(dt, "u"), "000123") def test_date_formats(self): # Specifiers 'I', 'r', and 'U' are covered in test_timezones(). my_birthday = datetime(1979, 7, 8, 22, 00) for specifier, expected in [ - ('b', 'jul'), - ('d', '08'), - ('D', 'Sun'), - ('E', 'July'), - ('F', 'July'), - ('j', '8'), - ('l', 'Sunday'), - ('L', 'False'), - ('m', '07'), - ('M', 'Jul'), - ('n', '7'), - ('N', 'July'), - ('o', '1979'), - ('S', 'th'), - ('t', '31'), - ('w', '0'), - ('W', '27'), - ('y', '79'), - ('Y', '1979'), - ('z', '189'), + ("b", "jul"), + ("d", "08"), + ("D", "Sun"), + ("E", "July"), + ("F", "July"), + ("j", "8"), + ("l", "Sunday"), + ("L", "False"), + ("m", "07"), + ("M", "Jul"), + ("n", "7"), + ("N", "July"), + ("o", "1979"), + ("S", "th"), + ("t", "31"), + ("w", "0"), + ("W", "27"), + ("y", "79"), + ("Y", "1979"), + ("z", "189"), ]: with self.subTest(specifier=specifier): self.assertEqual(dateformat.format(my_birthday, specifier), expected) def test_date_formats_c_format(self): timestamp = datetime(2008, 5, 19, 11, 45, 23, 123456) - self.assertEqual(dateformat.format(timestamp, 'c'), '2008-05-19T11:45:23.123456') + self.assertEqual( + dateformat.format(timestamp, "c"), "2008-05-19T11:45:23.123456" + ) def test_time_formats(self): # Specifiers 'I', 'r', and 'U' are covered in test_timezones(). my_birthday = datetime(1979, 7, 8, 22, 00) for specifier, expected in [ - ('a', 'p.m.'), - ('A', 'PM'), - ('f', '10'), - ('g', '10'), - ('G', '22'), - ('h', '10'), - ('H', '22'), - ('i', '00'), - ('P', '10 p.m.'), - ('s', '00'), - ('u', '000000'), + ("a", "p.m."), + ("A", "PM"), + ("f", "10"), + ("g", "10"), + ("G", "22"), + ("h", "10"), + ("H", "22"), + ("i", "00"), + ("P", "10 p.m."), + ("s", "00"), + ("u", "000000"), ]: with self.subTest(specifier=specifier): self.assertEqual(dateformat.format(my_birthday, specifier), expected) @@ -133,16 +148,16 @@ class DateFormatTests(SimpleTestCase): def test_dateformat(self): my_birthday = datetime(1979, 7, 8, 22, 00) - self.assertEqual(dateformat.format(my_birthday, r'Y z \C\E\T'), '1979 189 CET') + self.assertEqual(dateformat.format(my_birthday, r"Y z \C\E\T"), "1979 189 CET") - self.assertEqual(dateformat.format(my_birthday, r'jS \o\f F'), '8th of July') + self.assertEqual(dateformat.format(my_birthday, r"jS \o\f F"), "8th of July") def test_futuredates(self): the_future = datetime(2100, 10, 25, 0, 00) - self.assertEqual(dateformat.format(the_future, r'Y'), '2100') + self.assertEqual(dateformat.format(the_future, r"Y"), "2100") def test_day_of_year_leap(self): - self.assertEqual(dateformat.format(datetime(2000, 12, 31), 'z'), '366') + self.assertEqual(dateformat.format(datetime(2000, 12, 31), "z"), "366") def test_timezones(self): my_birthday = datetime(1979, 7, 8, 22, 00) @@ -156,43 +171,45 @@ class DateFormatTests(SimpleTestCase): if TZ_SUPPORT: for specifier, expected in [ - ('e', ''), - ('O', '+0100'), - ('r', 'Sun, 08 Jul 1979 22:00:00 +0100'), - ('T', 'CET'), - ('U', '300315600'), - ('Z', '3600'), + ("e", ""), + ("O", "+0100"), + ("r", "Sun, 08 Jul 1979 22:00:00 +0100"), + ("T", "CET"), + ("U", "300315600"), + ("Z", "3600"), ]: with self.subTest(specifier=specifier): - self.assertEqual(dateformat.format(my_birthday, specifier), expected) + self.assertEqual( + dateformat.format(my_birthday, specifier), expected + ) - self.assertEqual(dateformat.format(aware_dt, 'e'), '-0330') + self.assertEqual(dateformat.format(aware_dt, "e"), "-0330") self.assertEqual( - dateformat.format(aware_dt, 'r'), - 'Sat, 16 May 2009 05:30:30 -0330', + dateformat.format(aware_dt, "r"), + "Sat, 16 May 2009 05:30:30 -0330", ) - self.assertEqual(dateformat.format(summertime, 'I'), '1') - self.assertEqual(dateformat.format(summertime, 'O'), '+0200') + self.assertEqual(dateformat.format(summertime, "I"), "1") + self.assertEqual(dateformat.format(summertime, "O"), "+0200") - self.assertEqual(dateformat.format(wintertime, 'I'), '0') - self.assertEqual(dateformat.format(wintertime, 'O'), '+0100') + self.assertEqual(dateformat.format(wintertime, "I"), "0") + self.assertEqual(dateformat.format(wintertime, "O"), "+0100") - for specifier in ['e', 'O', 'T', 'Z']: + for specifier in ["e", "O", "T", "Z"]: with self.subTest(specifier=specifier): - self.assertEqual(dateformat.time_format(noon, specifier), '') + self.assertEqual(dateformat.time_format(noon, specifier), "") # Ticket #16924 -- We don't need timezone support to test this - self.assertEqual(dateformat.format(aware_dt, 'O'), '-0330') + self.assertEqual(dateformat.format(aware_dt, "O"), "-0330") def test_invalid_time_format_specifiers(self): my_birthday = date(1984, 8, 7) - for specifier in ['a', 'A', 'f', 'g', 'G', 'h', 'H', 'i', 'P', 'r', 's', 'u']: + for specifier in ["a", "A", "f", "g", "G", "h", "H", "i", "P", "r", "s", "u"]: with self.subTest(specifier=specifier): msg = ( - 'The format for date objects may not contain time-related ' - f'format specifiers (found {specifier!r}).' + "The format for date objects may not contain time-related " + f"format specifiers (found {specifier!r})." ) with self.assertRaisesMessage(TypeError, msg): dateformat.format(my_birthday, specifier) @@ -200,79 +217,80 @@ class DateFormatTests(SimpleTestCase): @requires_tz_support def test_e_format_with_named_time_zone(self): dt = datetime(1970, 1, 1, tzinfo=utc) - self.assertEqual(dateformat.format(dt, 'e'), 'UTC') + self.assertEqual(dateformat.format(dt, "e"), "UTC") @requires_tz_support def test_e_format_with_time_zone_with_unimplemented_tzname(self): class NoNameTZ(tzinfo): """Time zone without .tzname() defined.""" + def utcoffset(self, dt): return None dt = datetime(1970, 1, 1, tzinfo=NoNameTZ()) - self.assertEqual(dateformat.format(dt, 'e'), '') + self.assertEqual(dateformat.format(dt, "e"), "") def test_P_format(self): for expected, t in [ - ('midnight', time(0)), - ('noon', time(12)), - ('4 a.m.', time(4)), - ('8:30 a.m.', time(8, 30)), - ('4 p.m.', time(16)), - ('8:30 p.m.', time(20, 30)), + ("midnight", time(0)), + ("noon", time(12)), + ("4 a.m.", time(4)), + ("8:30 a.m.", time(8, 30)), + ("4 p.m.", time(16)), + ("8:30 p.m.", time(20, 30)), ]: with self.subTest(time=t): - self.assertEqual(dateformat.time_format(t, 'P'), expected) + self.assertEqual(dateformat.time_format(t, "P"), expected) def test_r_format_with_non_en_locale(self): # Changing the locale doesn't change the "r" format. dt = datetime(1979, 7, 8, 22, 00) - with translation.override('fr'): + with translation.override("fr"): self.assertEqual( - dateformat.format(dt, 'r'), - 'Sun, 08 Jul 1979 22:00:00 +0100', + dateformat.format(dt, "r"), + "Sun, 08 Jul 1979 22:00:00 +0100", ) def test_S_format(self): for expected, days in [ - ('st', [1, 21, 31]), - ('nd', [2, 22]), - ('rd', [3, 23]), - ('th', (n for n in range(4, 31) if n not in [21, 22, 23])), + ("st", [1, 21, 31]), + ("nd", [2, 22]), + ("rd", [3, 23]), + ("th", (n for n in range(4, 31) if n not in [21, 22, 23])), ]: for day in days: dt = date(1970, 1, day) with self.subTest(day=day): - self.assertEqual(dateformat.format(dt, 'S'), expected) + self.assertEqual(dateformat.format(dt, "S"), expected) def test_y_format_year_before_1000(self): tests = [ - (476, '76'), - (42, '42'), - (4, '04'), + (476, "76"), + (42, "42"), + (4, "04"), ] for year, expected_date in tests: with self.subTest(year=year): self.assertEqual( - dateformat.format(datetime(year, 9, 8, 5, 0), 'y'), + dateformat.format(datetime(year, 9, 8, 5, 0), "y"), expected_date, ) def test_Y_format_year_before_1000(self): - self.assertEqual(dateformat.format(datetime(1, 1, 1), 'Y'), '0001') - self.assertEqual(dateformat.format(datetime(999, 1, 1), 'Y'), '0999') + self.assertEqual(dateformat.format(datetime(1, 1, 1), "Y"), "0001") + self.assertEqual(dateformat.format(datetime(999, 1, 1), "Y"), "0999") def test_twelve_hour_format(self): tests = [ - (0, '12', '12'), - (1, '1', '01'), - (11, '11', '11'), - (12, '12', '12'), - (13, '1', '01'), - (23, '11', '11'), + (0, "12", "12"), + (1, "1", "01"), + (11, "11", "11"), + (12, "12", "12"), + (13, "1", "01"), + (23, "11", "11"), ] for hour, g_expected, h_expected in tests: dt = datetime(2000, 1, 1, hour) with self.subTest(hour=hour): - self.assertEqual(dateformat.format(dt, 'g'), g_expected) - self.assertEqual(dateformat.format(dt, 'h'), h_expected) + self.assertEqual(dateformat.format(dt, "g"), g_expected) + self.assertEqual(dateformat.format(dt, "h"), h_expected) diff --git a/tests/utils_tests/test_dateparse.py b/tests/utils_tests/test_dateparse.py index f2f66f351d..d010adce9b 100644 --- a/tests/utils_tests/test_dateparse.py +++ b/tests/utils_tests/test_dateparse.py @@ -2,70 +2,100 @@ import unittest from datetime import date, datetime, time, timedelta from django.utils.dateparse import ( - parse_date, parse_datetime, parse_duration, parse_time, + parse_date, + parse_datetime, + parse_duration, + parse_time, ) from django.utils.timezone import get_fixed_timezone class DateParseTests(unittest.TestCase): - def test_parse_date(self): # Valid inputs - self.assertEqual(parse_date('2012-04-23'), date(2012, 4, 23)) - self.assertEqual(parse_date('2012-4-9'), date(2012, 4, 9)) + self.assertEqual(parse_date("2012-04-23"), date(2012, 4, 23)) + self.assertEqual(parse_date("2012-4-9"), date(2012, 4, 9)) # Invalid inputs - self.assertIsNone(parse_date('20120423')) + self.assertIsNone(parse_date("20120423")) with self.assertRaises(ValueError): - parse_date('2012-04-56') + parse_date("2012-04-56") def test_parse_time(self): # Valid inputs - self.assertEqual(parse_time('09:15:00'), time(9, 15)) - self.assertEqual(parse_time('10:10'), time(10, 10)) - self.assertEqual(parse_time('10:20:30.400'), time(10, 20, 30, 400000)) - self.assertEqual(parse_time('10:20:30,400'), time(10, 20, 30, 400000)) - self.assertEqual(parse_time('4:8:16'), time(4, 8, 16)) + self.assertEqual(parse_time("09:15:00"), time(9, 15)) + self.assertEqual(parse_time("10:10"), time(10, 10)) + self.assertEqual(parse_time("10:20:30.400"), time(10, 20, 30, 400000)) + self.assertEqual(parse_time("10:20:30,400"), time(10, 20, 30, 400000)) + self.assertEqual(parse_time("4:8:16"), time(4, 8, 16)) # Time zone offset is ignored. - self.assertEqual(parse_time('00:05:23+04:00'), time(0, 5, 23)) + self.assertEqual(parse_time("00:05:23+04:00"), time(0, 5, 23)) # Invalid inputs - self.assertIsNone(parse_time('00:05:')) - self.assertIsNone(parse_time('00:05:23,')) - self.assertIsNone(parse_time('00:05:23+')) - self.assertIsNone(parse_time('00:05:23+25:00')) - self.assertIsNone(parse_time('4:18:101')) - self.assertIsNone(parse_time('091500')) + self.assertIsNone(parse_time("00:05:")) + self.assertIsNone(parse_time("00:05:23,")) + self.assertIsNone(parse_time("00:05:23+")) + self.assertIsNone(parse_time("00:05:23+25:00")) + self.assertIsNone(parse_time("4:18:101")) + self.assertIsNone(parse_time("091500")) with self.assertRaises(ValueError): - parse_time('09:15:90') + parse_time("09:15:90") def test_parse_datetime(self): valid_inputs = ( - ('2012-04-23T09:15:00', datetime(2012, 4, 23, 9, 15)), - ('2012-4-9 4:8:16', datetime(2012, 4, 9, 4, 8, 16)), - ('2012-04-23T09:15:00Z', datetime(2012, 4, 23, 9, 15, 0, 0, get_fixed_timezone(0))), - ('2012-4-9 4:8:16-0320', datetime(2012, 4, 9, 4, 8, 16, 0, get_fixed_timezone(-200))), - ('2012-04-23T10:20:30.400+02:30', datetime(2012, 4, 23, 10, 20, 30, 400000, get_fixed_timezone(150))), - ('2012-04-23T10:20:30.400+02', datetime(2012, 4, 23, 10, 20, 30, 400000, get_fixed_timezone(120))), - ('2012-04-23T10:20:30.400-02', datetime(2012, 4, 23, 10, 20, 30, 400000, get_fixed_timezone(-120))), - ('2012-04-23T10:20:30,400-02', datetime(2012, 4, 23, 10, 20, 30, 400000, get_fixed_timezone(-120))), - ('2012-04-23T10:20:30.400 +0230', datetime(2012, 4, 23, 10, 20, 30, 400000, get_fixed_timezone(150))), - ('2012-04-23T10:20:30,400 +00', datetime(2012, 4, 23, 10, 20, 30, 400000, get_fixed_timezone(0))), - ('2012-04-23T10:20:30 -02', datetime(2012, 4, 23, 10, 20, 30, 0, get_fixed_timezone(-120))), + ("2012-04-23T09:15:00", datetime(2012, 4, 23, 9, 15)), + ("2012-4-9 4:8:16", datetime(2012, 4, 9, 4, 8, 16)), + ( + "2012-04-23T09:15:00Z", + datetime(2012, 4, 23, 9, 15, 0, 0, get_fixed_timezone(0)), + ), + ( + "2012-4-9 4:8:16-0320", + datetime(2012, 4, 9, 4, 8, 16, 0, get_fixed_timezone(-200)), + ), + ( + "2012-04-23T10:20:30.400+02:30", + datetime(2012, 4, 23, 10, 20, 30, 400000, get_fixed_timezone(150)), + ), + ( + "2012-04-23T10:20:30.400+02", + datetime(2012, 4, 23, 10, 20, 30, 400000, get_fixed_timezone(120)), + ), + ( + "2012-04-23T10:20:30.400-02", + datetime(2012, 4, 23, 10, 20, 30, 400000, get_fixed_timezone(-120)), + ), + ( + "2012-04-23T10:20:30,400-02", + datetime(2012, 4, 23, 10, 20, 30, 400000, get_fixed_timezone(-120)), + ), + ( + "2012-04-23T10:20:30.400 +0230", + datetime(2012, 4, 23, 10, 20, 30, 400000, get_fixed_timezone(150)), + ), + ( + "2012-04-23T10:20:30,400 +00", + datetime(2012, 4, 23, 10, 20, 30, 400000, get_fixed_timezone(0)), + ), + ( + "2012-04-23T10:20:30 -02", + datetime(2012, 4, 23, 10, 20, 30, 0, get_fixed_timezone(-120)), + ), ) for source, expected in valid_inputs: with self.subTest(source=source): self.assertEqual(parse_datetime(source), expected) # Invalid inputs - self.assertIsNone(parse_datetime('20120423091500')) + self.assertIsNone(parse_datetime("20120423091500")) with self.assertRaises(ValueError): - parse_datetime('2012-04-56T09:15:90') + parse_datetime("2012-04-56T09:15:90") class DurationParseTests(unittest.TestCase): - def test_parse_python_format(self): timedeltas = [ - timedelta(days=4, minutes=15, seconds=30, milliseconds=100), # fractions of seconds + timedelta( + days=4, minutes=15, seconds=30, milliseconds=100 + ), # fractions of seconds timedelta(hours=10, minutes=15, seconds=30), # hours, minutes, seconds timedelta(days=4, minutes=15, seconds=30), # multiple days timedelta(days=1, minutes=00, seconds=00), # single day @@ -79,45 +109,63 @@ class DurationParseTests(unittest.TestCase): def test_parse_postgresql_format(self): test_values = ( - ('1 day', timedelta(1)), - ('-1 day', timedelta(-1)), - ('1 day 0:00:01', timedelta(days=1, seconds=1)), - ('1 day -0:00:01', timedelta(days=1, seconds=-1)), - ('-1 day -0:00:01', timedelta(days=-1, seconds=-1)), - ('-1 day +0:00:01', timedelta(days=-1, seconds=1)), - ('4 days 0:15:30.1', timedelta(days=4, minutes=15, seconds=30, milliseconds=100)), - ('4 days 0:15:30.0001', timedelta(days=4, minutes=15, seconds=30, microseconds=100)), - ('-4 days -15:00:30', timedelta(days=-4, hours=-15, seconds=-30)), + ("1 day", timedelta(1)), + ("-1 day", timedelta(-1)), + ("1 day 0:00:01", timedelta(days=1, seconds=1)), + ("1 day -0:00:01", timedelta(days=1, seconds=-1)), + ("-1 day -0:00:01", timedelta(days=-1, seconds=-1)), + ("-1 day +0:00:01", timedelta(days=-1, seconds=1)), + ( + "4 days 0:15:30.1", + timedelta(days=4, minutes=15, seconds=30, milliseconds=100), + ), + ( + "4 days 0:15:30.0001", + timedelta(days=4, minutes=15, seconds=30, microseconds=100), + ), + ("-4 days -15:00:30", timedelta(days=-4, hours=-15, seconds=-30)), ) for source, expected in test_values: with self.subTest(source=source): self.assertEqual(parse_duration(source), expected) def test_seconds(self): - self.assertEqual(parse_duration('30'), timedelta(seconds=30)) + self.assertEqual(parse_duration("30"), timedelta(seconds=30)) def test_minutes_seconds(self): - self.assertEqual(parse_duration('15:30'), timedelta(minutes=15, seconds=30)) - self.assertEqual(parse_duration('5:30'), timedelta(minutes=5, seconds=30)) + self.assertEqual(parse_duration("15:30"), timedelta(minutes=15, seconds=30)) + self.assertEqual(parse_duration("5:30"), timedelta(minutes=5, seconds=30)) def test_hours_minutes_seconds(self): - self.assertEqual(parse_duration('10:15:30'), timedelta(hours=10, minutes=15, seconds=30)) - self.assertEqual(parse_duration('1:15:30'), timedelta(hours=1, minutes=15, seconds=30)) - self.assertEqual(parse_duration('100:200:300'), timedelta(hours=100, minutes=200, seconds=300)) + self.assertEqual( + parse_duration("10:15:30"), timedelta(hours=10, minutes=15, seconds=30) + ) + self.assertEqual( + parse_duration("1:15:30"), timedelta(hours=1, minutes=15, seconds=30) + ) + self.assertEqual( + parse_duration("100:200:300"), + timedelta(hours=100, minutes=200, seconds=300), + ) def test_days(self): - self.assertEqual(parse_duration('4 15:30'), timedelta(days=4, minutes=15, seconds=30)) - self.assertEqual(parse_duration('4 10:15:30'), timedelta(days=4, hours=10, minutes=15, seconds=30)) + self.assertEqual( + parse_duration("4 15:30"), timedelta(days=4, minutes=15, seconds=30) + ) + self.assertEqual( + parse_duration("4 10:15:30"), + timedelta(days=4, hours=10, minutes=15, seconds=30), + ) def test_fractions_of_seconds(self): test_values = ( - ('15:30.1', timedelta(minutes=15, seconds=30, milliseconds=100)), - ('15:30.01', timedelta(minutes=15, seconds=30, milliseconds=10)), - ('15:30.001', timedelta(minutes=15, seconds=30, milliseconds=1)), - ('15:30.0001', timedelta(minutes=15, seconds=30, microseconds=100)), - ('15:30.00001', timedelta(minutes=15, seconds=30, microseconds=10)), - ('15:30.000001', timedelta(minutes=15, seconds=30, microseconds=1)), - ('15:30,000001', timedelta(minutes=15, seconds=30, microseconds=1)), + ("15:30.1", timedelta(minutes=15, seconds=30, milliseconds=100)), + ("15:30.01", timedelta(minutes=15, seconds=30, milliseconds=10)), + ("15:30.001", timedelta(minutes=15, seconds=30, milliseconds=1)), + ("15:30.0001", timedelta(minutes=15, seconds=30, microseconds=100)), + ("15:30.00001", timedelta(minutes=15, seconds=30, microseconds=10)), + ("15:30.000001", timedelta(minutes=15, seconds=30, microseconds=1)), + ("15:30,000001", timedelta(minutes=15, seconds=30, microseconds=1)), ) for source, expected in test_values: with self.subTest(source=source): @@ -125,15 +173,15 @@ class DurationParseTests(unittest.TestCase): def test_negative(self): test_values = ( - ('-4 15:30', timedelta(days=-4, minutes=15, seconds=30)), - ('-172800', timedelta(days=-2)), - ('-15:30', timedelta(minutes=-15, seconds=-30)), - ('-1:15:30', timedelta(hours=-1, minutes=-15, seconds=-30)), - ('-30.1', timedelta(seconds=-30, milliseconds=-100)), - ('-30,1', timedelta(seconds=-30, milliseconds=-100)), - ('-00:01:01', timedelta(minutes=-1, seconds=-1)), - ('-01:01', timedelta(seconds=-61)), - ('-01:-01', None), + ("-4 15:30", timedelta(days=-4, minutes=15, seconds=30)), + ("-172800", timedelta(days=-2)), + ("-15:30", timedelta(minutes=-15, seconds=-30)), + ("-1:15:30", timedelta(hours=-1, minutes=-15, seconds=-30)), + ("-30.1", timedelta(seconds=-30, milliseconds=-100)), + ("-30,1", timedelta(seconds=-30, milliseconds=-100)), + ("-00:01:01", timedelta(minutes=-1, seconds=-1)), + ("-01:01", timedelta(seconds=-61)), + ("-01:-01", None), ) for source, expected in test_values: with self.subTest(source=source): @@ -141,31 +189,31 @@ class DurationParseTests(unittest.TestCase): def test_iso_8601(self): test_values = ( - ('P4Y', None), - ('P4M', None), - ('P4W', None), - ('P4D', timedelta(days=4)), - ('-P1D', timedelta(days=-1)), - ('P0.5D', timedelta(hours=12)), - ('P0,5D', timedelta(hours=12)), - ('-P0.5D', timedelta(hours=-12)), - ('-P0,5D', timedelta(hours=-12)), - ('PT5H', timedelta(hours=5)), - ('-PT5H', timedelta(hours=-5)), - ('PT5M', timedelta(minutes=5)), - ('-PT5M', timedelta(minutes=-5)), - ('PT5S', timedelta(seconds=5)), - ('-PT5S', timedelta(seconds=-5)), - ('PT0.000005S', timedelta(microseconds=5)), - ('PT0,000005S', timedelta(microseconds=5)), - ('-PT0.000005S', timedelta(microseconds=-5)), - ('-PT0,000005S', timedelta(microseconds=-5)), - ('-P4DT1H', timedelta(days=-4, hours=-1)), + ("P4Y", None), + ("P4M", None), + ("P4W", None), + ("P4D", timedelta(days=4)), + ("-P1D", timedelta(days=-1)), + ("P0.5D", timedelta(hours=12)), + ("P0,5D", timedelta(hours=12)), + ("-P0.5D", timedelta(hours=-12)), + ("-P0,5D", timedelta(hours=-12)), + ("PT5H", timedelta(hours=5)), + ("-PT5H", timedelta(hours=-5)), + ("PT5M", timedelta(minutes=5)), + ("-PT5M", timedelta(minutes=-5)), + ("PT5S", timedelta(seconds=5)), + ("-PT5S", timedelta(seconds=-5)), + ("PT0.000005S", timedelta(microseconds=5)), + ("PT0,000005S", timedelta(microseconds=5)), + ("-PT0.000005S", timedelta(microseconds=-5)), + ("-PT0,000005S", timedelta(microseconds=-5)), + ("-P4DT1H", timedelta(days=-4, hours=-1)), # Invalid separators for decimal fractions. - ('P3(3D', None), - ('PT3)3H', None), - ('PT3|3M', None), - ('PT3/3S', None), + ("P3(3D", None), + ("PT3)3H", None), + ("PT3|3M", None), + ("PT3/3S", None), ) for source, expected in test_values: with self.subTest(source=source): diff --git a/tests/utils_tests/test_datetime_safe.py b/tests/utils_tests/test_datetime_safe.py index b5ee3d0cad..cb987319f4 100644 --- a/tests/utils_tests/test_datetime_safe.py +++ b/tests/utils_tests/test_datetime_safe.py @@ -1,4 +1,5 @@ -from datetime import date as original_date, datetime as original_datetime +from datetime import date as original_date +from datetime import datetime as original_datetime from django.test import SimpleTestCase, ignore_warnings from django.utils.deprecation import RemovedInDjango50Warning @@ -8,7 +9,6 @@ with ignore_warnings(category=RemovedInDjango50Warning): class DatetimeTests(SimpleTestCase): - def setUp(self): self.percent_y_safe = (1900, 1, 1) # >= 1900 required on Windows. self.just_safe = (1000, 1, 1) @@ -17,36 +17,54 @@ class DatetimeTests(SimpleTestCase): self.more_recent = (2006, 1, 1) def test_compare_datetimes(self): - self.assertEqual(original_datetime(*self.more_recent), datetime(*self.more_recent)) - self.assertEqual(original_datetime(*self.really_old), datetime(*self.really_old)) + self.assertEqual( + original_datetime(*self.more_recent), datetime(*self.more_recent) + ) + self.assertEqual( + original_datetime(*self.really_old), datetime(*self.really_old) + ) self.assertEqual(original_date(*self.more_recent), date(*self.more_recent)) self.assertEqual(original_date(*self.really_old), date(*self.really_old)) self.assertEqual( - original_date(*self.just_safe).strftime('%Y-%m-%d'), date(*self.just_safe).strftime('%Y-%m-%d') + original_date(*self.just_safe).strftime("%Y-%m-%d"), + date(*self.just_safe).strftime("%Y-%m-%d"), ) self.assertEqual( - original_datetime(*self.just_safe).strftime('%Y-%m-%d'), datetime(*self.just_safe).strftime('%Y-%m-%d') + original_datetime(*self.just_safe).strftime("%Y-%m-%d"), + datetime(*self.just_safe).strftime("%Y-%m-%d"), ) def test_safe_strftime(self): - self.assertEqual(date(*self.just_unsafe[:3]).strftime('%Y-%m-%d (weekday %w)'), '0999-12-31 (weekday 2)') - self.assertEqual(date(*self.just_safe).strftime('%Y-%m-%d (weekday %w)'), '1000-01-01 (weekday 3)') + self.assertEqual( + date(*self.just_unsafe[:3]).strftime("%Y-%m-%d (weekday %w)"), + "0999-12-31 (weekday 2)", + ) + self.assertEqual( + date(*self.just_safe).strftime("%Y-%m-%d (weekday %w)"), + "1000-01-01 (weekday 3)", + ) self.assertEqual( - datetime(*self.just_unsafe).strftime('%Y-%m-%d %H:%M:%S (weekday %w)'), '0999-12-31 23:59:59 (weekday 2)' + datetime(*self.just_unsafe).strftime("%Y-%m-%d %H:%M:%S (weekday %w)"), + "0999-12-31 23:59:59 (weekday 2)", ) self.assertEqual( - datetime(*self.just_safe).strftime('%Y-%m-%d %H:%M:%S (weekday %w)'), '1000-01-01 00:00:00 (weekday 3)' + datetime(*self.just_safe).strftime("%Y-%m-%d %H:%M:%S (weekday %w)"), + "1000-01-01 00:00:00 (weekday 3)", ) # %y will error before this date - self.assertEqual(date(*self.percent_y_safe).strftime('%y'), '00') - self.assertEqual(datetime(*self.percent_y_safe).strftime('%y'), '00') - with self.assertRaisesMessage(TypeError, 'strftime of dates before 1000 does not handle %y'): - datetime(*self.just_unsafe).strftime('%y') + self.assertEqual(date(*self.percent_y_safe).strftime("%y"), "00") + self.assertEqual(datetime(*self.percent_y_safe).strftime("%y"), "00") + with self.assertRaisesMessage( + TypeError, "strftime of dates before 1000 does not handle %y" + ): + datetime(*self.just_unsafe).strftime("%y") - self.assertEqual(date(1850, 8, 2).strftime("%Y/%m/%d was a %A"), '1850/08/02 was a Friday') + self.assertEqual( + date(1850, 8, 2).strftime("%Y/%m/%d was a %A"), "1850/08/02 was a Friday" + ) def test_zero_padding(self): """ @@ -54,4 +72,6 @@ class DatetimeTests(SimpleTestCase): Pre-1000AD dates are padded with zeros if necessary """ - self.assertEqual(date(1, 1, 1).strftime("%Y/%m/%d was a %A"), '0001/01/01 was a Monday') + self.assertEqual( + date(1, 1, 1).strftime("%Y/%m/%d was a %A"), "0001/01/01 was a Monday" + ) diff --git a/tests/utils_tests/test_deconstruct.py b/tests/utils_tests/test_deconstruct.py index f384ab8288..e90ff32676 100644 --- a/tests/utils_tests/test_deconstruct.py +++ b/tests/utils_tests/test_deconstruct.py @@ -13,7 +13,7 @@ class DeconstructibleChildClass(DeconstructibleClass): @deconstructible( - path='utils_tests.deconstructible_classes.DeconstructibleWithPathClass' + path="utils_tests.deconstructible_classes.DeconstructibleWithPathClass" ) class DeconstructibleWithPathClass: pass @@ -24,7 +24,7 @@ class DeconstructibleWithPathChildClass(DeconstructibleWithPathClass): @deconstructible( - path='utils_tests.deconstructible_classes.DeconstructibleInvalidPathClass', + path="utils_tests.deconstructible_classes.DeconstructibleInvalidPathClass", ) class DeconstructibleInvalidPathClass: pass @@ -36,61 +36,61 @@ class DeconstructibleInvalidPathChildClass(DeconstructibleInvalidPathClass): class DeconstructibleTests(SimpleTestCase): def test_deconstruct(self): - obj = DeconstructibleClass('arg', key='value') + obj = DeconstructibleClass("arg", key="value") path, args, kwargs = obj.deconstruct() - self.assertEqual(path, 'utils_tests.test_deconstruct.DeconstructibleClass') - self.assertEqual(args, ('arg',)) - self.assertEqual(kwargs, {'key': 'value'}) + self.assertEqual(path, "utils_tests.test_deconstruct.DeconstructibleClass") + self.assertEqual(args, ("arg",)) + self.assertEqual(kwargs, {"key": "value"}) def test_deconstruct_with_path(self): - obj = DeconstructibleWithPathClass('arg', key='value') + obj = DeconstructibleWithPathClass("arg", key="value") path, args, kwargs = obj.deconstruct() self.assertEqual( path, - 'utils_tests.deconstructible_classes.DeconstructibleWithPathClass', + "utils_tests.deconstructible_classes.DeconstructibleWithPathClass", ) - self.assertEqual(args, ('arg',)) - self.assertEqual(kwargs, {'key': 'value'}) + self.assertEqual(args, ("arg",)) + self.assertEqual(kwargs, {"key": "value"}) def test_deconstruct_child(self): - obj = DeconstructibleChildClass('arg', key='value') + obj = DeconstructibleChildClass("arg", key="value") path, args, kwargs = obj.deconstruct() - self.assertEqual(path, 'utils_tests.test_deconstruct.DeconstructibleChildClass') - self.assertEqual(args, ('arg',)) - self.assertEqual(kwargs, {'key': 'value'}) + self.assertEqual(path, "utils_tests.test_deconstruct.DeconstructibleChildClass") + self.assertEqual(args, ("arg",)) + self.assertEqual(kwargs, {"key": "value"}) def test_deconstruct_child_with_path(self): - obj = DeconstructibleWithPathChildClass('arg', key='value') + obj = DeconstructibleWithPathChildClass("arg", key="value") path, args, kwargs = obj.deconstruct() self.assertEqual( path, - 'utils_tests.test_deconstruct.DeconstructibleWithPathChildClass', + "utils_tests.test_deconstruct.DeconstructibleWithPathChildClass", ) - self.assertEqual(args, ('arg',)) - self.assertEqual(kwargs, {'key': 'value'}) + self.assertEqual(args, ("arg",)) + self.assertEqual(kwargs, {"key": "value"}) def test_invalid_path(self): obj = DeconstructibleInvalidPathClass() docs_version = get_docs_version() msg = ( - f'Could not find object DeconstructibleInvalidPathClass in ' - f'utils_tests.deconstructible_classes.\n' - f'Please note that you cannot serialize things like inner ' - f'classes. Please move the object into the main module body to ' - f'use migrations.\n' - f'For more information, see ' - f'https://docs.djangoproject.com/en/{docs_version}/topics/' - f'migrations/#serializing-values' + f"Could not find object DeconstructibleInvalidPathClass in " + f"utils_tests.deconstructible_classes.\n" + f"Please note that you cannot serialize things like inner " + f"classes. Please move the object into the main module body to " + f"use migrations.\n" + f"For more information, see " + f"https://docs.djangoproject.com/en/{docs_version}/topics/" + f"migrations/#serializing-values" ) with self.assertRaisesMessage(ValueError, msg): obj.deconstruct() def test_parent_invalid_path(self): - obj = DeconstructibleInvalidPathChildClass('arg', key='value') + obj = DeconstructibleInvalidPathChildClass("arg", key="value") path, args, kwargs = obj.deconstruct() self.assertEqual( path, - 'utils_tests.test_deconstruct.DeconstructibleInvalidPathChildClass', + "utils_tests.test_deconstruct.DeconstructibleInvalidPathChildClass", ) - self.assertEqual(args, ('arg',)) - self.assertEqual(kwargs, {'key': 'value'}) + self.assertEqual(args, ("arg",)) + self.assertEqual(kwargs, {"key": "value"}) diff --git a/tests/utils_tests/test_decorators.py b/tests/utils_tests/test_decorators.py index 4cd8320d0b..8c0244e819 100644 --- a/tests/utils_tests/test_decorators.py +++ b/tests/utils_tests/test_decorators.py @@ -58,59 +58,62 @@ class DecoratorFromMiddlewareTests(SimpleTestCase): Tests for view decorators created using ``django.utils.decorators.decorator_from_middleware``. """ + rf = RequestFactory() def test_process_view_middleware(self): """ Test a middleware that implements process_view. """ - process_view(self.rf.get('/')) + process_view(self.rf.get("/")) def test_callable_process_view_middleware(self): """ Test a middleware that implements process_view, operating on a callable class. """ - class_process_view(self.rf.get('/')) + class_process_view(self.rf.get("/")) def test_full_dec_normal(self): """ All methods of middleware are called for normal HttpResponses """ + @full_dec def normal_view(request): - template = engines['django'].from_string("Hello world") + template = engines["django"].from_string("Hello world") return HttpResponse(template.render()) - request = self.rf.get('/') + request = self.rf.get("/") normal_view(request) - self.assertTrue(getattr(request, 'process_request_reached', False)) - self.assertTrue(getattr(request, 'process_view_reached', False)) + self.assertTrue(getattr(request, "process_request_reached", False)) + self.assertTrue(getattr(request, "process_view_reached", False)) # process_template_response must not be called for HttpResponse - self.assertFalse(getattr(request, 'process_template_response_reached', False)) - self.assertTrue(getattr(request, 'process_response_reached', False)) + self.assertFalse(getattr(request, "process_template_response_reached", False)) + self.assertTrue(getattr(request, "process_response_reached", False)) def test_full_dec_templateresponse(self): """ All methods of middleware are called for TemplateResponses in the right sequence. """ + @full_dec def template_response_view(request): - template = engines['django'].from_string("Hello world") + template = engines["django"].from_string("Hello world") return TemplateResponse(request, template) - request = self.rf.get('/') + request = self.rf.get("/") response = template_response_view(request) - self.assertTrue(getattr(request, 'process_request_reached', False)) - self.assertTrue(getattr(request, 'process_view_reached', False)) - self.assertTrue(getattr(request, 'process_template_response_reached', False)) + self.assertTrue(getattr(request, "process_request_reached", False)) + self.assertTrue(getattr(request, "process_view_reached", False)) + self.assertTrue(getattr(request, "process_template_response_reached", False)) # response must not be rendered yet. self.assertFalse(response._is_rendered) # process_response must not be called until after response is rendered, # otherwise some decorators like csrf_protect and gzip_page will not # work correctly. See #16004 - self.assertFalse(getattr(request, 'process_response_reached', False)) + self.assertFalse(getattr(request, "process_response_reached", False)) response.render() - self.assertTrue(getattr(request, 'process_response_reached', False)) + self.assertTrue(getattr(request, "process_response_reached", False)) # process_response saw the rendered content self.assertEqual(request.process_response_content, b"Hello world") diff --git a/tests/utils_tests/test_duration.py b/tests/utils_tests/test_duration.py index 84a3a0893f..fc6cbc3362 100644 --- a/tests/utils_tests/test_duration.py +++ b/tests/utils_tests/test_duration.py @@ -3,31 +3,31 @@ import unittest from django.utils.dateparse import parse_duration from django.utils.duration import ( - duration_iso_string, duration_microseconds, duration_string, + duration_iso_string, + duration_microseconds, + duration_string, ) class TestDurationString(unittest.TestCase): - def test_simple(self): duration = datetime.timedelta(hours=1, minutes=3, seconds=5) - self.assertEqual(duration_string(duration), '01:03:05') + self.assertEqual(duration_string(duration), "01:03:05") def test_days(self): duration = datetime.timedelta(days=1, hours=1, minutes=3, seconds=5) - self.assertEqual(duration_string(duration), '1 01:03:05') + self.assertEqual(duration_string(duration), "1 01:03:05") def test_microseconds(self): duration = datetime.timedelta(hours=1, minutes=3, seconds=5, microseconds=12345) - self.assertEqual(duration_string(duration), '01:03:05.012345') + self.assertEqual(duration_string(duration), "01:03:05.012345") def test_negative(self): duration = datetime.timedelta(days=-1, hours=1, minutes=3, seconds=5) - self.assertEqual(duration_string(duration), '-1 01:03:05') + self.assertEqual(duration_string(duration), "-1 01:03:05") class TestParseDurationRoundtrip(unittest.TestCase): - def test_simple(self): duration = datetime.timedelta(hours=1, minutes=3, seconds=5) self.assertEqual(parse_duration(duration_string(duration)), duration) @@ -46,26 +46,24 @@ class TestParseDurationRoundtrip(unittest.TestCase): class TestISODurationString(unittest.TestCase): - def test_simple(self): duration = datetime.timedelta(hours=1, minutes=3, seconds=5) - self.assertEqual(duration_iso_string(duration), 'P0DT01H03M05S') + self.assertEqual(duration_iso_string(duration), "P0DT01H03M05S") def test_days(self): duration = datetime.timedelta(days=1, hours=1, minutes=3, seconds=5) - self.assertEqual(duration_iso_string(duration), 'P1DT01H03M05S') + self.assertEqual(duration_iso_string(duration), "P1DT01H03M05S") def test_microseconds(self): duration = datetime.timedelta(hours=1, minutes=3, seconds=5, microseconds=12345) - self.assertEqual(duration_iso_string(duration), 'P0DT01H03M05.012345S') + self.assertEqual(duration_iso_string(duration), "P0DT01H03M05.012345S") def test_negative(self): duration = -1 * datetime.timedelta(days=1, hours=1, minutes=3, seconds=5) - self.assertEqual(duration_iso_string(duration), '-P1DT01H03M05S') + self.assertEqual(duration_iso_string(duration), "-P1DT01H03M05S") class TestParseISODurationRoundtrip(unittest.TestCase): - def test_simple(self): duration = datetime.timedelta(hours=1, minutes=3, seconds=5) self.assertEqual(parse_duration(duration_iso_string(duration)), duration) @@ -80,7 +78,10 @@ class TestParseISODurationRoundtrip(unittest.TestCase): def test_negative(self): duration = datetime.timedelta(days=-1, hours=1, minutes=3, seconds=5) - self.assertEqual(parse_duration(duration_iso_string(duration)).total_seconds(), duration.total_seconds()) + self.assertEqual( + parse_duration(duration_iso_string(duration)).total_seconds(), + duration.total_seconds(), + ) class TestDurationMicroseconds(unittest.TestCase): @@ -94,4 +95,6 @@ class TestDurationMicroseconds(unittest.TestCase): ] for delta in deltas: with self.subTest(delta=delta): - self.assertEqual(datetime.timedelta(microseconds=duration_microseconds(delta)), delta) + self.assertEqual( + datetime.timedelta(microseconds=duration_microseconds(delta)), delta + ) diff --git a/tests/utils_tests/test_encoding.py b/tests/utils_tests/test_encoding.py index 36f2d8665f..8dddd4e250 100644 --- a/tests/utils_tests/test_encoding.py +++ b/tests/utils_tests/test_encoding.py @@ -7,9 +7,17 @@ from urllib.parse import quote_plus from django.test import SimpleTestCase from django.utils.encoding import ( - DjangoUnicodeDecodeError, escape_uri_path, filepath_to_uri, force_bytes, - force_str, get_system_encoding, iri_to_uri, repercent_broken_unicode, - smart_bytes, smart_str, uri_to_iri, + DjangoUnicodeDecodeError, + escape_uri_path, + filepath_to_uri, + force_bytes, + force_str, + get_system_encoding, + iri_to_uri, + repercent_broken_unicode, + smart_bytes, + smart_str, + uri_to_iri, ) from django.utils.functional import SimpleLazyObject from django.utils.translation import gettext_lazy @@ -20,16 +28,17 @@ class TestEncodingUtils(SimpleTestCase): """ Broken __str__ actually raises an error. """ + class MyString: def __str__(self): - return b'\xc3\xb6\xc3\xa4\xc3\xbc' + return b"\xc3\xb6\xc3\xa4\xc3\xbc" # str(s) raises a TypeError if the result is not a text type. with self.assertRaises(TypeError): force_str(MyString()) def test_force_str_lazy(self): - s = SimpleLazyObject(lambda: 'x') + s = SimpleLazyObject(lambda: "x") self.assertIs(type(force_str(s)), str) def test_force_str_DjangoUnicodeDecodeError(self): @@ -38,7 +47,7 @@ class TestEncodingUtils(SimpleTestCase): "start byte. You passed in b'\\xff' (<class 'bytes'>)" ) with self.assertRaisesMessage(DjangoUnicodeDecodeError, msg): - force_str(b'\xff') + force_str(b"\xff") def test_force_bytes_exception(self): """ @@ -48,19 +57,22 @@ class TestEncodingUtils(SimpleTestCase): error_msg = "This is an exception, voilà" exc = ValueError(error_msg) self.assertEqual(force_bytes(exc), error_msg.encode()) - self.assertEqual(force_bytes(exc, encoding='ascii', errors='ignore'), b'This is an exception, voil') + self.assertEqual( + force_bytes(exc, encoding="ascii", errors="ignore"), + b"This is an exception, voil", + ) def test_force_bytes_strings_only(self): today = datetime.date.today() self.assertEqual(force_bytes(today, strings_only=True), today) def test_force_bytes_encoding(self): - error_msg = 'This is an exception, voilà'.encode() - result = force_bytes(error_msg, encoding='ascii', errors='ignore') - self.assertEqual(result, b'This is an exception, voil') + error_msg = "This is an exception, voilà".encode() + result = force_bytes(error_msg, encoding="ascii", errors="ignore") + self.assertEqual(result, b"This is an exception, voil") def test_force_bytes_memory_view(self): - data = b'abc' + data = b"abc" result = force_bytes(memoryview(data)) # Type check is needed because memoryview(bytes) == bytes. self.assertIs(type(result), bytes) @@ -69,58 +81,69 @@ class TestEncodingUtils(SimpleTestCase): def test_smart_bytes(self): class Test: def __str__(self): - return 'ŠĐĆŽćžšđ' + return "ŠĐĆŽćžšđ" - lazy_func = gettext_lazy('x') + lazy_func = gettext_lazy("x") self.assertIs(smart_bytes(lazy_func), lazy_func) - self.assertEqual(smart_bytes(Test()), b'\xc5\xa0\xc4\x90\xc4\x86\xc5\xbd\xc4\x87\xc5\xbe\xc5\xa1\xc4\x91') - self.assertEqual(smart_bytes(1), b'1') - self.assertEqual(smart_bytes('foo'), b'foo') + self.assertEqual( + smart_bytes(Test()), + b"\xc5\xa0\xc4\x90\xc4\x86\xc5\xbd\xc4\x87\xc5\xbe\xc5\xa1\xc4\x91", + ) + self.assertEqual(smart_bytes(1), b"1") + self.assertEqual(smart_bytes("foo"), b"foo") def test_smart_str(self): class Test: def __str__(self): - return 'ŠĐĆŽćžšđ' + return "ŠĐĆŽćžšđ" - lazy_func = gettext_lazy('x') + lazy_func = gettext_lazy("x") self.assertIs(smart_str(lazy_func), lazy_func) - self.assertEqual(smart_str(Test()), '\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111') - self.assertEqual(smart_str(1), '1') - self.assertEqual(smart_str('foo'), 'foo') + self.assertEqual( + smart_str(Test()), "\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" + ) + self.assertEqual(smart_str(1), "1") + self.assertEqual(smart_str("foo"), "foo") def test_get_default_encoding(self): - with mock.patch('locale.getdefaultlocale', side_effect=Exception): - self.assertEqual(get_system_encoding(), 'ascii') + with mock.patch("locale.getdefaultlocale", side_effect=Exception): + self.assertEqual(get_system_encoding(), "ascii") def test_repercent_broken_unicode_recursion_error(self): # Prepare a string long enough to force a recursion error if the tested # function uses recursion. - data = b'\xfc' * sys.getrecursionlimit() + data = b"\xfc" * sys.getrecursionlimit() try: - self.assertEqual(repercent_broken_unicode(data), b'%FC' * sys.getrecursionlimit()) + self.assertEqual( + repercent_broken_unicode(data), b"%FC" * sys.getrecursionlimit() + ) except RecursionError: - self.fail('Unexpected RecursionError raised.') + self.fail("Unexpected RecursionError raised.") class TestRFC3987IEncodingUtils(unittest.TestCase): - def test_filepath_to_uri(self): self.assertIsNone(filepath_to_uri(None)) - self.assertEqual(filepath_to_uri('upload\\чубака.mp4'), 'upload/%D1%87%D1%83%D0%B1%D0%B0%D0%BA%D0%B0.mp4') - self.assertEqual(filepath_to_uri(Path('upload/test.png')), 'upload/test.png') - self.assertEqual(filepath_to_uri(Path('upload\\test.png')), 'upload/test.png') + self.assertEqual( + filepath_to_uri("upload\\чубака.mp4"), + "upload/%D1%87%D1%83%D0%B1%D0%B0%D0%BA%D0%B0.mp4", + ) + self.assertEqual(filepath_to_uri(Path("upload/test.png")), "upload/test.png") + self.assertEqual(filepath_to_uri(Path("upload\\test.png")), "upload/test.png") def test_iri_to_uri(self): cases = [ # Valid UTF-8 sequences are encoded. - ('red%09rosé#red', 'red%09ros%C3%A9#red'), - ('/blog/for/Jürgen Münster/', '/blog/for/J%C3%BCrgen%20M%C3%BCnster/'), - ('locations/%s' % quote_plus('Paris & Orléans'), 'locations/Paris+%26+Orl%C3%A9ans'), - + ("red%09rosé#red", "red%09ros%C3%A9#red"), + ("/blog/for/Jürgen Münster/", "/blog/for/J%C3%BCrgen%20M%C3%BCnster/"), + ( + "locations/%s" % quote_plus("Paris & Orléans"), + "locations/Paris+%26+Orl%C3%A9ans", + ), # Reserved chars remain unescaped. - ('%&', '%&'), - ('red&♥ros%#red', 'red&%E2%99%A5ros%#red'), - (gettext_lazy('red&♥ros%#red'), 'red&%E2%99%A5ros%#red'), + ("%&", "%&"), + ("red&♥ros%#red", "red&%E2%99%A5ros%#red"), + (gettext_lazy("red&♥ros%#red"), "red&%E2%99%A5ros%#red"), ] for iri, uri in cases: @@ -134,17 +157,20 @@ class TestRFC3987IEncodingUtils(unittest.TestCase): cases = [ (None, None), # Valid UTF-8 sequences are decoded. - ('/%e2%89%Ab%E2%99%a5%E2%89%aB/', '/≫♥≫/'), - ('/%E2%99%A5%E2%99%A5/?utf8=%E2%9C%93', '/♥♥/?utf8=✓'), - ('/%41%5a%6B/', '/AZk/'), + ("/%e2%89%Ab%E2%99%a5%E2%89%aB/", "/≫♥≫/"), + ("/%E2%99%A5%E2%99%A5/?utf8=%E2%9C%93", "/♥♥/?utf8=✓"), + ("/%41%5a%6B/", "/AZk/"), # Reserved and non-URL valid ASCII chars are not decoded. - ('/%25%20%02%41%7b/', '/%25%20%02A%7b/'), + ("/%25%20%02%41%7b/", "/%25%20%02A%7b/"), # Broken UTF-8 sequences remain escaped. - ('/%AAd%AAj%AAa%AAn%AAg%AAo%AA/', '/%AAd%AAj%AAa%AAn%AAg%AAo%AA/'), - ('/%E2%99%A5%E2%E2%99%A5/', '/♥%E2♥/'), - ('/%E2%99%A5%E2%99%E2%99%A5/', '/♥%E2%99♥/'), - ('/%E2%E2%99%A5%E2%99%A5%99/', '/%E2♥♥%99/'), - ('/%E2%99%A5%E2%99%A5/?utf8=%9C%93%E2%9C%93%9C%93', '/♥♥/?utf8=%9C%93✓%9C%93'), + ("/%AAd%AAj%AAa%AAn%AAg%AAo%AA/", "/%AAd%AAj%AAa%AAn%AAg%AAo%AA/"), + ("/%E2%99%A5%E2%E2%99%A5/", "/♥%E2♥/"), + ("/%E2%99%A5%E2%99%E2%99%A5/", "/♥%E2%99♥/"), + ("/%E2%E2%99%A5%E2%99%A5%99/", "/%E2♥♥%99/"), + ( + "/%E2%99%A5%E2%99%A5/?utf8=%9C%93%E2%9C%93%9C%93", + "/♥♥/?utf8=%9C%93✓%9C%93", + ), ] for uri, iri in cases: @@ -156,17 +182,23 @@ class TestRFC3987IEncodingUtils(unittest.TestCase): def test_complementarity(self): cases = [ - ('/blog/for/J%C3%BCrgen%20M%C3%BCnster/', '/blog/for/J\xfcrgen%20M\xfcnster/'), - ('%&', '%&'), - ('red&%E2%99%A5ros%#red', 'red&♥ros%#red'), - ('/%E2%99%A5%E2%99%A5/', '/♥♥/'), - ('/%E2%99%A5%E2%99%A5/?utf8=%E2%9C%93', '/♥♥/?utf8=✓'), - ('/%25%20%02%7b/', '/%25%20%02%7b/'), - ('/%AAd%AAj%AAa%AAn%AAg%AAo%AA/', '/%AAd%AAj%AAa%AAn%AAg%AAo%AA/'), - ('/%E2%99%A5%E2%E2%99%A5/', '/♥%E2♥/'), - ('/%E2%99%A5%E2%99%E2%99%A5/', '/♥%E2%99♥/'), - ('/%E2%E2%99%A5%E2%99%A5%99/', '/%E2♥♥%99/'), - ('/%E2%99%A5%E2%99%A5/?utf8=%9C%93%E2%9C%93%9C%93', '/♥♥/?utf8=%9C%93✓%9C%93'), + ( + "/blog/for/J%C3%BCrgen%20M%C3%BCnster/", + "/blog/for/J\xfcrgen%20M\xfcnster/", + ), + ("%&", "%&"), + ("red&%E2%99%A5ros%#red", "red&♥ros%#red"), + ("/%E2%99%A5%E2%99%A5/", "/♥♥/"), + ("/%E2%99%A5%E2%99%A5/?utf8=%E2%9C%93", "/♥♥/?utf8=✓"), + ("/%25%20%02%7b/", "/%25%20%02%7b/"), + ("/%AAd%AAj%AAa%AAn%AAg%AAo%AA/", "/%AAd%AAj%AAa%AAn%AAg%AAo%AA/"), + ("/%E2%99%A5%E2%E2%99%A5/", "/♥%E2♥/"), + ("/%E2%99%A5%E2%99%E2%99%A5/", "/♥%E2%99♥/"), + ("/%E2%E2%99%A5%E2%99%A5%99/", "/%E2♥♥%99/"), + ( + "/%E2%99%A5%E2%99%A5/?utf8=%9C%93%E2%9C%93%9C%93", + "/♥♥/?utf8=%9C%93✓%9C%93", + ), ] for uri, iri in cases: @@ -177,11 +209,11 @@ class TestRFC3987IEncodingUtils(unittest.TestCase): def test_escape_uri_path(self): cases = [ ( - '/;some/=awful/?path/:with/@lots/&of/+awful/chars', - '/%3Bsome/%3Dawful/%3Fpath/:with/@lots/&of/+awful/chars', + "/;some/=awful/?path/:with/@lots/&of/+awful/chars", + "/%3Bsome/%3Dawful/%3Fpath/:with/@lots/&of/+awful/chars", ), - ('/foo#bar', '/foo%23bar'), - ('/foo?bar', '/foo%3Fbar'), + ("/foo#bar", "/foo%23bar"), + ("/foo?bar", "/foo%3Fbar"), ] for uri, expected in cases: with self.subTest(uri): diff --git a/tests/utils_tests/test_feedgenerator.py b/tests/utils_tests/test_feedgenerator.py index 3847637aba..90deb2ddf2 100644 --- a/tests/utils_tests/test_feedgenerator.py +++ b/tests/utils_tests/test_feedgenerator.py @@ -15,8 +15,11 @@ class FeedgeneratorTests(SimpleTestCase): get_tag_uri() correctly generates TagURIs. """ self.assertEqual( - feedgenerator.get_tag_uri('http://example.org/foo/bar#headline', datetime.date(2004, 10, 25)), - 'tag:example.org,2004-10-25:/foo/bar/headline') + feedgenerator.get_tag_uri( + "http://example.org/foo/bar#headline", datetime.date(2004, 10, 25) + ), + "tag:example.org,2004-10-25:/foo/bar/headline", + ) def test_get_tag_uri_with_port(self): """ @@ -24,10 +27,11 @@ class FeedgeneratorTests(SimpleTestCase): """ self.assertEqual( feedgenerator.get_tag_uri( - 'http://www.example.org:8000/2008/11/14/django#headline', + "http://www.example.org:8000/2008/11/14/django#headline", datetime.datetime(2008, 11, 14, 13, 37, 0), ), - 'tag:www.example.org,2008-11-14:/2008/11/14/django/headline') + "tag:www.example.org,2008-11-14:/2008/11/14/django/headline", + ) def test_rfc2822_date(self): """ @@ -35,7 +39,7 @@ class FeedgeneratorTests(SimpleTestCase): """ self.assertEqual( feedgenerator.rfc2822_date(datetime.datetime(2008, 11, 14, 13, 37, 0)), - "Fri, 14 Nov 2008 13:37:00 -0000" + "Fri, 14 Nov 2008 13:37:00 -0000", ) def test_rfc2822_date_with_timezone(self): @@ -43,8 +47,12 @@ class FeedgeneratorTests(SimpleTestCase): rfc2822_date() correctly formats datetime objects with tzinfo. """ self.assertEqual( - feedgenerator.rfc2822_date(datetime.datetime(2008, 11, 14, 13, 37, 0, tzinfo=get_fixed_timezone(60))), - "Fri, 14 Nov 2008 13:37:00 +0100" + feedgenerator.rfc2822_date( + datetime.datetime( + 2008, 11, 14, 13, 37, 0, tzinfo=get_fixed_timezone(60) + ) + ), + "Fri, 14 Nov 2008 13:37:00 +0100", ) def test_rfc2822_date_without_time(self): @@ -53,7 +61,7 @@ class FeedgeneratorTests(SimpleTestCase): """ self.assertEqual( feedgenerator.rfc2822_date(datetime.date(2008, 11, 14)), - "Fri, 14 Nov 2008 00:00:00 -0000" + "Fri, 14 Nov 2008 00:00:00 -0000", ) def test_rfc3339_date(self): @@ -62,7 +70,7 @@ class FeedgeneratorTests(SimpleTestCase): """ self.assertEqual( feedgenerator.rfc3339_date(datetime.datetime(2008, 11, 14, 13, 37, 0)), - "2008-11-14T13:37:00Z" + "2008-11-14T13:37:00Z", ) def test_rfc3339_date_with_timezone(self): @@ -70,8 +78,12 @@ class FeedgeneratorTests(SimpleTestCase): rfc3339_date() correctly formats datetime objects with tzinfo. """ self.assertEqual( - feedgenerator.rfc3339_date(datetime.datetime(2008, 11, 14, 13, 37, 0, tzinfo=get_fixed_timezone(120))), - "2008-11-14T13:37:00+02:00" + feedgenerator.rfc3339_date( + datetime.datetime( + 2008, 11, 14, 13, 37, 0, tzinfo=get_fixed_timezone(120) + ) + ), + "2008-11-14T13:37:00+02:00", ) def test_rfc3339_date_without_time(self): @@ -80,7 +92,7 @@ class FeedgeneratorTests(SimpleTestCase): """ self.assertEqual( feedgenerator.rfc3339_date(datetime.date(2008, 11, 14)), - "2008-11-14T00:00:00Z" + "2008-11-14T00:00:00Z", ) def test_atom1_mime_type(self): @@ -88,50 +100,48 @@ class FeedgeneratorTests(SimpleTestCase): Atom MIME type has UTF8 Charset parameter set """ atom_feed = feedgenerator.Atom1Feed("title", "link", "description") - self.assertEqual( - atom_feed.content_type, "application/atom+xml; charset=utf-8" - ) + self.assertEqual(atom_feed.content_type, "application/atom+xml; charset=utf-8") def test_rss_mime_type(self): """ RSS MIME type has UTF8 Charset parameter set """ rss_feed = feedgenerator.Rss201rev2Feed("title", "link", "description") - self.assertEqual( - rss_feed.content_type, "application/rss+xml; charset=utf-8" - ) + self.assertEqual(rss_feed.content_type, "application/rss+xml; charset=utf-8") # Two regression tests for #14202 def test_feed_without_feed_url_gets_rendered_without_atom_link(self): - feed = feedgenerator.Rss201rev2Feed('title', '/link/', 'descr') - self.assertIsNone(feed.feed['feed_url']) - feed_content = feed.writeString('utf-8') - self.assertNotIn('<atom:link', feed_content) + feed = feedgenerator.Rss201rev2Feed("title", "/link/", "descr") + self.assertIsNone(feed.feed["feed_url"]) + feed_content = feed.writeString("utf-8") + self.assertNotIn("<atom:link", feed_content) self.assertNotIn('href="/feed/"', feed_content) self.assertNotIn('rel="self"', feed_content) def test_feed_with_feed_url_gets_rendered_with_atom_link(self): - feed = feedgenerator.Rss201rev2Feed('title', '/link/', 'descr', feed_url='/feed/') - self.assertEqual(feed.feed['feed_url'], '/feed/') - feed_content = feed.writeString('utf-8') - self.assertIn('<atom:link', feed_content) + feed = feedgenerator.Rss201rev2Feed( + "title", "/link/", "descr", feed_url="/feed/" + ) + self.assertEqual(feed.feed["feed_url"], "/feed/") + feed_content = feed.writeString("utf-8") + self.assertIn("<atom:link", feed_content) self.assertIn('href="/feed/"', feed_content) self.assertIn('rel="self"', feed_content) def test_atom_add_item(self): # Not providing any optional arguments to Atom1Feed.add_item() - feed = feedgenerator.Atom1Feed('title', '/link/', 'descr') - feed.add_item('item_title', 'item_link', 'item_description') - feed.writeString('utf-8') + feed = feedgenerator.Atom1Feed("title", "/link/", "descr") + feed.add_item("item_title", "item_link", "item_description") + feed.writeString("utf-8") def test_deterministic_attribute_order(self): - feed = feedgenerator.Atom1Feed('title', '/link/', 'desc') - feed_content = feed.writeString('utf-8') + feed = feedgenerator.Atom1Feed("title", "/link/", "desc") + feed_content = feed.writeString("utf-8") self.assertIn('href="/link/" rel="alternate"', feed_content) def test_latest_post_date_returns_utc_time(self): for use_tz in (True, False): with self.settings(USE_TZ=use_tz): - rss_feed = feedgenerator.Rss201rev2Feed('title', 'link', 'description') + rss_feed = feedgenerator.Rss201rev2Feed("title", "link", "description") self.assertEqual(rss_feed.latest_post_date().tzinfo, utc) diff --git a/tests/utils_tests/test_functional.py b/tests/utils_tests/test_functional.py index f720ffac3d..1e403f351b 100644 --- a/tests/utils_tests/test_functional.py +++ b/tests/utils_tests/test_functional.py @@ -14,6 +14,7 @@ class FunctionalTests(SimpleTestCase): def test_lazy_base_class(self): """lazy also finds base class methods in the proxy object""" + class Base: def base_method(self): pass @@ -22,23 +23,23 @@ class FunctionalTests(SimpleTestCase): pass t = lazy(lambda: Klazz(), Klazz)() - self.assertIn('base_method', dir(t)) + self.assertIn("base_method", dir(t)) def test_lazy_base_class_override(self): """lazy finds the correct (overridden) method implementation""" + class Base: def method(self): - return 'Base' + return "Base" class Klazz(Base): def method(self): - return 'Klazz' + return "Klazz" t = lazy(lambda: Klazz(), Base)() - self.assertEqual(t.method(), 'Klazz') + self.assertEqual(t.method(), "Klazz") def test_lazy_object_to_string(self): - class Klazz: def __str__(self): return "Î am ā Ǩlâzz." @@ -52,6 +53,7 @@ class FunctionalTests(SimpleTestCase): def assertCachedPropertyWorks(self, attr, Class): with self.subTest(attr=attr): + def get(source): return getattr(source, attr) @@ -62,8 +64,8 @@ class FunctionalTests(SimpleTestCase): subobj = SubClass() # Docstring is preserved. - self.assertEqual(get(Class).__doc__, 'Here is the docstring...') - self.assertEqual(get(SubClass).__doc__, 'Here is the docstring...') + self.assertEqual(get(Class).__doc__, "Here is the docstring...") + self.assertEqual(get(SubClass).__doc__, "Here is the docstring...") # It's cached. self.assertEqual(get(obj), get(obj)) self.assertEqual(get(subobj), get(subobj)) @@ -84,6 +86,7 @@ class FunctionalTests(SimpleTestCase): def test_cached_property(self): """cached_property caches its value and behaves like a property.""" + class Class: @cached_property def value(self): @@ -101,7 +104,7 @@ class FunctionalTests(SimpleTestCase): other = cached_property(other_value) - attrs = ['value', 'other', '__foo__'] + attrs = ["value", "other", "__foo__"] for attr in attrs: self.assertCachedPropertyWorks(attr, Class) @@ -112,14 +115,14 @@ class FunctionalTests(SimpleTestCase): """Here is the docstring...""" return 1, object() - other = cached_property(other_value, name='other') - other2 = cached_property(other_value, name='different_name') + other = cached_property(other_value, name="other") + other2 = cached_property(other_value, name="different_name") - self.assertCachedPropertyWorks('other', Class) + self.assertCachedPropertyWorks("other", Class) # An explicit name is ignored. obj = Class() obj.other2 - self.assertFalse(hasattr(obj, 'different_name')) + self.assertFalse(hasattr(obj, "different_name")) def test_cached_property_name_deprecation_warning(self): def value(self): @@ -127,13 +130,14 @@ class FunctionalTests(SimpleTestCase): msg = "The name argument is deprecated as it's unnecessary as of Python 3.6." with self.assertWarnsMessage(RemovedInDjango50Warning, msg): - cached_property(value, name='other_name') + cached_property(value, name="other_name") def test_cached_property_auto_name(self): """ cached_property caches its value and behaves like a property on mangled methods or when the name kwarg isn't set. """ + class Class: @cached_property def __value(self): @@ -146,13 +150,14 @@ class FunctionalTests(SimpleTestCase): other = cached_property(other_value) - attrs = ['_Class__value', 'other'] + attrs = ["_Class__value", "other"] for attr in attrs: self.assertCachedPropertyWorks(attr, Class) def test_cached_property_reuse_different_names(self): """Disallow this case because the decorated function wouldn't be cached.""" with self.assertRaises(RuntimeError) as ctx: + class ReusedCachedProperty: @cached_property def a(self): @@ -162,10 +167,12 @@ class FunctionalTests(SimpleTestCase): self.assertEqual( str(ctx.exception.__context__), - str(TypeError( - "Cannot assign the same cached_property to two different " - "names ('a' and 'b')." - )) + str( + TypeError( + "Cannot assign the same cached_property to two different " + "names ('a' and 'b')." + ) + ), ) def test_cached_property_reuse_same_name(self): @@ -200,7 +207,9 @@ class FunctionalTests(SimpleTestCase): pass Foo.cp = cp - msg = 'Cannot use cached_property instance without calling __set_name__() on it.' + msg = ( + "Cannot use cached_property instance without calling __set_name__() on it." + ) with self.assertRaisesMessage(TypeError, msg): Foo().cp @@ -221,7 +230,7 @@ class FunctionalTests(SimpleTestCase): self.assertNotEqual(lazy_b(), lazy_c()) def test_lazy_repr_text(self): - original_object = 'Lazy translation text' + original_object = "Lazy translation text" lazy_obj = lazy(lambda: original_object, str) self.assertEqual(repr(original_object), repr(lazy_obj())) @@ -231,7 +240,7 @@ class FunctionalTests(SimpleTestCase): self.assertEqual(repr(original_object), repr(lazy_obj())) def test_lazy_repr_bytes(self): - original_object = b'J\xc3\xbcst a str\xc3\xadng' + original_object = b"J\xc3\xbcst a str\xc3\xadng" lazy_obj = lazy(lambda: original_object, bytes) self.assertEqual(repr(original_object), repr(lazy_obj())) @@ -240,13 +249,13 @@ class FunctionalTests(SimpleTestCase): # it's used. lazified = lazy(lambda: 0, int) __proxy__ = lazified().__class__ - with mock.patch.object(__proxy__, '__prepare_class__') as mocked: + with mock.patch.object(__proxy__, "__prepare_class__") as mocked: lazified() mocked.assert_not_called() def test_lazy_bytes_and_str_result_classes(self): - lazy_obj = lazy(lambda: 'test', str, bytes) - msg = 'Cannot call lazy() with both bytes and text return types.' + lazy_obj = lazy(lambda: "test", str, bytes) + msg = "Cannot call lazy() with both bytes and text return types." with self.assertRaisesMessage(ValueError, msg): lazy_obj() diff --git a/tests/utils_tests/test_hashable.py b/tests/utils_tests/test_hashable.py index d267b112cc..681f4587b8 100644 --- a/tests/utils_tests/test_hashable.py +++ b/tests/utils_tests/test_hashable.py @@ -6,14 +6,14 @@ class TestHashable(SimpleTestCase): def test_equal(self): tests = ( ([], ()), - (['a', 1], ('a', 1)), + (["a", 1], ("a", 1)), ({}, ()), - ({'a'}, ('a',)), - (frozenset({'a'}), {'a'}), - ({'a': 1, 'b': 2}, (('a', 1), ('b', 2))), - ({'b': 2, 'a': 1}, (('a', 1), ('b', 2))), - (('a', ['b', 1]), ('a', ('b', 1))), - (('a', {'b': 1}), ('a', (('b', 1),))), + ({"a"}, ("a",)), + (frozenset({"a"}), {"a"}), + ({"a": 1, "b": 2}, (("a", 1), ("b", 2))), + ({"b": 2, "a": 1}, (("a", 1), ("b", 2))), + (("a", ["b", 1]), ("a", ("b", 1))), + (("a", {"b": 1}), ("a", (("b", 1),))), ) for value, expected in tests: with self.subTest(value=value): @@ -21,8 +21,8 @@ class TestHashable(SimpleTestCase): def test_count_equal(self): tests = ( - ({'a': 1, 'b': ['a', 1]}, (('a', 1), ('b', ('a', 1)))), - ({'a': 1, 'b': ('a', [1, 2])}, (('a', 1), ('b', ('a', (1, 2))))), + ({"a": 1, "b": ["a", 1]}, (("a", 1), ("b", ("a", 1)))), + ({"a": 1, "b": ("a", [1, 2])}, (("a", 1), ("b", ("a", (1, 2))))), ) for value, expected in tests: with self.subTest(value=value): diff --git a/tests/utils_tests/test_html.py b/tests/utils_tests/test_html.py index 63644daf61..c38a16de40 100644 --- a/tests/utils_tests/test_html.py +++ b/tests/utils_tests/test_html.py @@ -4,14 +4,22 @@ from datetime import datetime from django.test import SimpleTestCase from django.utils.functional import lazystr from django.utils.html import ( - conditional_escape, escape, escapejs, format_html, html_safe, json_script, - linebreaks, smart_urlquote, strip_spaces_between_tags, strip_tags, urlize, + conditional_escape, + escape, + escapejs, + format_html, + html_safe, + json_script, + linebreaks, + smart_urlquote, + strip_spaces_between_tags, + strip_tags, + urlize, ) from django.utils.safestring import mark_safe class TestUtilsHtml(SimpleTestCase): - def check_output(self, function, value, output=None): """ function(value) equals output. If output is None, function(value) @@ -23,11 +31,11 @@ class TestUtilsHtml(SimpleTestCase): def test_escape(self): items = ( - ('&', '&'), - ('<', '<'), - ('>', '>'), - ('"', '"'), - ("'", '''), + ("&", "&"), + ("<", "<"), + (">", ">"), + ('"', """), + ("'", "'"), ) # Substitution patterns for testing the above items. patterns = ("%s", "asdf%sfdsa", "%s1", "1%sb") @@ -36,11 +44,13 @@ class TestUtilsHtml(SimpleTestCase): for pattern in patterns: with self.subTest(value=value, output=output, pattern=pattern): self.check_output(escape, pattern % value, pattern % output) - self.check_output(escape, lazystr(pattern % value), pattern % output) + self.check_output( + escape, lazystr(pattern % value), pattern % output + ) # Check repeated values. self.check_output(escape, value * 2, output * 2) # Verify it doesn't double replace &. - self.check_output(escape, '<&', '<&') + self.check_output(escape, "<&", "<&") def test_format_html(self): self.assertEqual( @@ -51,14 +61,20 @@ class TestUtilsHtml(SimpleTestCase): third="< dangerous again", fourth=mark_safe("<i>safe again</i>"), ), - "< Dangerous > <b>safe</b> < dangerous again <i>safe again</i>" + "< Dangerous > <b>safe</b> < dangerous again <i>safe again</i>", ) def test_linebreaks(self): items = ( ("para1\n\npara2\r\rpara3", "<p>para1</p>\n\n<p>para2</p>\n\n<p>para3</p>"), - ("para1\nsub1\rsub2\n\npara2", "<p>para1<br>sub1<br>sub2</p>\n\n<p>para2</p>"), - ("para1\r\n\r\npara2\rsub1\r\rpara4", "<p>para1</p>\n\n<p>para2<br>sub1</p>\n\n<p>para4</p>"), + ( + "para1\nsub1\rsub2\n\npara2", + "<p>para1<br>sub1<br>sub2</p>\n\n<p>para2</p>", + ), + ( + "para1\r\n\r\npara2\rsub1\r\rpara4", + "<p>para1</p>\n\n<p>para2<br>sub1</p>\n\n<p>para4</p>", + ), ("para1\tmore\n\npara2", "<p>para1\tmore</p>\n\n<p>para2</p>"), ) for value, output in items: @@ -68,30 +84,34 @@ class TestUtilsHtml(SimpleTestCase): def test_strip_tags(self): items = ( - ('<p>See: 'é is an apostrophe followed by e acute</p>', - 'See: 'é is an apostrophe followed by e acute'), - ('<p>See: 'é is an apostrophe followed by e acute</p>', - 'See: 'é is an apostrophe followed by e acute'), - ('<adf>a', 'a'), - ('</adf>a', 'a'), - ('<asdf><asdf>e', 'e'), - ('hi, <f x', 'hi, <f x'), - ('234<235, right?', '234<235, right?'), - ('a4<a5 right?', 'a4<a5 right?'), - ('b7>b2!', 'b7>b2!'), - ('</fe', '</fe'), - ('<x>b<y>', 'b'), - ('a<p onclick="alert(\'<test>\')">b</p>c', 'abc'), - ('a<p a >b</p>c', 'abc'), - ('d<a:b c:d>e</p>f', 'def'), - ('<strong>foo</strong><a href="http://example.com">bar</a>', 'foobar'), + ( + "<p>See: 'é is an apostrophe followed by e acute</p>", + "See: 'é is an apostrophe followed by e acute", + ), + ( + "<p>See: 'é is an apostrophe followed by e acute</p>", + "See: 'é is an apostrophe followed by e acute", + ), + ("<adf>a", "a"), + ("</adf>a", "a"), + ("<asdf><asdf>e", "e"), + ("hi, <f x", "hi, <f x"), + ("234<235, right?", "234<235, right?"), + ("a4<a5 right?", "a4<a5 right?"), + ("b7>b2!", "b7>b2!"), + ("</fe", "</fe"), + ("<x>b<y>", "b"), + ("a<p onclick=\"alert('<test>')\">b</p>c", "abc"), + ("a<p a >b</p>c", "abc"), + ("d<a:b c:d>e</p>f", "def"), + ('<strong>foo</strong><a href="http://example.com">bar</a>', "foobar"), # caused infinite loop on Pythons not patched with # https://bugs.python.org/issue20288 - ('&gotcha&#;<>', '&gotcha&#;<>'), - ('<sc<!-- -->ript>test<<!-- -->/script>', 'ript>test'), - ('<script>alert()</script>&h', 'alert()h'), - ('><!' + ('&' * 16000) + 'D', '><!' + ('&' * 16000) + 'D'), - ('X<<<<br>br>br>br>X', 'XX'), + ("&gotcha&#;<>", "&gotcha&#;<>"), + ("<sc<!-- -->ript>test<<!-- -->/script>", "ript>test"), + ("<script>alert()</script>&h", "alert()h"), + ("><!" + ("&" * 16000) + "D", "><!" + ("&" * 16000) + "D"), + ("X<<<<br>br>br>br>X", "XX"), ) for value, output in items: with self.subTest(value=value, output=output): @@ -100,9 +120,9 @@ class TestUtilsHtml(SimpleTestCase): def test_strip_tags_files(self): # Test with more lengthy content (also catching performance regressions) - for filename in ('strip_tags1.html', 'strip_tags2.txt'): + for filename in ("strip_tags1.html", "strip_tags2.txt"): with self.subTest(filename=filename): - path = os.path.join(os.path.dirname(__file__), 'files', filename) + path = os.path.join(os.path.dirname(__file__), "files", filename) with open(path) as fp: content = fp.read() start = datetime.now() @@ -110,11 +130,11 @@ class TestUtilsHtml(SimpleTestCase): elapsed = datetime.now() - start self.assertEqual(elapsed.seconds, 0) self.assertIn("Please try again.", stripped) - self.assertNotIn('<', stripped) + self.assertNotIn("<", stripped) def test_strip_spaces_between_tags(self): # Strings that should come out untouched. - items = (' <adf>', '<adf> ', ' </adf> ', ' <f> x</f>') + items = (" <adf>", "<adf> ", " </adf> ", " <f> x</f>") for value in items: with self.subTest(value=value): self.check_output(strip_spaces_between_tags, value) @@ -122,9 +142,9 @@ class TestUtilsHtml(SimpleTestCase): # Strings that have spaces to strip. items = ( - ('<d> </d>', '<d></d>'), - ('<p>hello </p>\n<p> world</p>', '<p>hello </p><p> world</p>'), - ('\n<p>\t</p>\n<p> </p>\n', '\n<p></p><p></p>\n'), + ("<d> </d>", "<d></d>"), + ("<p>hello </p>\n<p> world</p>", "<p>hello </p><p> world</p>"), + ("\n<p>\t</p>\n<p> </p>\n", "\n<p></p><p></p>\n"), ) for value, output in items: with self.subTest(value=value, output=output): @@ -133,18 +153,24 @@ class TestUtilsHtml(SimpleTestCase): def test_escapejs(self): items = ( - ('"double quotes" and \'single quotes\'', '\\u0022double quotes\\u0022 and \\u0027single quotes\\u0027'), - (r'\ : backslashes, too', '\\u005C : backslashes, too'), ( - 'and lots of whitespace: \r\n\t\v\f\b', - 'and lots of whitespace: \\u000D\\u000A\\u0009\\u000B\\u000C\\u0008' + "\"double quotes\" and 'single quotes'", + "\\u0022double quotes\\u0022 and \\u0027single quotes\\u0027", + ), + (r"\ : backslashes, too", "\\u005C : backslashes, too"), + ( + "and lots of whitespace: \r\n\t\v\f\b", + "and lots of whitespace: \\u000D\\u000A\\u0009\\u000B\\u000C\\u0008", + ), + ( + r"<script>and this</script>", + "\\u003Cscript\\u003Eand this\\u003C/script\\u003E", ), - (r'<script>and this</script>', '\\u003Cscript\\u003Eand this\\u003C/script\\u003E'), ( - 'paragraph separator:\u2029and line separator:\u2028', - 'paragraph separator:\\u2029and line separator:\\u2028' + "paragraph separator:\u2029and line separator:\u2028", + "paragraph separator:\\u2029and line separator:\\u2028", ), - ('`', '\\u0060'), + ("`", "\\u0060"), ) for value, output in items: with self.subTest(value=value, output=output): @@ -154,46 +180,61 @@ class TestUtilsHtml(SimpleTestCase): def test_json_script(self): tests = ( # "<", ">" and "&" are quoted inside JSON strings - (('&<>', '<script id="test_id" type="application/json">"\\u0026\\u003C\\u003E"</script>')), + ( + ( + "&<>", + '<script id="test_id" type="application/json">"\\u0026\\u003C\\u003E"</script>', + ) + ), # "<", ">" and "&" are quoted inside JSON objects ( - {'a': '<script>test&ing</script>'}, + {"a": "<script>test&ing</script>"}, '<script id="test_id" type="application/json">' - '{"a": "\\u003Cscript\\u003Etest\\u0026ing\\u003C/script\\u003E"}</script>' + '{"a": "\\u003Cscript\\u003Etest\\u0026ing\\u003C/script\\u003E"}</script>', ), # Lazy strings are quoted - (lazystr('&<>'), '<script id="test_id" type="application/json">"\\u0026\\u003C\\u003E"</script>'), ( - {'a': lazystr('<script>test&ing</script>')}, + lazystr("&<>"), + '<script id="test_id" type="application/json">"\\u0026\\u003C\\u003E"</script>', + ), + ( + {"a": lazystr("<script>test&ing</script>")}, '<script id="test_id" type="application/json">' - '{"a": "\\u003Cscript\\u003Etest\\u0026ing\\u003C/script\\u003E"}</script>' + '{"a": "\\u003Cscript\\u003Etest\\u0026ing\\u003C/script\\u003E"}</script>', ), ) for arg, expected in tests: with self.subTest(arg=arg): - self.assertEqual(json_script(arg, 'test_id'), expected) + self.assertEqual(json_script(arg, "test_id"), expected) def test_json_script_without_id(self): self.assertHTMLEqual( - json_script({'key': 'value'}), + json_script({"key": "value"}), '<script type="application/json">{"key": "value"}</script>', ) def test_smart_urlquote(self): items = ( - ('http://öäü.com/', 'http://xn--4ca9at.com/'), - ('http://öäü.com/öäü/', 'http://xn--4ca9at.com/%C3%B6%C3%A4%C3%BC/'), + ("http://öäü.com/", "http://xn--4ca9at.com/"), + ("http://öäü.com/öäü/", "http://xn--4ca9at.com/%C3%B6%C3%A4%C3%BC/"), # Everything unsafe is quoted, !*'();:@&=+$,/?#[]~ is considered # safe as per RFC. - ('http://example.com/path/öäü/', 'http://example.com/path/%C3%B6%C3%A4%C3%BC/'), - ('http://example.com/%C3%B6/ä/', 'http://example.com/%C3%B6/%C3%A4/'), - ('http://example.com/?x=1&y=2+3&z=', 'http://example.com/?x=1&y=2+3&z='), - ('http://example.com/?x=<>"\'', 'http://example.com/?x=%3C%3E%22%27'), - ('http://example.com/?q=http://example.com/?x=1%26q=django', - 'http://example.com/?q=http%3A%2F%2Fexample.com%2F%3Fx%3D1%26q%3Ddjango'), - ('http://example.com/?q=http%3A%2F%2Fexample.com%2F%3Fx%3D1%26q%3Ddjango', - 'http://example.com/?q=http%3A%2F%2Fexample.com%2F%3Fx%3D1%26q%3Ddjango'), - ('http://.www.f oo.bar/', 'http://.www.f%20oo.bar/'), + ( + "http://example.com/path/öäü/", + "http://example.com/path/%C3%B6%C3%A4%C3%BC/", + ), + ("http://example.com/%C3%B6/ä/", "http://example.com/%C3%B6/%C3%A4/"), + ("http://example.com/?x=1&y=2+3&z=", "http://example.com/?x=1&y=2+3&z="), + ("http://example.com/?x=<>\"'", "http://example.com/?x=%3C%3E%22%27"), + ( + "http://example.com/?q=http://example.com/?x=1%26q=django", + "http://example.com/?q=http%3A%2F%2Fexample.com%2F%3Fx%3D1%26q%3Ddjango", + ), + ( + "http://example.com/?q=http%3A%2F%2Fexample.com%2F%3Fx%3D1%26q%3Ddjango", + "http://example.com/?q=http%3A%2F%2Fexample.com%2F%3Fx%3D1%26q%3Ddjango", + ), + ("http://.www.f oo.bar/", "http://.www.f%20oo.bar/"), ) # IDNs are properly quoted for value, output in items: @@ -201,8 +242,8 @@ class TestUtilsHtml(SimpleTestCase): self.assertEqual(smart_urlquote(value), output) def test_conditional_escape(self): - s = '<h1>interop</h1>' - self.assertEqual(conditional_escape(s), '<h1>interop</h1>') + s = "<h1>interop</h1>" + self.assertEqual(conditional_escape(s), "<h1>interop</h1>") self.assertEqual(conditional_escape(mark_safe(s)), s) self.assertEqual(conditional_escape(lazystr(mark_safe(s))), s) @@ -213,24 +254,24 @@ class TestUtilsHtml(SimpleTestCase): return "<h1>I'm a html class!</h1>" html_obj = HtmlClass() - self.assertTrue(hasattr(HtmlClass, '__html__')) - self.assertTrue(hasattr(html_obj, '__html__')) + self.assertTrue(hasattr(HtmlClass, "__html__")) + self.assertTrue(hasattr(html_obj, "__html__")) self.assertEqual(str(html_obj), html_obj.__html__()) def test_html_safe_subclass(self): class BaseClass: def __html__(self): # defines __html__ on its own - return 'some html content' + return "some html content" def __str__(self): - return 'some non html content' + return "some non html content" @html_safe class Subclass(BaseClass): def __str__(self): # overrides __str__ and is marked as html_safe - return 'some html safe content' + return "some html safe content" subclass_obj = Subclass() self.assertEqual(str(subclass_obj), subclass_obj.__html__()) @@ -238,6 +279,7 @@ class TestUtilsHtml(SimpleTestCase): def test_html_safe_defines_html_error(self): msg = "can't apply @html_safe to HtmlClass because it defines __html__()." with self.assertRaisesMessage(ValueError, msg): + @html_safe class HtmlClass: def __html__(self): @@ -246,6 +288,7 @@ class TestUtilsHtml(SimpleTestCase): def test_html_safe_doesnt_define_str(self): msg = "can't apply @html_safe to HtmlClass because it doesn't define __str__()." with self.assertRaisesMessage(ValueError, msg): + @html_safe class HtmlClass: pass @@ -253,18 +296,18 @@ class TestUtilsHtml(SimpleTestCase): def test_urlize(self): tests = ( ( - 'Search for google.com/?q=! and see.', - 'Search for <a href="http://google.com/?q=">google.com/?q=</a>! and see.' + "Search for google.com/?q=! and see.", + 'Search for <a href="http://google.com/?q=">google.com/?q=</a>! and see.', ), ( - 'Search for google.com/?q=1<! and see.', - 'Search for <a href="http://google.com/?q=1%3C">google.com/?q=1<</a>! and see.' + "Search for google.com/?q=1<! and see.", + 'Search for <a href="http://google.com/?q=1%3C">google.com/?q=1<</a>! and see.', ), ( - lazystr('Search for google.com/?q=!'), - 'Search for <a href="http://google.com/?q=">google.com/?q=</a>!' + lazystr("Search for google.com/?q=!"), + 'Search for <a href="http://google.com/?q=">google.com/?q=</a>!', ), - ('foo@example.com', '<a href="mailto:foo@example.com">foo@example.com</a>'), + ("foo@example.com", '<a href="mailto:foo@example.com">foo@example.com</a>'), ) for value, output in tests: with self.subTest(value=value): @@ -272,13 +315,13 @@ class TestUtilsHtml(SimpleTestCase): def test_urlize_unchanged_inputs(self): tests = ( - ('a' + '@a' * 50000) + 'a', # simple_email_re catastrophic test - ('a' + '.' * 1000000) + 'a', # trailing_punctuation catastrophic test - 'foo@', - '@foo.com', - 'foo@.example.com', - 'foo@localhost', - 'foo@localhost.', + ("a" + "@a" * 50000) + "a", # simple_email_re catastrophic test + ("a" + "." * 1000000) + "a", # trailing_punctuation catastrophic test + "foo@", + "@foo.com", + "foo@.example.com", + "foo@localhost", + "foo@localhost.", ) for value in tests: with self.subTest(value=value): diff --git a/tests/utils_tests/test_http.py b/tests/utils_tests/test_http.py index 77b91a7174..67f3361068 100644 --- a/tests/utils_tests/test_http.py +++ b/tests/utils_tests/test_http.py @@ -6,9 +6,17 @@ from unittest import mock from django.test import SimpleTestCase from django.utils.datastructures import MultiValueDict from django.utils.http import ( - base36_to_int, escape_leading_slashes, http_date, int_to_base36, - is_same_domain, parse_etags, parse_http_date, quote_etag, - url_has_allowed_host_and_scheme, urlencode, urlsafe_base64_decode, + base36_to_int, + escape_leading_slashes, + http_date, + int_to_base36, + is_same_domain, + parse_etags, + parse_http_date, + quote_etag, + url_has_allowed_host_and_scheme, + urlencode, + urlsafe_base64_decode, urlsafe_base64_encode, ) @@ -20,79 +28,94 @@ class URLEncodeTests(SimpleTestCase): ) def test_tuples(self): - self.assertEqual(urlencode((('a', 1), ('b', 2), ('c', 3))), 'a=1&b=2&c=3') + self.assertEqual(urlencode((("a", 1), ("b", 2), ("c", 3))), "a=1&b=2&c=3") def test_dict(self): - result = urlencode({'a': 1, 'b': 2, 'c': 3}) + result = urlencode({"a": 1, "b": 2, "c": 3}) # Dictionaries are treated as unordered. - self.assertIn(result, [ - 'a=1&b=2&c=3', - 'a=1&c=3&b=2', - 'b=2&a=1&c=3', - 'b=2&c=3&a=1', - 'c=3&a=1&b=2', - 'c=3&b=2&a=1', - ]) + self.assertIn( + result, + [ + "a=1&b=2&c=3", + "a=1&c=3&b=2", + "b=2&a=1&c=3", + "b=2&c=3&a=1", + "c=3&a=1&b=2", + "c=3&b=2&a=1", + ], + ) def test_dict_containing_sequence_not_doseq(self): - self.assertEqual(urlencode({'a': [1, 2]}, doseq=False), 'a=%5B1%2C+2%5D') + self.assertEqual(urlencode({"a": [1, 2]}, doseq=False), "a=%5B1%2C+2%5D") def test_dict_containing_tuple_not_doseq(self): - self.assertEqual(urlencode({'a': (1, 2)}, doseq=False), 'a=%281%2C+2%29') + self.assertEqual(urlencode({"a": (1, 2)}, doseq=False), "a=%281%2C+2%29") def test_custom_iterable_not_doseq(self): class IterableWithStr: def __str__(self): - return 'custom' + return "custom" def __iter__(self): yield from range(0, 3) - self.assertEqual(urlencode({'a': IterableWithStr()}, doseq=False), 'a=custom') + self.assertEqual(urlencode({"a": IterableWithStr()}, doseq=False), "a=custom") def test_dict_containing_sequence_doseq(self): - self.assertEqual(urlencode({'a': [1, 2]}, doseq=True), 'a=1&a=2') + self.assertEqual(urlencode({"a": [1, 2]}, doseq=True), "a=1&a=2") def test_dict_containing_empty_sequence_doseq(self): - self.assertEqual(urlencode({'a': []}, doseq=True), '') + self.assertEqual(urlencode({"a": []}, doseq=True), "") def test_multivaluedict(self): - result = urlencode(MultiValueDict({ - 'name': ['Adrian', 'Simon'], - 'position': ['Developer'], - }), doseq=True) + result = urlencode( + MultiValueDict( + { + "name": ["Adrian", "Simon"], + "position": ["Developer"], + } + ), + doseq=True, + ) # MultiValueDicts are similarly unordered. - self.assertIn(result, [ - 'name=Adrian&name=Simon&position=Developer', - 'position=Developer&name=Adrian&name=Simon', - ]) + self.assertIn( + result, + [ + "name=Adrian&name=Simon&position=Developer", + "position=Developer&name=Adrian&name=Simon", + ], + ) def test_dict_with_bytes_values(self): - self.assertEqual(urlencode({'a': b'abc'}, doseq=True), 'a=abc') + self.assertEqual(urlencode({"a": b"abc"}, doseq=True), "a=abc") def test_dict_with_sequence_of_bytes(self): - self.assertEqual(urlencode({'a': [b'spam', b'eggs', b'bacon']}, doseq=True), 'a=spam&a=eggs&a=bacon') + self.assertEqual( + urlencode({"a": [b"spam", b"eggs", b"bacon"]}, doseq=True), + "a=spam&a=eggs&a=bacon", + ) def test_dict_with_bytearray(self): - self.assertEqual(urlencode({'a': bytearray(range(2))}, doseq=True), 'a=0&a=1') + self.assertEqual(urlencode({"a": bytearray(range(2))}, doseq=True), "a=0&a=1") def test_generator(self): - self.assertEqual(urlencode({'a': range(2)}, doseq=True), 'a=0&a=1') - self.assertEqual(urlencode({'a': range(2)}, doseq=False), 'a=range%280%2C+2%29') + self.assertEqual(urlencode({"a": range(2)}, doseq=True), "a=0&a=1") + self.assertEqual(urlencode({"a": range(2)}, doseq=False), "a=range%280%2C+2%29") def test_none(self): with self.assertRaisesMessage(TypeError, self.cannot_encode_none_msg): - urlencode({'a': None}) + urlencode({"a": None}) def test_none_in_sequence(self): with self.assertRaisesMessage(TypeError, self.cannot_encode_none_msg): - urlencode({'a': [None]}, doseq=True) + urlencode({"a": [None]}, doseq=True) def test_none_in_generator(self): def gen(): yield None + with self.assertRaisesMessage(TypeError, self.cannot_encode_none_msg): - urlencode({'a': gen()}, doseq=True) + urlencode({"a": gen()}, doseq=True) class Base36IntTests(SimpleTestCase): @@ -101,22 +124,24 @@ class Base36IntTests(SimpleTestCase): self.assertEqual(n, base36_to_int(int_to_base36(n))) def test_negative_input(self): - with self.assertRaisesMessage(ValueError, 'Negative base36 conversion input.'): + with self.assertRaisesMessage(ValueError, "Negative base36 conversion input."): int_to_base36(-1) def test_to_base36_errors(self): - for n in ['1', 'foo', {1: 2}, (1, 2, 3), 3.141]: + for n in ["1", "foo", {1: 2}, (1, 2, 3), 3.141]: with self.assertRaises(TypeError): int_to_base36(n) def test_invalid_literal(self): - for n in ['#', ' ']: - with self.assertRaisesMessage(ValueError, "invalid literal for int() with base 36: '%s'" % n): + for n in ["#", " "]: + with self.assertRaisesMessage( + ValueError, "invalid literal for int() with base 36: '%s'" % n + ): base36_to_int(n) def test_input_too_large(self): - with self.assertRaisesMessage(ValueError, 'Base36 input too large'): - base36_to_int('1' * 14) + with self.assertRaisesMessage(ValueError, "Base36 input too large"): + base36_to_int("1" * 14) def test_to_int_errors(self): for n in [123, {1: 2}, (1, 2, 3), 3.141]: @@ -124,7 +149,7 @@ class Base36IntTests(SimpleTestCase): base36_to_int(n) def test_values(self): - for n, b36 in [(0, '0'), (1, '1'), (42, '16'), (818469960, 'django')]: + for n, b36 in [(0, "0"), (1, "1"), (42, "16"), (818469960, "django")]: self.assertEqual(int_to_base36(n), b36) self.assertEqual(base36_to_int(b36), n) @@ -132,111 +157,141 @@ class Base36IntTests(SimpleTestCase): class URLHasAllowedHostAndSchemeTests(unittest.TestCase): def test_bad_urls(self): bad_urls = ( - 'http://example.com', - 'http:///example.com', - 'https://example.com', - 'ftp://example.com', - r'\\example.com', - r'\\\example.com', - r'/\\/example.com', - r'\\\example.com', - r'\\example.com', - r'\\//example.com', - r'/\/example.com', - r'\/example.com', - r'/\example.com', - 'http:///example.com', - r'http:/\//example.com', - r'http:\/example.com', - r'http:/\example.com', + "http://example.com", + "http:///example.com", + "https://example.com", + "ftp://example.com", + r"\\example.com", + r"\\\example.com", + r"/\\/example.com", + r"\\\example.com", + r"\\example.com", + r"\\//example.com", + r"/\/example.com", + r"\/example.com", + r"/\example.com", + "http:///example.com", + r"http:/\//example.com", + r"http:\/example.com", + r"http:/\example.com", 'javascript:alert("XSS")', - '\njavascript:alert(x)', - '\x08//example.com', - r'http://otherserver\@example.com', - r'http:\\testserver\@example.com', - r'http://testserver\me:pass@example.com', - r'http://testserver\@example.com', - r'http:\\testserver\confirm\me@example.com', - 'http:999999999', - 'ftp:9999999999', - '\n', - 'http://[2001:cdba:0000:0000:0000:0000:3257:9652/', - 'http://2001:cdba:0000:0000:0000:0000:3257:9652]/', + "\njavascript:alert(x)", + "\x08//example.com", + r"http://otherserver\@example.com", + r"http:\\testserver\@example.com", + r"http://testserver\me:pass@example.com", + r"http://testserver\@example.com", + r"http:\\testserver\confirm\me@example.com", + "http:999999999", + "ftp:9999999999", + "\n", + "http://[2001:cdba:0000:0000:0000:0000:3257:9652/", + "http://2001:cdba:0000:0000:0000:0000:3257:9652]/", ) for bad_url in bad_urls: with self.subTest(url=bad_url): self.assertIs( - url_has_allowed_host_and_scheme(bad_url, allowed_hosts={'testserver', 'testserver2'}), + url_has_allowed_host_and_scheme( + bad_url, allowed_hosts={"testserver", "testserver2"} + ), False, ) def test_good_urls(self): good_urls = ( - '/view/?param=http://example.com', - '/view/?param=https://example.com', - '/view?param=ftp://example.com', - 'view/?param=//example.com', - 'https://testserver/', - 'HTTPS://testserver/', - '//testserver/', - 'http://testserver/confirm?email=me@example.com', - '/url%20with%20spaces/', - 'path/http:2222222222', + "/view/?param=http://example.com", + "/view/?param=https://example.com", + "/view?param=ftp://example.com", + "view/?param=//example.com", + "https://testserver/", + "HTTPS://testserver/", + "//testserver/", + "http://testserver/confirm?email=me@example.com", + "/url%20with%20spaces/", + "path/http:2222222222", ) for good_url in good_urls: with self.subTest(url=good_url): self.assertIs( - url_has_allowed_host_and_scheme(good_url, allowed_hosts={'otherserver', 'testserver'}), + url_has_allowed_host_and_scheme( + good_url, allowed_hosts={"otherserver", "testserver"} + ), True, ) def test_basic_auth(self): # Valid basic auth credentials are allowed. self.assertIs( - url_has_allowed_host_and_scheme(r'http://user:pass@testserver/', allowed_hosts={'user:pass@testserver'}), + url_has_allowed_host_and_scheme( + r"http://user:pass@testserver/", allowed_hosts={"user:pass@testserver"} + ), True, ) def test_no_allowed_hosts(self): # A path without host is allowed. - self.assertIs(url_has_allowed_host_and_scheme('/confirm/me@example.com', allowed_hosts=None), True) + self.assertIs( + url_has_allowed_host_and_scheme( + "/confirm/me@example.com", allowed_hosts=None + ), + True, + ) # Basic auth without host is not allowed. - self.assertIs(url_has_allowed_host_and_scheme(r'http://testserver\@example.com', allowed_hosts=None), False) + self.assertIs( + url_has_allowed_host_and_scheme( + r"http://testserver\@example.com", allowed_hosts=None + ), + False, + ) def test_allowed_hosts_str(self): - self.assertIs(url_has_allowed_host_and_scheme('http://good.com/good', allowed_hosts='good.com'), True) - self.assertIs(url_has_allowed_host_and_scheme('http://good.co/evil', allowed_hosts='good.com'), False) + self.assertIs( + url_has_allowed_host_and_scheme( + "http://good.com/good", allowed_hosts="good.com" + ), + True, + ) + self.assertIs( + url_has_allowed_host_and_scheme( + "http://good.co/evil", allowed_hosts="good.com" + ), + False, + ) def test_secure_param_https_urls(self): secure_urls = ( - 'https://example.com/p', - 'HTTPS://example.com/p', - '/view/?param=http://example.com', + "https://example.com/p", + "HTTPS://example.com/p", + "/view/?param=http://example.com", ) for url in secure_urls: with self.subTest(url=url): self.assertIs( - url_has_allowed_host_and_scheme(url, allowed_hosts={'example.com'}, require_https=True), + url_has_allowed_host_and_scheme( + url, allowed_hosts={"example.com"}, require_https=True + ), True, ) def test_secure_param_non_https_urls(self): insecure_urls = ( - 'http://example.com/p', - 'ftp://example.com/p', - '//example.com/p', + "http://example.com/p", + "ftp://example.com/p", + "//example.com/p", ) for url in insecure_urls: with self.subTest(url=url): self.assertIs( - url_has_allowed_host_and_scheme(url, allowed_hosts={'example.com'}, require_https=True), + url_has_allowed_host_and_scheme( + url, allowed_hosts={"example.com"}, require_https=True + ), False, ) class URLSafeBase64Tests(unittest.TestCase): def test_roundtrip(self): - bytestring = b'foo' + bytestring = b"foo" encoded = urlsafe_base64_encode(bytestring) decoded = urlsafe_base64_decode(encoded) self.assertEqual(bytestring, decoded) @@ -245,21 +300,21 @@ class URLSafeBase64Tests(unittest.TestCase): class IsSameDomainTests(unittest.TestCase): def test_good(self): for pair in ( - ('example.com', 'example.com'), - ('example.com', '.example.com'), - ('foo.example.com', '.example.com'), - ('example.com:8888', 'example.com:8888'), - ('example.com:8888', '.example.com:8888'), - ('foo.example.com:8888', '.example.com:8888'), + ("example.com", "example.com"), + ("example.com", ".example.com"), + ("foo.example.com", ".example.com"), + ("example.com:8888", "example.com:8888"), + ("example.com:8888", ".example.com:8888"), + ("foo.example.com:8888", ".example.com:8888"), ): self.assertIs(is_same_domain(*pair), True) def test_bad(self): for pair in ( - ('example2.com', 'example.com'), - ('foo.example.com', 'example.com'), - ('example.com:9999', 'example.com:8888'), - ('foo.example.com:8888', ''), + ("example2.com", "example.com"), + ("foo.example.com", "example.com"), + ("example.com:9999", "example.com:8888"), + ("foo.example.com:8888", ""), ): self.assertIs(is_same_domain(*pair), False) @@ -268,15 +323,15 @@ class ETagProcessingTests(unittest.TestCase): def test_parsing(self): self.assertEqual( parse_etags(r'"" , "etag", "e\\tag", W/"weak"'), - ['""', '"etag"', r'"e\\tag"', 'W/"weak"'] + ['""', '"etag"', r'"e\\tag"', 'W/"weak"'], ) - self.assertEqual(parse_etags('*'), ['*']) + self.assertEqual(parse_etags("*"), ["*"]) # Ignore RFC 2616 ETags that are invalid according to RFC 7232. self.assertEqual(parse_etags(r'"etag", "e\"t\"ag"'), ['"etag"']) def test_quoting(self): - self.assertEqual(quote_etag('etag'), '"etag"') # unquoted + self.assertEqual(quote_etag("etag"), '"etag"') # unquoted self.assertEqual(quote_etag('"etag"'), '"etag"') # quoted self.assertEqual(quote_etag('W/"etag"'), 'W/"etag"') # quoted, weak @@ -284,17 +339,17 @@ class ETagProcessingTests(unittest.TestCase): class HttpDateProcessingTests(unittest.TestCase): def test_http_date(self): t = 1167616461.0 - self.assertEqual(http_date(t), 'Mon, 01 Jan 2007 01:54:21 GMT') + self.assertEqual(http_date(t), "Mon, 01 Jan 2007 01:54:21 GMT") def test_parsing_rfc1123(self): - parsed = parse_http_date('Sun, 06 Nov 1994 08:49:37 GMT') + parsed = parse_http_date("Sun, 06 Nov 1994 08:49:37 GMT") self.assertEqual( datetime.fromtimestamp(parsed, timezone.utc), datetime(1994, 11, 6, 8, 49, 37, tzinfo=timezone.utc), ) - @unittest.skipIf(platform.architecture()[0] == '32bit', 'The Year 2038 problem.') - @mock.patch('django.utils.http.datetime.datetime') + @unittest.skipIf(platform.architecture()[0] == "32bit", "The Year 2038 problem.") + @mock.patch("django.utils.http.datetime.datetime") def test_parsing_rfc850(self, mocked_datetime): mocked_datetime.side_effect = datetime mocked_datetime.now = mock.Mock() @@ -302,13 +357,41 @@ class HttpDateProcessingTests(unittest.TestCase): now_2 = datetime(2020, 11, 6, 8, 49, 37, tzinfo=timezone.utc) now_3 = datetime(2048, 11, 6, 8, 49, 37, tzinfo=timezone.utc) tests = ( - (now_1, 'Tuesday, 31-Dec-69 08:49:37 GMT', datetime(2069, 12, 31, 8, 49, 37, tzinfo=timezone.utc)), - (now_1, 'Tuesday, 10-Nov-70 08:49:37 GMT', datetime(1970, 11, 10, 8, 49, 37, tzinfo=timezone.utc)), - (now_1, 'Sunday, 06-Nov-94 08:49:37 GMT', datetime(1994, 11, 6, 8, 49, 37, tzinfo=timezone.utc)), - (now_2, 'Wednesday, 31-Dec-70 08:49:37 GMT', datetime(2070, 12, 31, 8, 49, 37, tzinfo=timezone.utc)), - (now_2, 'Friday, 31-Dec-71 08:49:37 GMT', datetime(1971, 12, 31, 8, 49, 37, tzinfo=timezone.utc)), - (now_3, 'Sunday, 31-Dec-00 08:49:37 GMT', datetime(2000, 12, 31, 8, 49, 37, tzinfo=timezone.utc)), - (now_3, 'Friday, 31-Dec-99 08:49:37 GMT', datetime(1999, 12, 31, 8, 49, 37, tzinfo=timezone.utc)), + ( + now_1, + "Tuesday, 31-Dec-69 08:49:37 GMT", + datetime(2069, 12, 31, 8, 49, 37, tzinfo=timezone.utc), + ), + ( + now_1, + "Tuesday, 10-Nov-70 08:49:37 GMT", + datetime(1970, 11, 10, 8, 49, 37, tzinfo=timezone.utc), + ), + ( + now_1, + "Sunday, 06-Nov-94 08:49:37 GMT", + datetime(1994, 11, 6, 8, 49, 37, tzinfo=timezone.utc), + ), + ( + now_2, + "Wednesday, 31-Dec-70 08:49:37 GMT", + datetime(2070, 12, 31, 8, 49, 37, tzinfo=timezone.utc), + ), + ( + now_2, + "Friday, 31-Dec-71 08:49:37 GMT", + datetime(1971, 12, 31, 8, 49, 37, tzinfo=timezone.utc), + ), + ( + now_3, + "Sunday, 31-Dec-00 08:49:37 GMT", + datetime(2000, 12, 31, 8, 49, 37, tzinfo=timezone.utc), + ), + ( + now_3, + "Friday, 31-Dec-99 08:49:37 GMT", + datetime(1999, 12, 31, 8, 49, 37, tzinfo=timezone.utc), + ), ) for now, rfc850str, expected_date in tests: with self.subTest(rfc850str=rfc850str): @@ -322,7 +405,7 @@ class HttpDateProcessingTests(unittest.TestCase): mocked_datetime.reset_mock() def test_parsing_asctime(self): - parsed = parse_http_date('Sun Nov 6 08:49:37 1994') + parsed = parse_http_date("Sun Nov 6 08:49:37 1994") self.assertEqual( datetime.fromtimestamp(parsed, timezone.utc), datetime(1994, 11, 6, 8, 49, 37, tzinfo=timezone.utc), @@ -331,12 +414,12 @@ class HttpDateProcessingTests(unittest.TestCase): def test_parsing_asctime_nonascii_digits(self): """Non-ASCII unicode decimals raise an error.""" with self.assertRaises(ValueError): - parse_http_date('Sun Nov 6 08:49:37 1994') + parse_http_date("Sun Nov 6 08:49:37 1994") with self.assertRaises(ValueError): - parse_http_date('Sun Nov 12 08:49:37 1994') + parse_http_date("Sun Nov 12 08:49:37 1994") def test_parsing_year_less_than_70(self): - parsed = parse_http_date('Sun Nov 6 08:49:37 0037') + parsed = parse_http_date("Sun Nov 6 08:49:37 0037") self.assertEqual( datetime.fromtimestamp(parsed, timezone.utc), datetime(2037, 11, 6, 8, 49, 37, tzinfo=timezone.utc), @@ -346,8 +429,8 @@ class HttpDateProcessingTests(unittest.TestCase): class EscapeLeadingSlashesTests(unittest.TestCase): def test(self): tests = ( - ('//example.com', '/%2Fexample.com'), - ('//', '/%2F'), + ("//example.com", "/%2Fexample.com"), + ("//", "/%2F"), ) for url, expected in tests: with self.subTest(url=url): diff --git a/tests/utils_tests/test_inspect.py b/tests/utils_tests/test_inspect.py index ae83d675fe..b8359c2508 100644 --- a/tests/utils_tests/test_inspect.py +++ b/tests/utils_tests/test_inspect.py @@ -13,11 +13,11 @@ class Person: def just_args(self, *args): return args - def all_kinds(self, name, address='home', age=25, *args, **kwargs): + def all_kinds(self, name, address="home", age=25, *args, **kwargs): return kwargs @classmethod - def cls_all_kinds(cls, name, address='home', age=25, *args, **kwargs): + def cls_all_kinds(cls, name, address="home", age=25, *args, **kwargs): return kwargs @@ -37,20 +37,32 @@ class TestInspectMethods(unittest.TestCase): self.assertEqual(inspect.get_func_full_args(Person().no_arguments), []) def test_get_func_full_args_one_argument(self): - self.assertEqual(inspect.get_func_full_args(Person.one_argument), [('something',)]) + self.assertEqual( + inspect.get_func_full_args(Person.one_argument), [("something",)] + ) self.assertEqual( inspect.get_func_full_args(Person().one_argument), - [('something',)], + [("something",)], ) def test_get_func_full_args_all_arguments_method(self): - arguments = [('name',), ('address', 'home'), ('age', 25), ('*args',), ('**kwargs',)] + arguments = [ + ("name",), + ("address", "home"), + ("age", 25), + ("*args",), + ("**kwargs",), + ] self.assertEqual(inspect.get_func_full_args(Person.all_kinds), arguments) self.assertEqual(inspect.get_func_full_args(Person().all_kinds), arguments) def test_get_func_full_args_all_arguments_classmethod(self): arguments = [ - ('name',), ('address', 'home'), ('age', 25), ('*args',), ('**kwargs',), + ("name",), + ("address", "home"), + ("age", 25), + ("*args",), + ("**kwargs",), ] self.assertEqual(inspect.get_func_full_args(Person.cls_all_kinds), arguments) self.assertEqual(inspect.get_func_full_args(Person().cls_all_kinds), arguments) @@ -70,14 +82,16 @@ class TestInspectMethods(unittest.TestCase): self.assertIs(inspect.method_has_no_args(Person().one_argument), False) def test_func_supports_parameter(self): - self.assertIs(inspect.func_supports_parameter(Person.all_kinds, 'address'), True) self.assertIs( - inspect.func_supports_parameter(Person().all_kinds, 'address'), + inspect.func_supports_parameter(Person.all_kinds, "address"), True + ) + self.assertIs( + inspect.func_supports_parameter(Person().all_kinds, "address"), True, ) - self.assertIs(inspect.func_supports_parameter(Person.all_kinds, 'zone'), False) + self.assertIs(inspect.func_supports_parameter(Person.all_kinds, "zone"), False) self.assertIs( - inspect.func_supports_parameter(Person().all_kinds, 'zone'), + inspect.func_supports_parameter(Person().all_kinds, "zone"), False, ) diff --git a/tests/utils_tests/test_ipv6.py b/tests/utils_tests/test_ipv6.py index 4e434f3c3a..b41778693d 100644 --- a/tests/utils_tests/test_ipv6.py +++ b/tests/utils_tests/test_ipv6.py @@ -4,54 +4,63 @@ from django.utils.ipv6 import clean_ipv6_address, is_valid_ipv6_address class TestUtilsIPv6(unittest.TestCase): - def test_validates_correct_plain_address(self): - self.assertTrue(is_valid_ipv6_address('fe80::223:6cff:fe8a:2e8a')) - self.assertTrue(is_valid_ipv6_address('2a02::223:6cff:fe8a:2e8a')) - self.assertTrue(is_valid_ipv6_address('1::2:3:4:5:6:7')) - self.assertTrue(is_valid_ipv6_address('::')) - self.assertTrue(is_valid_ipv6_address('::a')) - self.assertTrue(is_valid_ipv6_address('2::')) + self.assertTrue(is_valid_ipv6_address("fe80::223:6cff:fe8a:2e8a")) + self.assertTrue(is_valid_ipv6_address("2a02::223:6cff:fe8a:2e8a")) + self.assertTrue(is_valid_ipv6_address("1::2:3:4:5:6:7")) + self.assertTrue(is_valid_ipv6_address("::")) + self.assertTrue(is_valid_ipv6_address("::a")) + self.assertTrue(is_valid_ipv6_address("2::")) def test_validates_correct_with_v4mapping(self): - self.assertTrue(is_valid_ipv6_address('::ffff:254.42.16.14')) - self.assertTrue(is_valid_ipv6_address('::ffff:0a0a:0a0a')) + self.assertTrue(is_valid_ipv6_address("::ffff:254.42.16.14")) + self.assertTrue(is_valid_ipv6_address("::ffff:0a0a:0a0a")) def test_validates_incorrect_plain_address(self): - self.assertFalse(is_valid_ipv6_address('foo')) - self.assertFalse(is_valid_ipv6_address('127.0.0.1')) - self.assertFalse(is_valid_ipv6_address('12345::')) - self.assertFalse(is_valid_ipv6_address('1::2:3::4')) - self.assertFalse(is_valid_ipv6_address('1::zzz')) - self.assertFalse(is_valid_ipv6_address('1::2:3:4:5:6:7:8')) - self.assertFalse(is_valid_ipv6_address('1:2')) - self.assertFalse(is_valid_ipv6_address('1:::2')) - self.assertFalse(is_valid_ipv6_address('fe80::223: 6cff:fe8a:2e8a')) - self.assertFalse(is_valid_ipv6_address('2a02::223:6cff :fe8a:2e8a')) + self.assertFalse(is_valid_ipv6_address("foo")) + self.assertFalse(is_valid_ipv6_address("127.0.0.1")) + self.assertFalse(is_valid_ipv6_address("12345::")) + self.assertFalse(is_valid_ipv6_address("1::2:3::4")) + self.assertFalse(is_valid_ipv6_address("1::zzz")) + self.assertFalse(is_valid_ipv6_address("1::2:3:4:5:6:7:8")) + self.assertFalse(is_valid_ipv6_address("1:2")) + self.assertFalse(is_valid_ipv6_address("1:::2")) + self.assertFalse(is_valid_ipv6_address("fe80::223: 6cff:fe8a:2e8a")) + self.assertFalse(is_valid_ipv6_address("2a02::223:6cff :fe8a:2e8a")) def test_validates_incorrect_with_v4mapping(self): - self.assertFalse(is_valid_ipv6_address('::ffff:999.42.16.14')) - self.assertFalse(is_valid_ipv6_address('::ffff:zzzz:0a0a')) + self.assertFalse(is_valid_ipv6_address("::ffff:999.42.16.14")) + self.assertFalse(is_valid_ipv6_address("::ffff:zzzz:0a0a")) # The ::1.2.3.4 format used to be valid but was deprecated # in rfc4291 section 2.5.5.1 - self.assertTrue(is_valid_ipv6_address('::254.42.16.14')) - self.assertTrue(is_valid_ipv6_address('::0a0a:0a0a')) - self.assertFalse(is_valid_ipv6_address('::999.42.16.14')) - self.assertFalse(is_valid_ipv6_address('::zzzz:0a0a')) + self.assertTrue(is_valid_ipv6_address("::254.42.16.14")) + self.assertTrue(is_valid_ipv6_address("::0a0a:0a0a")) + self.assertFalse(is_valid_ipv6_address("::999.42.16.14")) + self.assertFalse(is_valid_ipv6_address("::zzzz:0a0a")) def test_cleans_plain_address(self): - self.assertEqual(clean_ipv6_address('DEAD::0:BEEF'), 'dead::beef') - self.assertEqual(clean_ipv6_address('2001:000:a:0000:0:fe:fe:beef'), '2001:0:a::fe:fe:beef') - self.assertEqual(clean_ipv6_address('2001::a:0000:0:fe:fe:beef'), '2001:0:a::fe:fe:beef') + self.assertEqual(clean_ipv6_address("DEAD::0:BEEF"), "dead::beef") + self.assertEqual( + clean_ipv6_address("2001:000:a:0000:0:fe:fe:beef"), "2001:0:a::fe:fe:beef" + ) + self.assertEqual( + clean_ipv6_address("2001::a:0000:0:fe:fe:beef"), "2001:0:a::fe:fe:beef" + ) def test_cleans_with_v4_mapping(self): - self.assertEqual(clean_ipv6_address('::ffff:0a0a:0a0a'), '::ffff:10.10.10.10') - self.assertEqual(clean_ipv6_address('::ffff:1234:1234'), '::ffff:18.52.18.52') - self.assertEqual(clean_ipv6_address('::ffff:18.52.18.52'), '::ffff:18.52.18.52') - self.assertEqual(clean_ipv6_address('::ffff:0.52.18.52'), '::ffff:0.52.18.52') - self.assertEqual(clean_ipv6_address('::ffff:0.0.0.0'), '::ffff:0.0.0.0') + self.assertEqual(clean_ipv6_address("::ffff:0a0a:0a0a"), "::ffff:10.10.10.10") + self.assertEqual(clean_ipv6_address("::ffff:1234:1234"), "::ffff:18.52.18.52") + self.assertEqual(clean_ipv6_address("::ffff:18.52.18.52"), "::ffff:18.52.18.52") + self.assertEqual(clean_ipv6_address("::ffff:0.52.18.52"), "::ffff:0.52.18.52") + self.assertEqual(clean_ipv6_address("::ffff:0.0.0.0"), "::ffff:0.0.0.0") def test_unpacks_ipv4(self): - self.assertEqual(clean_ipv6_address('::ffff:0a0a:0a0a', unpack_ipv4=True), '10.10.10.10') - self.assertEqual(clean_ipv6_address('::ffff:1234:1234', unpack_ipv4=True), '18.52.18.52') - self.assertEqual(clean_ipv6_address('::ffff:18.52.18.52', unpack_ipv4=True), '18.52.18.52') + self.assertEqual( + clean_ipv6_address("::ffff:0a0a:0a0a", unpack_ipv4=True), "10.10.10.10" + ) + self.assertEqual( + clean_ipv6_address("::ffff:1234:1234", unpack_ipv4=True), "18.52.18.52" + ) + self.assertEqual( + clean_ipv6_address("::ffff:18.52.18.52", unpack_ipv4=True), "18.52.18.52" + ) diff --git a/tests/utils_tests/test_jslex.py b/tests/utils_tests/test_jslex.py index 0afb329188..0963dd0f16 100644 --- a/tests/utils_tests/test_jslex.py +++ b/tests/utils_tests/test_jslex.py @@ -9,30 +9,60 @@ class JsTokensTest(SimpleTestCase): LEX_CASES = [ # ids ("a ABC $ _ a123", ["id a", "id ABC", "id $", "id _", "id a123"]), - ("\\u1234 abc\\u0020 \\u0065_\\u0067", ["id \\u1234", "id abc\\u0020", "id \\u0065_\\u0067"]), + ( + "\\u1234 abc\\u0020 \\u0065_\\u0067", + ["id \\u1234", "id abc\\u0020", "id \\u0065_\\u0067"], + ), # numbers - ("123 1.234 0.123e-3 0 1E+40 1e1 .123", [ - "dnum 123", "dnum 1.234", "dnum 0.123e-3", "dnum 0", "dnum 1E+40", - "dnum 1e1", "dnum .123", - ]), + ( + "123 1.234 0.123e-3 0 1E+40 1e1 .123", + [ + "dnum 123", + "dnum 1.234", + "dnum 0.123e-3", + "dnum 0", + "dnum 1E+40", + "dnum 1e1", + "dnum .123", + ], + ), ("0x1 0xabCD 0XABcd", ["hnum 0x1", "hnum 0xabCD", "hnum 0XABcd"]), ("010 0377 090", ["onum 010", "onum 0377", "dnum 0", "dnum 90"]), ("0xa123ghi", ["hnum 0xa123", "id ghi"]), # keywords - ("function Function FUNCTION", ["keyword function", "id Function", "id FUNCTION"]), - ("const constructor in inherits", ["keyword const", "id constructor", "keyword in", "id inherits"]), + ( + "function Function FUNCTION", + ["keyword function", "id Function", "id FUNCTION"], + ), + ( + "const constructor in inherits", + ["keyword const", "id constructor", "keyword in", "id inherits"], + ), ("true true_enough", ["reserved true", "id true_enough"]), # strings - (''' 'hello' "hello" ''', ["string 'hello'", 'string "hello"']), - (r""" 'don\'t' "don\"t" '"' "'" '\'' "\"" """, [ - r"""string 'don\'t'""", r'''string "don\"t"''', r"""string '"'""", - r'''string "'"''', r"""string '\''""", r'''string "\""''' - ]), + (""" 'hello' "hello" """, ["string 'hello'", 'string "hello"']), + ( + r""" 'don\'t' "don\"t" '"' "'" '\'' "\"" """, + [ + r"""string 'don\'t'""", + r'''string "don\"t"''', + r"""string '"'""", + r'''string "'"''', + r"""string '\''""", + r'''string "\""''', + ], + ), (r'"ƃuıxǝ⅂ ʇdıɹɔsɐʌɐſ\""', [r'string "ƃuıxǝ⅂ ʇdıɹɔsɐʌɐſ\""']), # comments ("a//b", ["id a", "linecomment //b"]), - ("/****/a/=2//hello", ["comment /****/", "id a", "punct /=", "dnum 2", "linecomment //hello"]), - ("/*\n * Header\n */\na=1;", ["comment /*\n * Header\n */", "id a", "punct =", "dnum 1", "punct ;"]), + ( + "/****/a/=2//hello", + ["comment /****/", "id a", "punct /=", "dnum 2", "linecomment //hello"], + ), + ( + "/*\n * Header\n */\na=1;", + ["comment /*\n * Header\n */", "id a", "punct =", "dnum 1", "punct ;"], + ), # punctuation ("a+++b", ["id a", "punct ++", "punct +", "id b"]), # regex @@ -40,35 +70,84 @@ class JsTokensTest(SimpleTestCase): (r"a=/a*[^/]+/,1", ["id a", "punct =", "regex /a*[^/]+/", "punct ,", "dnum 1"]), (r"a=/a*\[^/,1", ["id a", "punct =", r"regex /a*\[^/", "punct ,", "dnum 1"]), (r"a=/\//,1", ["id a", "punct =", r"regex /\//", "punct ,", "dnum 1"]), - # next two are from https://www-archive.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions # NOQA ( """for (var x = a in foo && "</x>" || mot ? z:/x:3;x<5;y</g/i) {xyz(x++);}""", [ - "keyword for", "punct (", "keyword var", "id x", "punct =", - "id a", "keyword in", "id foo", "punct &&", 'string "</x>"', - "punct ||", "id mot", "punct ?", "id z", "punct :", - "regex /x:3;x<5;y</g", "punct /", "id i", "punct )", "punct {", - "id xyz", "punct (", "id x", "punct ++", "punct )", "punct ;", - "punct }" + "keyword for", + "punct (", + "keyword var", + "id x", + "punct =", + "id a", + "keyword in", + "id foo", + "punct &&", + 'string "</x>"', + "punct ||", + "id mot", + "punct ?", + "id z", + "punct :", + "regex /x:3;x<5;y</g", + "punct /", + "id i", + "punct )", + "punct {", + "id xyz", + "punct (", + "id x", + "punct ++", + "punct )", + "punct ;", + "punct }", ], ), ( """for (var x = a in foo && "</x>" || mot ? z/x:3;x<5;y</g/i) {xyz(x++);}""", [ - "keyword for", "punct (", "keyword var", "id x", "punct =", - "id a", "keyword in", "id foo", "punct &&", 'string "</x>"', - "punct ||", "id mot", "punct ?", "id z", "punct /", "id x", - "punct :", "dnum 3", "punct ;", "id x", "punct <", "dnum 5", - "punct ;", "id y", "punct <", "regex /g/i", "punct )", - "punct {", "id xyz", "punct (", "id x", "punct ++", "punct )", - "punct ;", "punct }", + "keyword for", + "punct (", + "keyword var", + "id x", + "punct =", + "id a", + "keyword in", + "id foo", + "punct &&", + 'string "</x>"', + "punct ||", + "id mot", + "punct ?", + "id z", + "punct /", + "id x", + "punct :", + "dnum 3", + "punct ;", + "id x", + "punct <", + "dnum 5", + "punct ;", + "id y", + "punct <", + "regex /g/i", + "punct )", + "punct {", + "id xyz", + "punct (", + "id x", + "punct ++", + "punct )", + "punct ;", + "punct }", ], ), - # Various "illegal" regexes that are valid according to the std. - (r"""/????/, /++++/, /[----]/ """, ["regex /????/", "punct ,", "regex /++++/", "punct ,", "regex /[----]/"]), - + ( + r"""/????/, /++++/, /[----]/ """, + ["regex /????/", "punct ,", "regex /++++/", "punct ,", "regex /[----]/"], + ), # Stress cases from https://stackoverflow.com/questions/5533925/what-javascript-constructs-does-jslex-incorrectly-lex/5573409#5573409 # NOQA (r"""/\[/""", [r"""regex /\[/"""]), (r"""/[i]/""", [r"""regex /[i]/"""]), @@ -86,16 +165,34 @@ class JsTokensTest(SimpleTestCase): NUMERIC_LITERAL: /^[0-9]+(?:\.[0-9]*(?:[eE][-+][0-9]+)?)?/, SYMBOL: /^(?:==|=|<>|<=|<|>=|>|!~~|!~|~~|~|!==|!=|!~=|!~|!|&|\||\.|\:|,|\(|\)|\[|\]|\{|\}|\?|\:|;|@|\^|\/\+|\/|\*|\+|-)/ }; - """, # NOQA + """, # NOQA [ - "id rexl", "punct .", "id re", "punct =", "punct {", - "id NAME", "punct :", r"""regex /^(?![0-9])(?:\w)+|^"(?:[^"]|"")+"/""", "punct ,", - "id UNQUOTED_LITERAL", "punct :", r"""regex /^@(?:(?![0-9])(?:\w|\:)+|^"(?:[^"]|"")+")\[[^\]]+\]/""", - "punct ,", - "id QUOTED_LITERAL", "punct :", r"""regex /^'(?:[^']|'')*'/""", "punct ,", - "id NUMERIC_LITERAL", "punct :", r"""regex /^[0-9]+(?:\.[0-9]*(?:[eE][-+][0-9]+)?)?/""", "punct ,", - "id SYMBOL", "punct :", r"""regex /^(?:==|=|<>|<=|<|>=|>|!~~|!~|~~|~|!==|!=|!~=|!~|!|&|\||\.|\:|,|\(|\)|\[|\]|\{|\}|\?|\:|;|@|\^|\/\+|\/|\*|\+|-)/""", # NOQA - "punct }", "punct ;" + "id rexl", + "punct .", + "id re", + "punct =", + "punct {", + "id NAME", + "punct :", + r"""regex /^(?![0-9])(?:\w)+|^"(?:[^"]|"")+"/""", + "punct ,", + "id UNQUOTED_LITERAL", + "punct :", + r"""regex /^@(?:(?![0-9])(?:\w|\:)+|^"(?:[^"]|"")+")\[[^\]]+\]/""", + "punct ,", + "id QUOTED_LITERAL", + "punct :", + r"""regex /^'(?:[^']|'')*'/""", + "punct ,", + "id NUMERIC_LITERAL", + "punct :", + r"""regex /^[0-9]+(?:\.[0-9]*(?:[eE][-+][0-9]+)?)?/""", + "punct ,", + "id SYMBOL", + "punct :", + r"""regex /^(?:==|=|<>|<=|<|>=|>|!~~|!~|~~|~|!==|!=|!~=|!~|!|&|\||\.|\:|,|\(|\)|\[|\]|\{|\}|\?|\:|;|@|\^|\/\+|\/|\*|\+|-)/""", # NOQA + "punct }", + "punct ;", ], ), ( @@ -110,31 +207,80 @@ class JsTokensTest(SimpleTestCase): str = '"'; """, # NOQA [ - "id rexl", "punct .", "id re", "punct =", "punct {", - "id NAME", "punct :", r"""regex /^(?![0-9])(?:\w)+|^"(?:[^"]|"")+"/""", "punct ,", - "id UNQUOTED_LITERAL", "punct :", r"""regex /^@(?:(?![0-9])(?:\w|\:)+|^"(?:[^"]|"")+")\[[^\]]+\]/""", + "id rexl", + "punct .", + "id re", + "punct =", + "punct {", + "id NAME", + "punct :", + r"""regex /^(?![0-9])(?:\w)+|^"(?:[^"]|"")+"/""", + "punct ,", + "id UNQUOTED_LITERAL", + "punct :", + r"""regex /^@(?:(?![0-9])(?:\w|\:)+|^"(?:[^"]|"")+")\[[^\]]+\]/""", + "punct ,", + "id QUOTED_LITERAL", + "punct :", + r"""regex /^'(?:[^']|'')*'/""", + "punct ,", + "id NUMERIC_LITERAL", + "punct :", + r"""regex /^[0-9]+(?:\.[0-9]*(?:[eE][-+][0-9]+)?)?/""", + "punct ,", + "id SYMBOL", + "punct :", + r"""regex /^(?:==|=|<>|<=|<|>=|>|!~~|!~|~~|~|!==|!=|!~=|!~|!|&|\||\.|\:|,|\(|\)|\[|\]|\{|\}|\?|\:|;|@|\^|\/\+|\/|\*|\+|-)/""", # NOQA + "punct }", + "punct ;", + "id str", + "punct =", + """string '"'""", + "punct ;", + ], + ), + ( + r""" this._js = "e.str(\"" + this.value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"") + "\")"; """, + [ + "keyword this", + "punct .", + "id _js", + "punct =", + r'''string "e.str(\""''', + "punct +", + "keyword this", + "punct .", + "id value", + "punct .", + "id replace", + "punct (", + r"regex /\\/g", "punct ,", - "id QUOTED_LITERAL", "punct :", r"""regex /^'(?:[^']|'')*'/""", "punct ,", - "id NUMERIC_LITERAL", "punct :", r"""regex /^[0-9]+(?:\.[0-9]*(?:[eE][-+][0-9]+)?)?/""", "punct ,", - "id SYMBOL", "punct :", r"""regex /^(?:==|=|<>|<=|<|>=|>|!~~|!~|~~|~|!==|!=|!~=|!~|!|&|\||\.|\:|,|\(|\)|\[|\]|\{|\}|\?|\:|;|@|\^|\/\+|\/|\*|\+|-)/""", # NOQA - "punct }", "punct ;", - "id str", "punct =", """string '"'""", "punct ;", + r'string "\\\\"', + "punct )", + "punct .", + "id replace", + "punct (", + r'regex /"/g', + "punct ,", + r'string "\\\""', + "punct )", + "punct +", + r'string "\")"', + "punct ;", ], ), - (r""" this._js = "e.str(\"" + this.value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"") + "\")"; """, - ["keyword this", "punct .", "id _js", "punct =", r'''string "e.str(\""''', "punct +", "keyword this", - "punct .", "id value", "punct .", "id replace", "punct (", r"regex /\\/g", "punct ,", r'string "\\\\"', - "punct )", - "punct .", "id replace", "punct (", r'regex /"/g', "punct ,", r'string "\\\""', "punct )", "punct +", - r'string "\")"', "punct ;"]), ] def make_function(input, toks): def test_func(self): lexer = JsLexer() - result = ["%s %s" % (name, tok) for name, tok in lexer.lex(input) if name != 'ws'] + result = [ + "%s %s" % (name, tok) for name, tok in lexer.lex(input) if name != "ws" + ] self.assertEqual(result, toks) + return test_func @@ -153,8 +299,9 @@ GETTEXT_CASES = ( a = 1; /* /[0-9]+/ */ b = 0x2a0b / 1; // /[0-9]+/ c = 3; - """ - ), ( + """, + ), + ( r""" a = 1.234e-5; /* @@ -168,8 +315,9 @@ GETTEXT_CASES = ( * /[0-9+/ */ b = .0123; - """ - ), ( + """, + ), + ( r""" x = y / z; alert(gettext("hello")); @@ -179,8 +327,9 @@ GETTEXT_CASES = ( x = y / z; alert(gettext("hello")); x /= 3; - """ - ), ( + """, + ), + ( r""" s = "Hello \"th/foo/ere\""; s = 'He\x23llo \'th/foo/ere\''; @@ -190,8 +339,9 @@ GETTEXT_CASES = ( s = "Hello \"th/foo/ere\""; s = "He\x23llo \'th/foo/ere\'"; s = "slash quote \", just quote \""; - """ - ), ( + """, + ), + ( r""" s = "Line continuation\ continued /hello/ still the string";/hello/; @@ -199,8 +349,9 @@ GETTEXT_CASES = ( r""" s = "Line continuation\ continued /hello/ still the string";"REGEX"; - """ - ), ( + """, + ), + ( r""" var regex = /pattern/; var regex2 = /matter/gm; @@ -210,8 +361,9 @@ GETTEXT_CASES = ( var regex = "REGEX"; var regex2 = "REGEX"; var regex3 = "REGEX".foo("hey"); - """ - ), ( + """, + ), + ( r""" for (var x = a in foo && "</x>" || mot ? z:/x:3;x<5;y</g/i) {xyz(x++);} for (var x = a in foo && "</x>" || mot ? z/x:3;x<5;y</g/i) {xyz(x++);} @@ -219,14 +371,16 @@ GETTEXT_CASES = ( r""" for (var x = a in foo && "</x>" || mot ? z:"REGEX"/i) {xyz(x++);} for (var x = a in foo && "</x>" || mot ? z/x:3;x<5;y<"REGEX") {xyz(x++);} - """ - ), ( + """, + ), + ( """ \\u1234xyz = gettext('Hello there'); - """, r""" + """, + r""" Uu1234xyz = gettext("Hello there"); - """ - ) + """, + ), ) @@ -237,6 +391,7 @@ class JsToCForGettextTest(SimpleTestCase): def make_function(js, c): def test_func(self): self.assertEqual(prepare_js_for_gettext(js), c) + return test_func diff --git a/tests/utils_tests/test_lazyobject.py b/tests/utils_tests/test_lazyobject.py index e5bccc6362..131d893a44 100644 --- a/tests/utils_tests/test_lazyobject.py +++ b/tests/utils_tests/test_lazyobject.py @@ -13,7 +13,8 @@ class Foo: """ A simple class with just one attribute. """ - foo = 'bar' + + foo = "bar" def __eq__(self, other): return self.foo == other.foo @@ -24,6 +25,7 @@ class LazyObjectTestCase(TestCase): """ Wrap the given object into a LazyObject """ + class AdHocLazyObject(LazyObject): def _setup(self): self._wrapped = wrapped_object @@ -32,39 +34,39 @@ class LazyObjectTestCase(TestCase): def test_getattr(self): obj = self.lazy_wrap(Foo()) - self.assertEqual(obj.foo, 'bar') + self.assertEqual(obj.foo, "bar") def test_setattr(self): obj = self.lazy_wrap(Foo()) - obj.foo = 'BAR' - obj.bar = 'baz' - self.assertEqual(obj.foo, 'BAR') - self.assertEqual(obj.bar, 'baz') + obj.foo = "BAR" + obj.bar = "baz" + self.assertEqual(obj.foo, "BAR") + self.assertEqual(obj.bar, "baz") def test_setattr2(self): # Same as test_setattr but in reversed order obj = self.lazy_wrap(Foo()) - obj.bar = 'baz' - obj.foo = 'BAR' - self.assertEqual(obj.foo, 'BAR') - self.assertEqual(obj.bar, 'baz') + obj.bar = "baz" + obj.foo = "BAR" + self.assertEqual(obj.foo, "BAR") + self.assertEqual(obj.bar, "baz") def test_delattr(self): obj = self.lazy_wrap(Foo()) - obj.bar = 'baz' - self.assertEqual(obj.bar, 'baz') + obj.bar = "baz" + self.assertEqual(obj.bar, "baz") del obj.bar with self.assertRaises(AttributeError): obj.bar def test_cmp(self): - obj1 = self.lazy_wrap('foo') - obj2 = self.lazy_wrap('bar') - obj3 = self.lazy_wrap('foo') - self.assertEqual(obj1, 'foo') + obj1 = self.lazy_wrap("foo") + obj2 = self.lazy_wrap("bar") + obj3 = self.lazy_wrap("foo") + self.assertEqual(obj1, "foo") self.assertEqual(obj1, obj3) self.assertNotEqual(obj1, obj2) - self.assertNotEqual(obj1, 'bar') + self.assertNotEqual(obj1, "bar") def test_lt(self): obj1 = self.lazy_wrap(1) @@ -77,12 +79,12 @@ class LazyObjectTestCase(TestCase): self.assertGreater(obj2, obj1) def test_bytes(self): - obj = self.lazy_wrap(b'foo') - self.assertEqual(bytes(obj), b'foo') + obj = self.lazy_wrap(b"foo") + self.assertEqual(bytes(obj), b"foo") def test_text(self): - obj = self.lazy_wrap('foo') - self.assertEqual(str(obj), 'foo') + obj = self.lazy_wrap("foo") + self.assertEqual(str(obj), "foo") def test_bool(self): # Refs #21840 @@ -92,11 +94,11 @@ class LazyObjectTestCase(TestCase): self.assertTrue(t) def test_dir(self): - obj = self.lazy_wrap('foo') - self.assertEqual(dir(obj), dir('foo')) + obj = self.lazy_wrap("foo") + self.assertEqual(dir(obj), dir("foo")) def test_len(self): - for seq in ['asd', [1, 2, 3], {'a': 1, 'b': 2, 'c': 3}]: + for seq in ["asd", [1, 2, 3], {"a": 1, "b": 2, "c": 3}]: obj = self.lazy_wrap(seq) self.assertEqual(len(obj), 3) @@ -109,16 +111,16 @@ class LazyObjectTestCase(TestCase): self.assertIsInstance(self.lazy_wrap(Bar()), Foo) def test_hash(self): - obj = self.lazy_wrap('foo') - d = {obj: 'bar'} - self.assertIn('foo', d) - self.assertEqual(d['foo'], 'bar') + obj = self.lazy_wrap("foo") + d = {obj: "bar"} + self.assertIn("foo", d) + self.assertEqual(d["foo"], "bar") def test_contains(self): test_data = [ - ('c', 'abcde'), + ("c", "abcde"), (2, [1, 2, 3]), - ('a', {'a': 1, 'b': 2, 'c': 3}), + ("a", {"a": 1, "b": 2, "c": 3}), (2, {1, 2, 3}), ] for needle, haystack in test_data: @@ -131,70 +133,66 @@ class LazyObjectTestCase(TestCase): def test_getitem(self): obj_list = self.lazy_wrap([1, 2, 3]) - obj_dict = self.lazy_wrap({'a': 1, 'b': 2, 'c': 3}) + obj_dict = self.lazy_wrap({"a": 1, "b": 2, "c": 3}) self.assertEqual(obj_list[0], 1) self.assertEqual(obj_list[-1], 3) self.assertEqual(obj_list[1:2], [2]) - self.assertEqual(obj_dict['b'], 2) + self.assertEqual(obj_dict["b"], 2) with self.assertRaises(IndexError): obj_list[3] with self.assertRaises(KeyError): - obj_dict['f'] + obj_dict["f"] def test_setitem(self): obj_list = self.lazy_wrap([1, 2, 3]) - obj_dict = self.lazy_wrap({'a': 1, 'b': 2, 'c': 3}) + obj_dict = self.lazy_wrap({"a": 1, "b": 2, "c": 3}) obj_list[0] = 100 self.assertEqual(obj_list, [100, 2, 3]) obj_list[1:2] = [200, 300, 400] self.assertEqual(obj_list, [100, 200, 300, 400, 3]) - obj_dict['a'] = 100 - obj_dict['d'] = 400 - self.assertEqual(obj_dict, {'a': 100, 'b': 2, 'c': 3, 'd': 400}) + obj_dict["a"] = 100 + obj_dict["d"] = 400 + self.assertEqual(obj_dict, {"a": 100, "b": 2, "c": 3, "d": 400}) def test_delitem(self): obj_list = self.lazy_wrap([1, 2, 3]) - obj_dict = self.lazy_wrap({'a': 1, 'b': 2, 'c': 3}) + obj_dict = self.lazy_wrap({"a": 1, "b": 2, "c": 3}) del obj_list[-1] - del obj_dict['c'] + del obj_dict["c"] self.assertEqual(obj_list, [1, 2]) - self.assertEqual(obj_dict, {'a': 1, 'b': 2}) + self.assertEqual(obj_dict, {"a": 1, "b": 2}) with self.assertRaises(IndexError): del obj_list[3] with self.assertRaises(KeyError): - del obj_dict['f'] + del obj_dict["f"] def test_iter(self): # Tests whether an object's custom `__iter__` method is being # used when iterating over it. class IterObject: - def __init__(self, values): self.values = values def __iter__(self): return iter(self.values) - original_list = ['test', '123'] - self.assertEqual( - list(self.lazy_wrap(IterObject(original_list))), - original_list - ) + original_list = ["test", "123"] + self.assertEqual(list(self.lazy_wrap(IterObject(original_list))), original_list) def test_pickle(self): # See ticket #16563 obj = self.lazy_wrap(Foo()) - obj.bar = 'baz' + obj.bar = "baz" pickled = pickle.dumps(obj) unpickled = pickle.loads(pickled) self.assertIsInstance(unpickled, Foo) @@ -311,21 +309,23 @@ class SimpleLazyObjectTestCase(LazyObjectTestCase): obj = self.lazy_wrap(42) # __repr__ contains __repr__ of setup function and does not evaluate # the SimpleLazyObject - self.assertRegex(repr(obj), '^<SimpleLazyObject:') + self.assertRegex(repr(obj), "^<SimpleLazyObject:") self.assertIs(obj._wrapped, empty) # make sure evaluation hasn't been triggered self.assertEqual(obj, 42) # evaluate the lazy object self.assertIsInstance(obj._wrapped, int) - self.assertEqual(repr(obj), '<SimpleLazyObject: 42>') + self.assertEqual(repr(obj), "<SimpleLazyObject: 42>") def test_trace(self): # See ticket #19456 old_trace_func = sys.gettrace() try: + def trace_func(frame, event, arg): - frame.f_locals['self'].__class__ + frame.f_locals["self"].__class__ if old_trace_func is not None: old_trace_func(frame, event, arg) + sys.settrace(trace_func) self.lazy_wrap(None) finally: @@ -346,16 +346,16 @@ class SimpleLazyObjectTestCase(LazyObjectTestCase): def test_dict(self): # See ticket #18447 - lazydict = SimpleLazyObject(lambda: {'one': 1}) - self.assertEqual(lazydict['one'], 1) - lazydict['one'] = -1 - self.assertEqual(lazydict['one'], -1) - self.assertIn('one', lazydict) - self.assertNotIn('two', lazydict) + lazydict = SimpleLazyObject(lambda: {"one": 1}) + self.assertEqual(lazydict["one"], 1) + lazydict["one"] = -1 + self.assertEqual(lazydict["one"], -1) + self.assertIn("one", lazydict) + self.assertNotIn("two", lazydict) self.assertEqual(len(lazydict), 1) - del lazydict['one'] + del lazydict["one"] with self.assertRaises(KeyError): - lazydict['one'] + lazydict["one"] def test_list_set(self): lazy_list = SimpleLazyObject(lambda: [1, 2, 3, 4, 5]) @@ -373,17 +373,18 @@ class BaseBaz: A base class with a funky __reduce__ method, meant to simulate the __reduce__ method of Model, which sets self._django_version. """ + def __init__(self): - self.baz = 'wrong' + self.baz = "wrong" def __reduce__(self): - self.baz = 'right' + self.baz = "right" return super().__reduce__() def __eq__(self, other): if self.__class__ != other.__class__: return False - for attr in ['bar', 'baz', 'quux']: + for attr in ["bar", "baz", "quux"]: if hasattr(self, attr) != hasattr(other, attr): return False elif getattr(self, attr, None) != getattr(other, attr, None): @@ -395,12 +396,13 @@ class Baz(BaseBaz): """ A class that inherits from BaseBaz and has its own __reduce_ex__ method. """ + def __init__(self, bar): self.bar = bar super().__init__() def __reduce_ex__(self, proto): - self.quux = 'quux' + self.quux = "quux" return super().__reduce_ex__(proto) @@ -410,6 +412,7 @@ class BazProxy(Baz): dicts, which simulates some crazy things that people might do with e.g. proxy models. """ + def __init__(self, baz): self.__dict__ = baz.__dict__ self._baz = baz @@ -422,6 +425,7 @@ class SimpleLazyObjectPickleTestCase(TestCase): Regression test for pickling a SimpleLazyObject wrapping a model (#25389). Also covers other classes with a custom __reduce__ method. """ + def test_pickle_with_reduce(self): """ Test in a fairly synthetic setting. @@ -437,7 +441,7 @@ class SimpleLazyObjectPickleTestCase(TestCase): pickled = pickle.dumps(obj, protocol) unpickled = pickle.loads(pickled) self.assertEqual(unpickled, obj) - self.assertEqual(unpickled.baz, 'right') + self.assertEqual(unpickled.baz, "right") def test_pickle_model(self): """ @@ -452,7 +456,11 @@ class SimpleLazyObjectPickleTestCase(TestCase): lazy_category.categoryinfo lazy_category_2 = SimpleLazyObject(lambda: category) with warnings.catch_warnings(record=True) as recorded: - self.assertEqual(pickle.loads(pickle.dumps(lazy_category, protocol)), category) - self.assertEqual(pickle.loads(pickle.dumps(lazy_category_2, protocol)), category) + self.assertEqual( + pickle.loads(pickle.dumps(lazy_category, protocol)), category + ) + self.assertEqual( + pickle.loads(pickle.dumps(lazy_category_2, protocol)), category + ) # Assert that there were no warnings. self.assertEqual(len(recorded), 0) diff --git a/tests/utils_tests/test_lorem_ipsum.py b/tests/utils_tests/test_lorem_ipsum.py index 78c6a3a410..deda09c717 100644 --- a/tests/utils_tests/test_lorem_ipsum.py +++ b/tests/utils_tests/test_lorem_ipsum.py @@ -9,20 +9,20 @@ class LoremIpsumTests(unittest.TestCase): """words(n) returns n + 19 words, even if n is negative.""" self.assertEqual( words(-5), - 'lorem ipsum dolor sit amet consectetur adipisicing elit sed do ' - 'eiusmod tempor incididunt ut' + "lorem ipsum dolor sit amet consectetur adipisicing elit sed do " + "eiusmod tempor incididunt ut", ) def test_same_or_less_common_words(self): """words(n) for n < 19.""" - self.assertEqual(words(7), 'lorem ipsum dolor sit amet consectetur adipisicing') + self.assertEqual(words(7), "lorem ipsum dolor sit amet consectetur adipisicing") def test_common_words_in_string(self): """words(n) starts with the 19 standard lorem ipsum words for n > 19.""" self.assertTrue( words(25).startswith( - 'lorem ipsum dolor sit amet consectetur adipisicing elit sed ' - 'do eiusmod tempor incididunt ut labore et dolore magna aliqua' + "lorem ipsum dolor sit amet consectetur adipisicing elit sed " + "do eiusmod tempor incididunt ut labore et dolore magna aliqua" ) ) @@ -34,59 +34,64 @@ class LoremIpsumTests(unittest.TestCase): """words(n) has n words when n is greater than len(WORDS).""" self.assertEqual(len(words(500).split()), 500) - @mock.patch('django.utils.lorem_ipsum.random.sample') + @mock.patch("django.utils.lorem_ipsum.random.sample") def test_not_common_words(self, mock_sample): """words(n, common=False) returns random words.""" - mock_sample.return_value = ['exercitationem', 'perferendis'] - self.assertEqual(words(2, common=False), 'exercitationem perferendis') + mock_sample.return_value = ["exercitationem", "perferendis"] + self.assertEqual(words(2, common=False), "exercitationem perferendis") def test_sentence_starts_with_capital(self): """A sentence starts with a capital letter.""" self.assertTrue(sentence()[0].isupper()) - @mock.patch('django.utils.lorem_ipsum.random.sample') - @mock.patch('django.utils.lorem_ipsum.random.choice') - @mock.patch('django.utils.lorem_ipsum.random.randint') + @mock.patch("django.utils.lorem_ipsum.random.sample") + @mock.patch("django.utils.lorem_ipsum.random.choice") + @mock.patch("django.utils.lorem_ipsum.random.randint") def test_sentence(self, mock_randint, mock_choice, mock_sample): """ Sentences are built using some number of phrases and a set of words. """ mock_randint.return_value = 2 # Use two phrases. - mock_sample.return_value = ['exercitationem', 'perferendis'] - mock_choice.return_value = '?' + mock_sample.return_value = ["exercitationem", "perferendis"] + mock_choice.return_value = "?" value = sentence() self.assertEqual(mock_randint.call_count, 3) self.assertEqual(mock_sample.call_count, 2) self.assertEqual(mock_choice.call_count, 1) - self.assertEqual(value, 'Exercitationem perferendis, exercitationem perferendis?') + self.assertEqual( + value, "Exercitationem perferendis, exercitationem perferendis?" + ) - @mock.patch('django.utils.lorem_ipsum.random.choice') + @mock.patch("django.utils.lorem_ipsum.random.choice") def test_sentence_ending(self, mock_choice): """Sentences end with a question mark or a period.""" - mock_choice.return_value = '?' - self.assertIn(sentence()[-1], '?') - mock_choice.return_value = '.' - self.assertIn(sentence()[-1], '.') + mock_choice.return_value = "?" + self.assertIn(sentence()[-1], "?") + mock_choice.return_value = "." + self.assertIn(sentence()[-1], ".") - @mock.patch('django.utils.lorem_ipsum.random.sample') - @mock.patch('django.utils.lorem_ipsum.random.choice') - @mock.patch('django.utils.lorem_ipsum.random.randint') + @mock.patch("django.utils.lorem_ipsum.random.sample") + @mock.patch("django.utils.lorem_ipsum.random.choice") + @mock.patch("django.utils.lorem_ipsum.random.randint") def test_paragraph(self, mock_paragraph_randint, mock_choice, mock_sample): """paragraph() generates a single paragraph.""" # Make creating 2 sentences use 2 phrases. mock_paragraph_randint.return_value = 2 - mock_sample.return_value = ['exercitationem', 'perferendis'] - mock_choice.return_value = '.' + mock_sample.return_value = ["exercitationem", "perferendis"] + mock_choice.return_value = "." value = paragraph() self.assertEqual(mock_paragraph_randint.call_count, 7) - self.assertEqual(value, ( - 'Exercitationem perferendis, exercitationem perferendis. ' - 'Exercitationem perferendis, exercitationem perferendis.' - )) + self.assertEqual( + value, + ( + "Exercitationem perferendis, exercitationem perferendis. " + "Exercitationem perferendis, exercitationem perferendis." + ), + ) - @mock.patch('django.utils.lorem_ipsum.random.sample') - @mock.patch('django.utils.lorem_ipsum.random.choice') - @mock.patch('django.utils.lorem_ipsum.random.randint') + @mock.patch("django.utils.lorem_ipsum.random.sample") + @mock.patch("django.utils.lorem_ipsum.random.choice") + @mock.patch("django.utils.lorem_ipsum.random.randint") def test_paragraphs_not_common(self, mock_randint, mock_choice, mock_sample): """ paragraphs(1, common=False) generating one paragraph that's not the @@ -94,28 +99,29 @@ class LoremIpsumTests(unittest.TestCase): """ # Make creating 2 sentences use 2 phrases. mock_randint.return_value = 2 - mock_sample.return_value = ['exercitationem', 'perferendis'] - mock_choice.return_value = '.' + mock_sample.return_value = ["exercitationem", "perferendis"] + mock_choice.return_value = "." self.assertEqual( paragraphs(1, common=False), [ - 'Exercitationem perferendis, exercitationem perferendis. ' - 'Exercitationem perferendis, exercitationem perferendis.' - ] + "Exercitationem perferendis, exercitationem perferendis. " + "Exercitationem perferendis, exercitationem perferendis." + ], ) self.assertEqual(mock_randint.call_count, 7) def test_paragraphs(self): """paragraphs(1) uses the COMMON_P paragraph.""" self.assertEqual( - paragraphs(1), [ - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, ' - 'sed do eiusmod tempor incididunt ut labore et dolore magna ' - 'aliqua. Ut enim ad minim veniam, quis nostrud exercitation ' - 'ullamco laboris nisi ut aliquip ex ea commodo consequat. ' - 'Duis aute irure dolor in reprehenderit in voluptate velit ' - 'esse cillum dolore eu fugiat nulla pariatur. Excepteur sint ' - 'occaecat cupidatat non proident, sunt in culpa qui officia ' - 'deserunt mollit anim id est laborum.' - ] + paragraphs(1), + [ + "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " + "sed do eiusmod tempor incididunt ut labore et dolore magna " + "aliqua. Ut enim ad minim veniam, quis nostrud exercitation " + "ullamco laboris nisi ut aliquip ex ea commodo consequat. " + "Duis aute irure dolor in reprehenderit in voluptate velit " + "esse cillum dolore eu fugiat nulla pariatur. Excepteur sint " + "occaecat cupidatat non proident, sunt in culpa qui officia " + "deserunt mollit anim id est laborum." + ], ) diff --git a/tests/utils_tests/test_module/another_bad_module.py b/tests/utils_tests/test_module/another_bad_module.py index 766456242d..769bb2b246 100644 --- a/tests/utils_tests/test_module/another_bad_module.py +++ b/tests/utils_tests/test_module/another_bad_module.py @@ -1,9 +1,11 @@ from . import site -content = 'Another Bad Module' +content = "Another Bad Module" -site._registry.update({ - 'foo': 'bar', -}) +site._registry.update( + { + "foo": "bar", + } +) -raise Exception('Some random exception.') +raise Exception("Some random exception.") diff --git a/tests/utils_tests/test_module/another_good_module.py b/tests/utils_tests/test_module/another_good_module.py index eccdaa4c59..7ab8224f5f 100644 --- a/tests/utils_tests/test_module/another_good_module.py +++ b/tests/utils_tests/test_module/another_good_module.py @@ -1,7 +1,9 @@ from . import site -content = 'Another Good Module' +content = "Another Good Module" -site._registry.update({ - 'lorem': 'ipsum', -}) +site._registry.update( + { + "lorem": "ipsum", + } +) diff --git a/tests/utils_tests/test_module/bad_module.py b/tests/utils_tests/test_module/bad_module.py index 55bbdd9d3a..728799ef26 100644 --- a/tests/utils_tests/test_module/bad_module.py +++ b/tests/utils_tests/test_module/bad_module.py @@ -1,3 +1,3 @@ import a_package_name_that_does_not_exist # NOQA -content = 'Bad Module' +content = "Bad Module" diff --git a/tests/utils_tests/test_module/child_module/grandchild_module.py b/tests/utils_tests/test_module/child_module/grandchild_module.py index 3375c07f56..09bd1c4b7f 100644 --- a/tests/utils_tests/test_module/child_module/grandchild_module.py +++ b/tests/utils_tests/test_module/child_module/grandchild_module.py @@ -1 +1 @@ -content = 'Grandchild Module' +content = "Grandchild Module" diff --git a/tests/utils_tests/test_module/good_module.py b/tests/utils_tests/test_module/good_module.py index f6261c5bc8..90a0388554 100644 --- a/tests/utils_tests/test_module/good_module.py +++ b/tests/utils_tests/test_module/good_module.py @@ -1 +1 @@ -content = 'Good Module' +content = "Good Module" diff --git a/tests/utils_tests/test_module_loading.py b/tests/utils_tests/test_module_loading.py index 773c0a2735..736d456d2d 100644 --- a/tests/utils_tests/test_module_loading.py +++ b/tests/utils_tests/test_module_loading.py @@ -7,192 +7,215 @@ from zipimport import zipimporter from django.test import SimpleTestCase, modify_settings from django.test.utils import extend_sys_path from django.utils.module_loading import ( - autodiscover_modules, import_string, module_has_submodule, + autodiscover_modules, + import_string, + module_has_submodule, ) from django.utils.version import PY310 class DefaultLoader(unittest.TestCase): - def test_loader(self): "Normal module existence can be tested" - test_module = import_module('utils_tests.test_module') - test_no_submodule = import_module( - 'utils_tests.test_no_submodule') + test_module = import_module("utils_tests.test_module") + test_no_submodule = import_module("utils_tests.test_no_submodule") # An importable child - self.assertTrue(module_has_submodule(test_module, 'good_module')) - mod = import_module('utils_tests.test_module.good_module') - self.assertEqual(mod.content, 'Good Module') + self.assertTrue(module_has_submodule(test_module, "good_module")) + mod = import_module("utils_tests.test_module.good_module") + self.assertEqual(mod.content, "Good Module") # A child that exists, but will generate an import error if loaded - self.assertTrue(module_has_submodule(test_module, 'bad_module')) + self.assertTrue(module_has_submodule(test_module, "bad_module")) with self.assertRaises(ImportError): - import_module('utils_tests.test_module.bad_module') + import_module("utils_tests.test_module.bad_module") # A child that doesn't exist - self.assertFalse(module_has_submodule(test_module, 'no_such_module')) + self.assertFalse(module_has_submodule(test_module, "no_such_module")) with self.assertRaises(ImportError): - import_module('utils_tests.test_module.no_such_module') + import_module("utils_tests.test_module.no_such_module") # A child that doesn't exist, but is the name of a package on the path - self.assertFalse(module_has_submodule(test_module, 'django')) + self.assertFalse(module_has_submodule(test_module, "django")) with self.assertRaises(ImportError): - import_module('utils_tests.test_module.django') + import_module("utils_tests.test_module.django") # Don't be confused by caching of import misses import types # NOQA: causes attempted import of utils_tests.types - self.assertFalse(module_has_submodule(sys.modules['utils_tests'], 'types')) + + self.assertFalse(module_has_submodule(sys.modules["utils_tests"], "types")) # A module which doesn't have a __path__ (so no submodules) - self.assertFalse(module_has_submodule(test_no_submodule, 'anything')) + self.assertFalse(module_has_submodule(test_no_submodule, "anything")) with self.assertRaises(ImportError): - import_module('utils_tests.test_no_submodule.anything') + import_module("utils_tests.test_no_submodule.anything") def test_has_sumbodule_with_dotted_path(self): """Nested module existence can be tested.""" - test_module = import_module('utils_tests.test_module') + test_module = import_module("utils_tests.test_module") # A grandchild that exists. - self.assertIs(module_has_submodule(test_module, 'child_module.grandchild_module'), True) + self.assertIs( + module_has_submodule(test_module, "child_module.grandchild_module"), True + ) # A grandchild that doesn't exist. - self.assertIs(module_has_submodule(test_module, 'child_module.no_such_module'), False) + self.assertIs( + module_has_submodule(test_module, "child_module.no_such_module"), False + ) # A grandchild whose parent doesn't exist. - self.assertIs(module_has_submodule(test_module, 'no_such_module.grandchild_module'), False) + self.assertIs( + module_has_submodule(test_module, "no_such_module.grandchild_module"), False + ) # A grandchild whose parent is not a package. - self.assertIs(module_has_submodule(test_module, 'good_module.no_such_module'), False) + self.assertIs( + module_has_submodule(test_module, "good_module.no_such_module"), False + ) class EggLoader(unittest.TestCase): def setUp(self): - self.egg_dir = '%s/eggs' % os.path.dirname(__file__) + self.egg_dir = "%s/eggs" % os.path.dirname(__file__) def tearDown(self): sys.path_importer_cache.clear() - sys.modules.pop('egg_module.sub1.sub2.bad_module', None) - sys.modules.pop('egg_module.sub1.sub2.good_module', None) - sys.modules.pop('egg_module.sub1.sub2', None) - sys.modules.pop('egg_module.sub1', None) - sys.modules.pop('egg_module.bad_module', None) - sys.modules.pop('egg_module.good_module', None) - sys.modules.pop('egg_module', None) + sys.modules.pop("egg_module.sub1.sub2.bad_module", None) + sys.modules.pop("egg_module.sub1.sub2.good_module", None) + sys.modules.pop("egg_module.sub1.sub2", None) + sys.modules.pop("egg_module.sub1", None) + sys.modules.pop("egg_module.bad_module", None) + sys.modules.pop("egg_module.good_module", None) + sys.modules.pop("egg_module", None) def test_shallow_loader(self): "Module existence can be tested inside eggs" - egg_name = '%s/test_egg.egg' % self.egg_dir + egg_name = "%s/test_egg.egg" % self.egg_dir with extend_sys_path(egg_name): - egg_module = import_module('egg_module') + egg_module = import_module("egg_module") # An importable child - self.assertTrue(module_has_submodule(egg_module, 'good_module')) - mod = import_module('egg_module.good_module') - self.assertEqual(mod.content, 'Good Module') + self.assertTrue(module_has_submodule(egg_module, "good_module")) + mod = import_module("egg_module.good_module") + self.assertEqual(mod.content, "Good Module") # A child that exists, but will generate an import error if loaded - self.assertTrue(module_has_submodule(egg_module, 'bad_module')) + self.assertTrue(module_has_submodule(egg_module, "bad_module")) with self.assertRaises(ImportError): - import_module('egg_module.bad_module') + import_module("egg_module.bad_module") # A child that doesn't exist - self.assertFalse(module_has_submodule(egg_module, 'no_such_module')) + self.assertFalse(module_has_submodule(egg_module, "no_such_module")) with self.assertRaises(ImportError): - import_module('egg_module.no_such_module') + import_module("egg_module.no_such_module") def test_deep_loader(self): "Modules deep inside an egg can still be tested for existence" - egg_name = '%s/test_egg.egg' % self.egg_dir + egg_name = "%s/test_egg.egg" % self.egg_dir with extend_sys_path(egg_name): - egg_module = import_module('egg_module.sub1.sub2') + egg_module = import_module("egg_module.sub1.sub2") # An importable child - self.assertTrue(module_has_submodule(egg_module, 'good_module')) - mod = import_module('egg_module.sub1.sub2.good_module') - self.assertEqual(mod.content, 'Deep Good Module') + self.assertTrue(module_has_submodule(egg_module, "good_module")) + mod = import_module("egg_module.sub1.sub2.good_module") + self.assertEqual(mod.content, "Deep Good Module") # A child that exists, but will generate an import error if loaded - self.assertTrue(module_has_submodule(egg_module, 'bad_module')) + self.assertTrue(module_has_submodule(egg_module, "bad_module")) with self.assertRaises(ImportError): - import_module('egg_module.sub1.sub2.bad_module') + import_module("egg_module.sub1.sub2.bad_module") # A child that doesn't exist - self.assertFalse(module_has_submodule(egg_module, 'no_such_module')) + self.assertFalse(module_has_submodule(egg_module, "no_such_module")) with self.assertRaises(ImportError): - import_module('egg_module.sub1.sub2.no_such_module') + import_module("egg_module.sub1.sub2.no_such_module") class ModuleImportTests(SimpleTestCase): def test_import_string(self): - cls = import_string('django.utils.module_loading.import_string') + cls = import_string("django.utils.module_loading.import_string") self.assertEqual(cls, import_string) # Test exceptions raised with self.assertRaises(ImportError): - import_string('no_dots_in_path') + import_string("no_dots_in_path") msg = 'Module "utils_tests" does not define a "unexistent" attribute' with self.assertRaisesMessage(ImportError, msg): - import_string('utils_tests.unexistent') + import_string("utils_tests.unexistent") -@modify_settings(INSTALLED_APPS={'append': 'utils_tests.test_module'}) +@modify_settings(INSTALLED_APPS={"append": "utils_tests.test_module"}) class AutodiscoverModulesTestCase(SimpleTestCase): - def tearDown(self): sys.path_importer_cache.clear() - sys.modules.pop('utils_tests.test_module.another_bad_module', None) - sys.modules.pop('utils_tests.test_module.another_good_module', None) - sys.modules.pop('utils_tests.test_module.bad_module', None) - sys.modules.pop('utils_tests.test_module.good_module', None) - sys.modules.pop('utils_tests.test_module', None) + sys.modules.pop("utils_tests.test_module.another_bad_module", None) + sys.modules.pop("utils_tests.test_module.another_good_module", None) + sys.modules.pop("utils_tests.test_module.bad_module", None) + sys.modules.pop("utils_tests.test_module.good_module", None) + sys.modules.pop("utils_tests.test_module", None) def test_autodiscover_modules_found(self): - autodiscover_modules('good_module') + autodiscover_modules("good_module") def test_autodiscover_modules_not_found(self): - autodiscover_modules('missing_module') + autodiscover_modules("missing_module") def test_autodiscover_modules_found_but_bad_module(self): - with self.assertRaisesMessage(ImportError, "No module named 'a_package_name_that_does_not_exist'"): - autodiscover_modules('bad_module') + with self.assertRaisesMessage( + ImportError, "No module named 'a_package_name_that_does_not_exist'" + ): + autodiscover_modules("bad_module") def test_autodiscover_modules_several_one_bad_module(self): - with self.assertRaisesMessage(ImportError, "No module named 'a_package_name_that_does_not_exist'"): - autodiscover_modules('good_module', 'bad_module') + with self.assertRaisesMessage( + ImportError, "No module named 'a_package_name_that_does_not_exist'" + ): + autodiscover_modules("good_module", "bad_module") def test_autodiscover_modules_several_found(self): - autodiscover_modules('good_module', 'another_good_module') + autodiscover_modules("good_module", "another_good_module") def test_autodiscover_modules_several_found_with_registry(self): from .test_module import site - autodiscover_modules('good_module', 'another_good_module', register_to=site) - self.assertEqual(site._registry, {'lorem': 'ipsum'}) + + autodiscover_modules("good_module", "another_good_module", register_to=site) + self.assertEqual(site._registry, {"lorem": "ipsum"}) def test_validate_registry_keeps_intact(self): from .test_module import site + with self.assertRaisesMessage(Exception, "Some random exception."): - autodiscover_modules('another_bad_module', register_to=site) + autodiscover_modules("another_bad_module", register_to=site) self.assertEqual(site._registry, {}) def test_validate_registry_resets_after_erroneous_module(self): from .test_module import site + with self.assertRaisesMessage(Exception, "Some random exception."): - autodiscover_modules('another_good_module', 'another_bad_module', register_to=site) - self.assertEqual(site._registry, {'lorem': 'ipsum'}) + autodiscover_modules( + "another_good_module", "another_bad_module", register_to=site + ) + self.assertEqual(site._registry, {"lorem": "ipsum"}) def test_validate_registry_resets_after_missing_module(self): from .test_module import site - autodiscover_modules('does_not_exist', 'another_good_module', 'does_not_exist2', register_to=site) - self.assertEqual(site._registry, {'lorem': 'ipsum'}) + + autodiscover_modules( + "does_not_exist", "another_good_module", "does_not_exist2", register_to=site + ) + self.assertEqual(site._registry, {"lorem": "ipsum"}) if PY310: + class TestFinder: def __init__(self, *args, **kwargs): self.importer = zipimporter(*args, **kwargs) def find_spec(self, path, target=None): return self.importer.find_spec(path, target) + else: + class TestFinder: def __init__(self, *args, **kwargs): self.importer = zipimporter(*args, **kwargs) @@ -218,6 +241,7 @@ class CustomLoader(EggLoader): it uses a custom defined Loader class. Although the EggLoader combines both functions into one class, this isn't required. """ + def setUp(self): super().setUp() sys.path_hooks.insert(0, TestFinder) diff --git a/tests/utils_tests/test_numberformat.py b/tests/utils_tests/test_numberformat.py index 2da0c9f300..cec3e4c385 100644 --- a/tests/utils_tests/test_numberformat.py +++ b/tests/utils_tests/test_numberformat.py @@ -6,127 +6,169 @@ from django.utils.numberformat import format as nformat class TestNumberFormat(SimpleTestCase): - def test_format_number(self): - self.assertEqual(nformat(1234, '.'), '1234') - self.assertEqual(nformat(1234.2, '.'), '1234.2') - self.assertEqual(nformat(1234, '.', decimal_pos=2), '1234.00') - self.assertEqual(nformat(1234, '.', grouping=2, thousand_sep=','), '1234') - self.assertEqual(nformat(1234, '.', grouping=2, thousand_sep=',', force_grouping=True), '12,34') - self.assertEqual(nformat(-1234.33, '.', decimal_pos=1), '-1234.3') + self.assertEqual(nformat(1234, "."), "1234") + self.assertEqual(nformat(1234.2, "."), "1234.2") + self.assertEqual(nformat(1234, ".", decimal_pos=2), "1234.00") + self.assertEqual(nformat(1234, ".", grouping=2, thousand_sep=","), "1234") + self.assertEqual( + nformat(1234, ".", grouping=2, thousand_sep=",", force_grouping=True), + "12,34", + ) + self.assertEqual(nformat(-1234.33, ".", decimal_pos=1), "-1234.3") # The use_l10n parameter can force thousand grouping behavior. with self.settings(USE_THOUSAND_SEPARATOR=True): - self.assertEqual(nformat(1234, '.', grouping=3, thousand_sep=',', use_l10n=False), '1234') - self.assertEqual(nformat(1234, '.', grouping=3, thousand_sep=',', use_l10n=True), '1,234') + self.assertEqual( + nformat(1234, ".", grouping=3, thousand_sep=",", use_l10n=False), "1234" + ) + self.assertEqual( + nformat(1234, ".", grouping=3, thousand_sep=",", use_l10n=True), "1,234" + ) def test_format_string(self): - self.assertEqual(nformat('1234', '.'), '1234') - self.assertEqual(nformat('1234.2', '.'), '1234.2') - self.assertEqual(nformat('1234', '.', decimal_pos=2), '1234.00') - self.assertEqual(nformat('1234', '.', grouping=2, thousand_sep=','), '1234') - self.assertEqual(nformat('1234', '.', grouping=2, thousand_sep=',', force_grouping=True), '12,34') - self.assertEqual(nformat('-1234.33', '.', decimal_pos=1), '-1234.3') - self.assertEqual(nformat('10000', '.', grouping=3, thousand_sep='comma', force_grouping=True), '10comma000') + self.assertEqual(nformat("1234", "."), "1234") + self.assertEqual(nformat("1234.2", "."), "1234.2") + self.assertEqual(nformat("1234", ".", decimal_pos=2), "1234.00") + self.assertEqual(nformat("1234", ".", grouping=2, thousand_sep=","), "1234") + self.assertEqual( + nformat("1234", ".", grouping=2, thousand_sep=",", force_grouping=True), + "12,34", + ) + self.assertEqual(nformat("-1234.33", ".", decimal_pos=1), "-1234.3") + self.assertEqual( + nformat( + "10000", ".", grouping=3, thousand_sep="comma", force_grouping=True + ), + "10comma000", + ) def test_large_number(self): most_max = ( - '{}179769313486231570814527423731704356798070567525844996' - '598917476803157260780028538760589558632766878171540458953' - '514382464234321326889464182768467546703537516986049910576' - '551282076245490090389328944075868508455133942304583236903' - '222948165808559332123348274797826204144723168738177180919' - '29988125040402618412485836{}' + "{}179769313486231570814527423731704356798070567525844996" + "598917476803157260780028538760589558632766878171540458953" + "514382464234321326889464182768467546703537516986049910576" + "551282076245490090389328944075868508455133942304583236903" + "222948165808559332123348274797826204144723168738177180919" + "29988125040402618412485836{}" ) most_max2 = ( - '{}35953862697246314162905484746340871359614113505168999' - '31978349536063145215600570775211791172655337563430809179' - '07028764928468642653778928365536935093407075033972099821' - '15310256415249098018077865788815173701691026788460916647' - '38064458963316171186642466965495956524082894463374763543' - '61838599762500808052368249716736' + "{}35953862697246314162905484746340871359614113505168999" + "31978349536063145215600570775211791172655337563430809179" + "07028764928468642653778928365536935093407075033972099821" + "15310256415249098018077865788815173701691026788460916647" + "38064458963316171186642466965495956524082894463374763543" + "61838599762500808052368249716736" ) int_max = int(float_info.max) - self.assertEqual(nformat(int_max, '.'), most_max.format('', '8')) - self.assertEqual(nformat(int_max + 1, '.'), most_max.format('', '9')) - self.assertEqual(nformat(int_max * 2, '.'), most_max2.format('')) - self.assertEqual(nformat(0 - int_max, '.'), most_max.format('-', '8')) - self.assertEqual(nformat(-1 - int_max, '.'), most_max.format('-', '9')) - self.assertEqual(nformat(-2 * int_max, '.'), most_max2.format('-')) + self.assertEqual(nformat(int_max, "."), most_max.format("", "8")) + self.assertEqual(nformat(int_max + 1, "."), most_max.format("", "9")) + self.assertEqual(nformat(int_max * 2, "."), most_max2.format("")) + self.assertEqual(nformat(0 - int_max, "."), most_max.format("-", "8")) + self.assertEqual(nformat(-1 - int_max, "."), most_max.format("-", "9")) + self.assertEqual(nformat(-2 * int_max, "."), most_max2.format("-")) def test_float_numbers(self): tests = [ - (9e-10, 10, '0.0000000009'), - (9e-19, 2, '0.00'), - (.00000000000099, 0, '0'), - (.00000000000099, 13, '0.0000000000009'), - (1e16, None, '10000000000000000'), - (1e16, 2, '10000000000000000.00'), + (9e-10, 10, "0.0000000009"), + (9e-19, 2, "0.00"), + (0.00000000000099, 0, "0"), + (0.00000000000099, 13, "0.0000000000009"), + (1e16, None, "10000000000000000"), + (1e16, 2, "10000000000000000.00"), # A float without a fractional part (3.) results in a ".0" when no # decimal_pos is given. Contrast that with the Decimal('3.') case # in test_decimal_numbers which doesn't return a fractional part. - (3., None, '3.0'), + (3.0, None, "3.0"), ] for value, decimal_pos, expected_value in tests: with self.subTest(value=value, decimal_pos=decimal_pos): - self.assertEqual(nformat(value, '.', decimal_pos), expected_value) + self.assertEqual(nformat(value, ".", decimal_pos), expected_value) # Thousand grouping behavior. self.assertEqual( - nformat(1e16, '.', thousand_sep=',', grouping=3, force_grouping=True), - '10,000,000,000,000,000', + nformat(1e16, ".", thousand_sep=",", grouping=3, force_grouping=True), + "10,000,000,000,000,000", ) self.assertEqual( - nformat(1e16, '.', decimal_pos=2, thousand_sep=',', grouping=3, force_grouping=True), - '10,000,000,000,000,000.00', + nformat( + 1e16, + ".", + decimal_pos=2, + thousand_sep=",", + grouping=3, + force_grouping=True, + ), + "10,000,000,000,000,000.00", ) def test_decimal_numbers(self): - self.assertEqual(nformat(Decimal('1234'), '.'), '1234') - self.assertEqual(nformat(Decimal('1234.2'), '.'), '1234.2') - self.assertEqual(nformat(Decimal('1234'), '.', decimal_pos=2), '1234.00') - self.assertEqual(nformat(Decimal('1234'), '.', grouping=2, thousand_sep=','), '1234') - self.assertEqual(nformat(Decimal('1234'), '.', grouping=2, thousand_sep=',', force_grouping=True), '12,34') - self.assertEqual(nformat(Decimal('-1234.33'), '.', decimal_pos=1), '-1234.3') - self.assertEqual(nformat(Decimal('0.00000001'), '.', decimal_pos=8), '0.00000001') - self.assertEqual(nformat(Decimal('9e-19'), '.', decimal_pos=2), '0.00') - self.assertEqual(nformat(Decimal('.00000000000099'), '.', decimal_pos=0), '0') + self.assertEqual(nformat(Decimal("1234"), "."), "1234") + self.assertEqual(nformat(Decimal("1234.2"), "."), "1234.2") + self.assertEqual(nformat(Decimal("1234"), ".", decimal_pos=2), "1234.00") self.assertEqual( - nformat(Decimal('1e16'), '.', thousand_sep=',', grouping=3, force_grouping=True), - '10,000,000,000,000,000' + nformat(Decimal("1234"), ".", grouping=2, thousand_sep=","), "1234" ) self.assertEqual( - nformat(Decimal('1e16'), '.', decimal_pos=2, thousand_sep=',', grouping=3, force_grouping=True), - '10,000,000,000,000,000.00' + nformat( + Decimal("1234"), ".", grouping=2, thousand_sep=",", force_grouping=True + ), + "12,34", ) - self.assertEqual(nformat(Decimal('3.'), '.'), '3') - self.assertEqual(nformat(Decimal('3.0'), '.'), '3.0') + self.assertEqual(nformat(Decimal("-1234.33"), ".", decimal_pos=1), "-1234.3") + self.assertEqual( + nformat(Decimal("0.00000001"), ".", decimal_pos=8), "0.00000001" + ) + self.assertEqual(nformat(Decimal("9e-19"), ".", decimal_pos=2), "0.00") + self.assertEqual(nformat(Decimal(".00000000000099"), ".", decimal_pos=0), "0") + self.assertEqual( + nformat( + Decimal("1e16"), ".", thousand_sep=",", grouping=3, force_grouping=True + ), + "10,000,000,000,000,000", + ) + self.assertEqual( + nformat( + Decimal("1e16"), + ".", + decimal_pos=2, + thousand_sep=",", + grouping=3, + force_grouping=True, + ), + "10,000,000,000,000,000.00", + ) + self.assertEqual(nformat(Decimal("3."), "."), "3") + self.assertEqual(nformat(Decimal("3.0"), "."), "3.0") # Very large & small numbers. tests = [ - ('9e9999', None, '9e+9999'), - ('9e9999', 3, '9.000e+9999'), - ('9e201', None, '9e+201'), - ('9e200', None, '9e+200'), - ('1.2345e999', 2, '1.23e+999'), - ('9e-999', None, '9e-999'), - ('1e-7', 8, '0.00000010'), - ('1e-8', 8, '0.00000001'), - ('1e-9', 8, '0.00000000'), - ('1e-10', 8, '0.00000000'), - ('1e-11', 8, '0.00000000'), - ('1' + ('0' * 300), 3, '1.000e+300'), - ('0.{}1234'.format('0' * 299), 3, '0.000'), + ("9e9999", None, "9e+9999"), + ("9e9999", 3, "9.000e+9999"), + ("9e201", None, "9e+201"), + ("9e200", None, "9e+200"), + ("1.2345e999", 2, "1.23e+999"), + ("9e-999", None, "9e-999"), + ("1e-7", 8, "0.00000010"), + ("1e-8", 8, "0.00000001"), + ("1e-9", 8, "0.00000000"), + ("1e-10", 8, "0.00000000"), + ("1e-11", 8, "0.00000000"), + ("1" + ("0" * 300), 3, "1.000e+300"), + ("0.{}1234".format("0" * 299), 3, "0.000"), ] for value, decimal_pos, expected_value in tests: with self.subTest(value=value): - self.assertEqual(nformat(Decimal(value), '.', decimal_pos), expected_value) + self.assertEqual( + nformat(Decimal(value), ".", decimal_pos), expected_value + ) def test_decimal_subclass(self): class EuroDecimal(Decimal): """ Wrapper for Decimal which prefixes each amount with the € symbol. """ + def __format__(self, specifier, **kwargs): amount = super().__format__(specifier, **kwargs) - return '€ {}'.format(amount) + return "€ {}".format(amount) - price = EuroDecimal('1.23') - self.assertEqual(nformat(price, ','), '€ 1,23') + price = EuroDecimal("1.23") + self.assertEqual(nformat(price, ","), "€ 1,23") diff --git a/tests/utils_tests/test_os_utils.py b/tests/utils_tests/test_os_utils.py index 76c0eda944..7204167688 100644 --- a/tests/utils_tests/test_os_utils.py +++ b/tests/utils_tests/test_os_utils.py @@ -9,10 +9,7 @@ from django.utils._os import safe_join, to_path class SafeJoinTests(unittest.TestCase): def test_base_path_ends_with_sep(self): drive, path = os.path.splitdrive(safe_join("/abc/", "abc")) - self.assertEqual( - path, - "{0}abc{0}abc".format(os.path.sep) - ) + self.assertEqual(path, "{0}abc{0}abc".format(os.path.sep)) def test_root_path(self): drive, path = os.path.splitdrive(safe_join("/", "path")) @@ -34,9 +31,9 @@ class SafeJoinTests(unittest.TestCase): class ToPathTests(unittest.TestCase): def test_to_path(self): - for path in ('/tmp/some_file.txt', Path('/tmp/some_file.txt')): + for path in ("/tmp/some_file.txt", Path("/tmp/some_file.txt")): with self.subTest(path): - self.assertEqual(to_path(path), Path('/tmp/some_file.txt')) + self.assertEqual(to_path(path), Path("/tmp/some_file.txt")) def test_to_path_invalid_value(self): with self.assertRaises(TypeError): diff --git a/tests/utils_tests/test_regex_helper.py b/tests/utils_tests/test_regex_helper.py index 895890bd26..ca918e5be7 100644 --- a/tests/utils_tests/test_regex_helper.py +++ b/tests/utils_tests/test_regex_helper.py @@ -8,47 +8,50 @@ from django.utils import regex_helper class NormalizeTests(unittest.TestCase): def test_empty(self): pattern = r"" - expected = [('', [])] + expected = [("", [])] result = regex_helper.normalize(pattern) self.assertEqual(result, expected) def test_escape(self): pattern = r"\\\^\$\.\|\?\*\+\(\)\[" - expected = [('\\^$.|?*+()[', [])] + expected = [("\\^$.|?*+()[", [])] result = regex_helper.normalize(pattern) self.assertEqual(result, expected) def test_group_positional(self): pattern = r"(.*)-(.+)" - expected = [('%(_0)s-%(_1)s', ['_0', '_1'])] + expected = [("%(_0)s-%(_1)s", ["_0", "_1"])] result = regex_helper.normalize(pattern) self.assertEqual(result, expected) def test_group_noncapturing(self): pattern = r"(?:non-capturing)" - expected = [('non-capturing', [])] + expected = [("non-capturing", [])] result = regex_helper.normalize(pattern) self.assertEqual(result, expected) def test_group_named(self): pattern = r"(?P<first_group_name>.*)-(?P<second_group_name>.*)" - expected = [('%(first_group_name)s-%(second_group_name)s', - ['first_group_name', 'second_group_name'])] + expected = [ + ( + "%(first_group_name)s-%(second_group_name)s", + ["first_group_name", "second_group_name"], + ) + ] result = regex_helper.normalize(pattern) self.assertEqual(result, expected) def test_group_backreference(self): pattern = r"(?P<first_group_name>.*)-(?P=first_group_name)" - expected = [('%(first_group_name)s-%(first_group_name)s', - ['first_group_name'])] + expected = [("%(first_group_name)s-%(first_group_name)s", ["first_group_name"])] result = regex_helper.normalize(pattern) self.assertEqual(result, expected) class LazyReCompileTests(SimpleTestCase): def test_flags_with_pre_compiled_regex(self): - test_pattern = re.compile('test') + test_pattern = re.compile("test") lazy_test_pattern = regex_helper._lazy_re_compile(test_pattern, re.I) - msg = 'flags must be empty if regex is passed pre-compiled' + msg = "flags must be empty if regex is passed pre-compiled" with self.assertRaisesMessage(AssertionError, msg): - lazy_test_pattern.match('TEST') + lazy_test_pattern.match("TEST") diff --git a/tests/utils_tests/test_safestring.py b/tests/utils_tests/test_safestring.py index 80f31d42ac..d7805662f1 100644 --- a/tests/utils_tests/test_safestring.py +++ b/tests/utils_tests/test_safestring.py @@ -9,7 +9,7 @@ class customescape(str): def __html__(self): # Implement specific and wrong escaping in order to be able to detect # when it runs. - return self.replace('<', '<<').replace('>', '>>') + return self.replace("<", "<<").replace(">", ">>") class SafeStringTest(SimpleTestCase): @@ -19,63 +19,64 @@ class SafeStringTest(SimpleTestCase): self.assertEqual(tpl.render(context), expected) def test_mark_safe(self): - s = mark_safe('a&b') + s = mark_safe("a&b") - self.assertRenderEqual('{{ s }}', 'a&b', s=s) - self.assertRenderEqual('{{ s|force_escape }}', 'a&b', s=s) + self.assertRenderEqual("{{ s }}", "a&b", s=s) + self.assertRenderEqual("{{ s|force_escape }}", "a&b", s=s) def test_mark_safe_str(self): """ Calling str() on a SafeString instance doesn't lose the safe status. """ - s = mark_safe('a&b') + s = mark_safe("a&b") self.assertIsInstance(str(s), type(s)) def test_mark_safe_object_implementing_dunder_html(self): - e = customescape('<a&b>') + e = customescape("<a&b>") s = mark_safe(e) self.assertIs(s, e) - self.assertRenderEqual('{{ s }}', '<<a&b>>', s=s) - self.assertRenderEqual('{{ s|force_escape }}', '<a&b>', s=s) + self.assertRenderEqual("{{ s }}", "<<a&b>>", s=s) + self.assertRenderEqual("{{ s|force_escape }}", "<a&b>", s=s) def test_mark_safe_lazy(self): - s = lazystr('a&b') + s = lazystr("a&b") self.assertIsInstance(mark_safe(s), SafeData) - self.assertRenderEqual('{{ s }}', 'a&b', s=mark_safe(s)) + self.assertRenderEqual("{{ s }}", "a&b", s=mark_safe(s)) def test_mark_safe_object_implementing_dunder_str(self): class Obj: def __str__(self): - return '<obj>' + return "<obj>" s = mark_safe(Obj()) - self.assertRenderEqual('{{ s }}', '<obj>', s=s) + self.assertRenderEqual("{{ s }}", "<obj>", s=s) def test_mark_safe_result_implements_dunder_html(self): - self.assertEqual(mark_safe('a&b').__html__(), 'a&b') + self.assertEqual(mark_safe("a&b").__html__(), "a&b") def test_mark_safe_lazy_result_implements_dunder_html(self): - self.assertEqual(mark_safe(lazystr('a&b')).__html__(), 'a&b') + self.assertEqual(mark_safe(lazystr("a&b")).__html__(), "a&b") def test_add_lazy_safe_text_and_safe_text(self): - s = html.escape(lazystr('a')) - s += mark_safe('&b') - self.assertRenderEqual('{{ s }}', 'a&b', s=s) + s = html.escape(lazystr("a")) + s += mark_safe("&b") + self.assertRenderEqual("{{ s }}", "a&b", s=s) - s = html.escapejs(lazystr('a')) - s += mark_safe('&b') - self.assertRenderEqual('{{ s }}', 'a&b', s=s) + s = html.escapejs(lazystr("a")) + s += mark_safe("&b") + self.assertRenderEqual("{{ s }}", "a&b", s=s) def test_mark_safe_as_decorator(self): """ mark_safe used as a decorator leaves the result of a function unchanged. """ + def clean_string_provider(): - return '<html><body>dummy</body></html>' + return "<html><body>dummy</body></html>" self.assertEqual(mark_safe(clean_string_provider)(), clean_string_provider()) @@ -83,9 +84,10 @@ class SafeStringTest(SimpleTestCase): """ mark_safe doesn't affect a callable that has an __html__() method. """ + class SafeStringContainer: def __html__(self): - return '<html></html>' + return "<html></html>" self.assertIs(mark_safe(SafeStringContainer), SafeStringContainer) @@ -93,14 +95,15 @@ class SafeStringTest(SimpleTestCase): """ mark_safe doesn't affect lazy strings (Promise objects). """ + def html_str(): - return '<html></html>' + return "<html></html>" lazy_str = lazy(html_str, str)() self.assertEqual(mark_safe(lazy_str), html_str()) def test_default_additional_attrs(self): - s = SafeString('a&b') + s = SafeString("a&b") msg = "object has no attribute 'dynamic_attr'" with self.assertRaisesMessage(AttributeError, msg): s.dynamic_attr = True diff --git a/tests/utils_tests/test_simplelazyobject.py b/tests/utils_tests/test_simplelazyobject.py index d6386fe79c..7c9c021afb 100644 --- a/tests/utils_tests/test_simplelazyobject.py +++ b/tests/utils_tests/test_simplelazyobject.py @@ -6,9 +6,8 @@ from django.utils.functional import SimpleLazyObject class TestUtilsSimpleLazyObjectDjangoTestCase(TestCase): - def test_pickle(self): - user = User.objects.create_user('johndoe', 'john@example.com', 'pass') + user = User.objects.create_user("johndoe", "john@example.com", "pass") x = SimpleLazyObject(lambda: user) pickle.dumps(x) # Try the variant protocol levels. diff --git a/tests/utils_tests/test_termcolors.py b/tests/utils_tests/test_termcolors.py index 0469137a9c..7ee4f9b0b2 100644 --- a/tests/utils_tests/test_termcolors.py +++ b/tests/utils_tests/test_termcolors.py @@ -1,209 +1,233 @@ import unittest from django.utils.termcolors import ( - DARK_PALETTE, DEFAULT_PALETTE, LIGHT_PALETTE, NOCOLOR_PALETTE, PALETTES, - colorize, parse_color_setting, + DARK_PALETTE, + DEFAULT_PALETTE, + LIGHT_PALETTE, + NOCOLOR_PALETTE, + PALETTES, + colorize, + parse_color_setting, ) class TermColorTests(unittest.TestCase): - def test_empty_string(self): - self.assertEqual(parse_color_setting(''), PALETTES[DEFAULT_PALETTE]) + self.assertEqual(parse_color_setting(""), PALETTES[DEFAULT_PALETTE]) def test_simple_palette(self): - self.assertEqual(parse_color_setting('light'), PALETTES[LIGHT_PALETTE]) - self.assertEqual(parse_color_setting('dark'), PALETTES[DARK_PALETTE]) - self.assertIsNone(parse_color_setting('nocolor')) + self.assertEqual(parse_color_setting("light"), PALETTES[LIGHT_PALETTE]) + self.assertEqual(parse_color_setting("dark"), PALETTES[DARK_PALETTE]) + self.assertIsNone(parse_color_setting("nocolor")) def test_fg(self): self.assertEqual( - parse_color_setting('error=green'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green'}) + parse_color_setting("error=green"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green"}), ) def test_fg_bg(self): self.assertEqual( - parse_color_setting('error=green/blue'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green', 'bg': 'blue'}) + parse_color_setting("error=green/blue"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green", "bg": "blue"}), ) def test_fg_opts(self): self.assertEqual( - parse_color_setting('error=green,blink'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green', 'opts': ('blink',)}) + parse_color_setting("error=green,blink"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green", "opts": ("blink",)}), ) self.assertEqual( - parse_color_setting('error=green,bold,blink'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green', 'opts': ('blink', 'bold')}) + parse_color_setting("error=green,bold,blink"), + dict( + PALETTES[NOCOLOR_PALETTE], + ERROR={"fg": "green", "opts": ("blink", "bold")}, + ), ) def test_fg_bg_opts(self): self.assertEqual( - parse_color_setting('error=green/blue,blink'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green', 'bg': 'blue', 'opts': ('blink',)}) + parse_color_setting("error=green/blue,blink"), + dict( + PALETTES[NOCOLOR_PALETTE], + ERROR={"fg": "green", "bg": "blue", "opts": ("blink",)}, + ), ) self.assertEqual( - parse_color_setting('error=green/blue,bold,blink'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green', 'bg': 'blue', 'opts': ('blink', 'bold')}) + parse_color_setting("error=green/blue,bold,blink"), + dict( + PALETTES[NOCOLOR_PALETTE], + ERROR={"fg": "green", "bg": "blue", "opts": ("blink", "bold")}, + ), ) def test_override_palette(self): self.assertEqual( - parse_color_setting('light;error=green'), - dict(PALETTES[LIGHT_PALETTE], ERROR={'fg': 'green'}) + parse_color_setting("light;error=green"), + dict(PALETTES[LIGHT_PALETTE], ERROR={"fg": "green"}), ) def test_override_nocolor(self): self.assertEqual( - parse_color_setting('nocolor;error=green'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green'}) + parse_color_setting("nocolor;error=green"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green"}), ) def test_reverse_override(self): - self.assertEqual(parse_color_setting('error=green;light'), PALETTES[LIGHT_PALETTE]) + self.assertEqual( + parse_color_setting("error=green;light"), PALETTES[LIGHT_PALETTE] + ) def test_multiple_roles(self): self.assertEqual( - parse_color_setting('error=green;sql_field=blue'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green'}, SQL_FIELD={'fg': 'blue'}) + parse_color_setting("error=green;sql_field=blue"), + dict( + PALETTES[NOCOLOR_PALETTE], + ERROR={"fg": "green"}, + SQL_FIELD={"fg": "blue"}, + ), ) def test_override_with_multiple_roles(self): self.assertEqual( - parse_color_setting('light;error=green;sql_field=blue'), - dict(PALETTES[LIGHT_PALETTE], ERROR={'fg': 'green'}, SQL_FIELD={'fg': 'blue'}) + parse_color_setting("light;error=green;sql_field=blue"), + dict( + PALETTES[LIGHT_PALETTE], ERROR={"fg": "green"}, SQL_FIELD={"fg": "blue"} + ), ) def test_empty_definition(self): - self.assertIsNone(parse_color_setting(';')) - self.assertEqual(parse_color_setting('light;'), PALETTES[LIGHT_PALETTE]) - self.assertIsNone(parse_color_setting(';;;')) + self.assertIsNone(parse_color_setting(";")) + self.assertEqual(parse_color_setting("light;"), PALETTES[LIGHT_PALETTE]) + self.assertIsNone(parse_color_setting(";;;")) def test_empty_options(self): self.assertEqual( - parse_color_setting('error=green,'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green'}) + parse_color_setting("error=green,"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green"}), ) self.assertEqual( - parse_color_setting('error=green,,,'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green'}) + parse_color_setting("error=green,,,"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green"}), ) self.assertEqual( - parse_color_setting('error=green,,blink,,'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green', 'opts': ('blink',)}) + parse_color_setting("error=green,,blink,,"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green", "opts": ("blink",)}), ) def test_bad_palette(self): - self.assertIsNone(parse_color_setting('unknown')) + self.assertIsNone(parse_color_setting("unknown")) def test_bad_role(self): - self.assertIsNone(parse_color_setting('unknown=')) - self.assertIsNone(parse_color_setting('unknown=green')) + self.assertIsNone(parse_color_setting("unknown=")) + self.assertIsNone(parse_color_setting("unknown=green")) self.assertEqual( - parse_color_setting('unknown=green;sql_field=blue'), - dict(PALETTES[NOCOLOR_PALETTE], SQL_FIELD={'fg': 'blue'}) + parse_color_setting("unknown=green;sql_field=blue"), + dict(PALETTES[NOCOLOR_PALETTE], SQL_FIELD={"fg": "blue"}), ) def test_bad_color(self): - self.assertIsNone(parse_color_setting('error=')) + self.assertIsNone(parse_color_setting("error=")) self.assertEqual( - parse_color_setting('error=;sql_field=blue'), - dict(PALETTES[NOCOLOR_PALETTE], SQL_FIELD={'fg': 'blue'}) + parse_color_setting("error=;sql_field=blue"), + dict(PALETTES[NOCOLOR_PALETTE], SQL_FIELD={"fg": "blue"}), ) - self.assertIsNone(parse_color_setting('error=unknown')) + self.assertIsNone(parse_color_setting("error=unknown")) self.assertEqual( - parse_color_setting('error=unknown;sql_field=blue'), - dict(PALETTES[NOCOLOR_PALETTE], SQL_FIELD={'fg': 'blue'}) + parse_color_setting("error=unknown;sql_field=blue"), + dict(PALETTES[NOCOLOR_PALETTE], SQL_FIELD={"fg": "blue"}), ) self.assertEqual( - parse_color_setting('error=green/unknown'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green'}) + parse_color_setting("error=green/unknown"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green"}), ) self.assertEqual( - parse_color_setting('error=green/blue/something'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green', 'bg': 'blue'}) + parse_color_setting("error=green/blue/something"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green", "bg": "blue"}), ) self.assertEqual( - parse_color_setting('error=green/blue/something,blink'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green', 'bg': 'blue', 'opts': ('blink',)}) + parse_color_setting("error=green/blue/something,blink"), + dict( + PALETTES[NOCOLOR_PALETTE], + ERROR={"fg": "green", "bg": "blue", "opts": ("blink",)}, + ), ) def test_bad_option(self): self.assertEqual( - parse_color_setting('error=green,unknown'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green'}) + parse_color_setting("error=green,unknown"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green"}), ) self.assertEqual( - parse_color_setting('error=green,unknown,blink'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green', 'opts': ('blink',)}) + parse_color_setting("error=green,unknown,blink"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green", "opts": ("blink",)}), ) def test_role_case(self): self.assertEqual( - parse_color_setting('ERROR=green'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green'}) + parse_color_setting("ERROR=green"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green"}), ) self.assertEqual( - parse_color_setting('eRrOr=green'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green'}) + parse_color_setting("eRrOr=green"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green"}), ) def test_color_case(self): self.assertEqual( - parse_color_setting('error=GREEN'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green'}) + parse_color_setting("error=GREEN"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green"}), ) self.assertEqual( - parse_color_setting('error=GREEN/BLUE'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green', 'bg': 'blue'}) + parse_color_setting("error=GREEN/BLUE"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green", "bg": "blue"}), ) self.assertEqual( - parse_color_setting('error=gReEn'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green'}) + parse_color_setting("error=gReEn"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green"}), ) self.assertEqual( - parse_color_setting('error=gReEn/bLuE'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green', 'bg': 'blue'}) + parse_color_setting("error=gReEn/bLuE"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green", "bg": "blue"}), ) def test_opts_case(self): self.assertEqual( - parse_color_setting('error=green,BLINK'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green', 'opts': ('blink',)}) + parse_color_setting("error=green,BLINK"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green", "opts": ("blink",)}), ) self.assertEqual( - parse_color_setting('error=green,bLiNk'), - dict(PALETTES[NOCOLOR_PALETTE], ERROR={'fg': 'green', 'opts': ('blink',)}) + parse_color_setting("error=green,bLiNk"), + dict(PALETTES[NOCOLOR_PALETTE], ERROR={"fg": "green", "opts": ("blink",)}), ) def test_colorize_empty_text(self): - self.assertEqual(colorize(text=None), '\x1b[m\x1b[0m') - self.assertEqual(colorize(text=''), '\x1b[m\x1b[0m') + self.assertEqual(colorize(text=None), "\x1b[m\x1b[0m") + self.assertEqual(colorize(text=""), "\x1b[m\x1b[0m") - self.assertEqual(colorize(text=None, opts=('noreset',)), '\x1b[m') - self.assertEqual(colorize(text='', opts=('noreset',)), '\x1b[m') + self.assertEqual(colorize(text=None, opts=("noreset",)), "\x1b[m") + self.assertEqual(colorize(text="", opts=("noreset",)), "\x1b[m") def test_colorize_reset(self): - self.assertEqual(colorize(text='', opts=('reset',)), '\x1b[0m') + self.assertEqual(colorize(text="", opts=("reset",)), "\x1b[0m") def test_colorize_fg_bg(self): - self.assertEqual(colorize(text='Test', fg='red'), '\x1b[31mTest\x1b[0m') - self.assertEqual(colorize(text='Test', bg='red'), '\x1b[41mTest\x1b[0m') + self.assertEqual(colorize(text="Test", fg="red"), "\x1b[31mTest\x1b[0m") + self.assertEqual(colorize(text="Test", bg="red"), "\x1b[41mTest\x1b[0m") # Ignored kwarg. - self.assertEqual(colorize(text='Test', other='red'), '\x1b[mTest\x1b[0m') + self.assertEqual(colorize(text="Test", other="red"), "\x1b[mTest\x1b[0m") def test_colorize_opts(self): self.assertEqual( - colorize(text='Test', opts=('bold', 'underscore')), - '\x1b[1;4mTest\x1b[0m', + colorize(text="Test", opts=("bold", "underscore")), + "\x1b[1;4mTest\x1b[0m", ) self.assertEqual( - colorize(text='Test', opts=('blink',)), - '\x1b[5mTest\x1b[0m', + colorize(text="Test", opts=("blink",)), + "\x1b[5mTest\x1b[0m", ) # Ignored opts. self.assertEqual( - colorize(text='Test', opts=('not_an_option',)), - '\x1b[mTest\x1b[0m', + colorize(text="Test", opts=("not_an_option",)), + "\x1b[mTest\x1b[0m", ) diff --git a/tests/utils_tests/test_text.py b/tests/utils_tests/test_text.py index 820a890bc5..caab19a55d 100644 --- a/tests/utils_tests/test_text.py +++ b/tests/utils_tests/test_text.py @@ -8,106 +8,117 @@ from django.utils.functional import lazystr from django.utils.text import format_lazy from django.utils.translation import gettext_lazy, override -IS_WIDE_BUILD = (len('\U0001F4A9') == 1) +IS_WIDE_BUILD = len("\U0001F4A9") == 1 class TestUtilsText(SimpleTestCase): - def test_get_text_list(self): - self.assertEqual(text.get_text_list(['a', 'b', 'c', 'd']), 'a, b, c or d') - self.assertEqual(text.get_text_list(['a', 'b', 'c'], 'and'), 'a, b and c') - self.assertEqual(text.get_text_list(['a', 'b'], 'and'), 'a and b') - self.assertEqual(text.get_text_list(['a']), 'a') - self.assertEqual(text.get_text_list([]), '') - with override('ar'): - self.assertEqual(text.get_text_list(['a', 'b', 'c']), "a، b أو c") + self.assertEqual(text.get_text_list(["a", "b", "c", "d"]), "a, b, c or d") + self.assertEqual(text.get_text_list(["a", "b", "c"], "and"), "a, b and c") + self.assertEqual(text.get_text_list(["a", "b"], "and"), "a and b") + self.assertEqual(text.get_text_list(["a"]), "a") + self.assertEqual(text.get_text_list([]), "") + with override("ar"): + self.assertEqual(text.get_text_list(["a", "b", "c"]), "a، b أو c") def test_smart_split(self): testdata = [ - ('This is "a person" test.', - ['This', 'is', '"a person"', 'test.']), - ('This is "a person\'s" test.', - ['This', 'is', '"a person\'s"', 'test.']), - ('This is "a person\\"s" test.', - ['This', 'is', '"a person\\"s"', 'test.']), - ('"a \'one', - ['"a', "'one"]), - ('all friends\' tests', - ['all', 'friends\'', 'tests']), - ('url search_page words="something else"', - ['url', 'search_page', 'words="something else"']), - ("url search_page words='something else'", - ['url', 'search_page', "words='something else'"]), - ('url search_page words "something else"', - ['url', 'search_page', 'words', '"something else"']), - ('url search_page words-"something else"', - ['url', 'search_page', 'words-"something else"']), - ('url search_page words=hello', - ['url', 'search_page', 'words=hello']), - ('url search_page words="something else', - ['url', 'search_page', 'words="something', 'else']), - ("cut:','|cut:' '", - ["cut:','|cut:' '"]), - (lazystr("a b c d"), # Test for #20231 - ['a', 'b', 'c', 'd']), + ('This is "a person" test.', ["This", "is", '"a person"', "test."]), + ('This is "a person\'s" test.', ["This", "is", '"a person\'s"', "test."]), + ('This is "a person\\"s" test.', ["This", "is", '"a person\\"s"', "test."]), + ("\"a 'one", ['"a', "'one"]), + ("all friends' tests", ["all", "friends'", "tests"]), + ( + 'url search_page words="something else"', + ["url", "search_page", 'words="something else"'], + ), + ( + "url search_page words='something else'", + ["url", "search_page", "words='something else'"], + ), + ( + 'url search_page words "something else"', + ["url", "search_page", "words", '"something else"'], + ), + ( + 'url search_page words-"something else"', + ["url", "search_page", 'words-"something else"'], + ), + ("url search_page words=hello", ["url", "search_page", "words=hello"]), + ( + 'url search_page words="something else', + ["url", "search_page", 'words="something', "else"], + ), + ("cut:','|cut:' '", ["cut:','|cut:' '"]), + (lazystr("a b c d"), ["a", "b", "c", "d"]), # Test for #20231 ] for test, expected in testdata: with self.subTest(value=test): self.assertEqual(list(text.smart_split(test)), expected) def test_truncate_chars(self): - truncator = text.Truncator('The quick brown fox jumped over the lazy dog.') - self.assertEqual('The quick brown fox jumped over the lazy dog.', truncator.chars(100)), - self.assertEqual('The quick brown fox …', truncator.chars(21)), - self.assertEqual('The quick brown fo.....', truncator.chars(23, '.....')), - self.assertEqual('.....', truncator.chars(4, '.....')), + truncator = text.Truncator("The quick brown fox jumped over the lazy dog.") + self.assertEqual( + "The quick brown fox jumped over the lazy dog.", truncator.chars(100) + ), + self.assertEqual("The quick brown fox …", truncator.chars(21)), + self.assertEqual("The quick brown fo.....", truncator.chars(23, ".....")), + self.assertEqual(".....", truncator.chars(4, ".....")), - nfc = text.Truncator('o\xfco\xfco\xfco\xfc') - nfd = text.Truncator('ou\u0308ou\u0308ou\u0308ou\u0308') - self.assertEqual('oüoüoüoü', nfc.chars(8)) - self.assertEqual('oüoüoüoü', nfd.chars(8)) - self.assertEqual('oü…', nfc.chars(3)) - self.assertEqual('oü…', nfd.chars(3)) + nfc = text.Truncator("o\xfco\xfco\xfco\xfc") + nfd = text.Truncator("ou\u0308ou\u0308ou\u0308ou\u0308") + self.assertEqual("oüoüoüoü", nfc.chars(8)) + self.assertEqual("oüoüoüoü", nfd.chars(8)) + self.assertEqual("oü…", nfc.chars(3)) + self.assertEqual("oü…", nfd.chars(3)) # Ensure the final length is calculated correctly when there are # combining characters with no precomposed form, and that combining # characters are not split up. - truncator = text.Truncator('-B\u030AB\u030A----8') - self.assertEqual('-B\u030A…', truncator.chars(3)) - self.assertEqual('-B\u030AB\u030A-…', truncator.chars(5)) - self.assertEqual('-B\u030AB\u030A----8', truncator.chars(8)) + truncator = text.Truncator("-B\u030AB\u030A----8") + self.assertEqual("-B\u030A…", truncator.chars(3)) + self.assertEqual("-B\u030AB\u030A-…", truncator.chars(5)) + self.assertEqual("-B\u030AB\u030A----8", truncator.chars(8)) # Ensure the length of the end text is correctly calculated when it # contains combining characters with no precomposed form. - truncator = text.Truncator('-----') - self.assertEqual('---B\u030A', truncator.chars(4, 'B\u030A')) - self.assertEqual('-----', truncator.chars(5, 'B\u030A')) + truncator = text.Truncator("-----") + self.assertEqual("---B\u030A", truncator.chars(4, "B\u030A")) + self.assertEqual("-----", truncator.chars(5, "B\u030A")) # Make a best effort to shorten to the desired length, but requesting # a length shorter than the ellipsis shouldn't break - self.assertEqual('…', text.Truncator('asdf').chars(0)) + self.assertEqual("…", text.Truncator("asdf").chars(0)) # lazy strings are handled correctly - self.assertEqual(text.Truncator(lazystr('The quick brown fox')).chars(10), 'The quick…') + self.assertEqual( + text.Truncator(lazystr("The quick brown fox")).chars(10), "The quick…" + ) def test_truncate_chars_html(self): perf_test_values = [ - (('</a' + '\t' * 50000) + '//>', None), - ('&' * 50000, '&' * 9 + '…'), - ('_X<<<<<<<<<<<>', None), + (("</a" + "\t" * 50000) + "//>", None), + ("&" * 50000, "&" * 9 + "…"), + ("_X<<<<<<<<<<<>", None), ] for value, expected in perf_test_values: with self.subTest(value=value): truncator = text.Truncator(value) - self.assertEqual(expected if expected else value, truncator.chars(10, html=True)) + self.assertEqual( + expected if expected else value, truncator.chars(10, html=True) + ) def test_truncate_words(self): - truncator = text.Truncator('The quick brown fox jumped over the lazy dog.') - self.assertEqual('The quick brown fox jumped over the lazy dog.', truncator.words(10)) - self.assertEqual('The quick brown fox…', truncator.words(4)) - self.assertEqual('The quick brown fox[snip]', truncator.words(4, '[snip]')) + truncator = text.Truncator("The quick brown fox jumped over the lazy dog.") + self.assertEqual( + "The quick brown fox jumped over the lazy dog.", truncator.words(10) + ) + self.assertEqual("The quick brown fox…", truncator.words(4)) + self.assertEqual("The quick brown fox[snip]", truncator.words(4, "[snip]")) # lazy strings are handled correctly - truncator = text.Truncator(lazystr('The quick brown fox jumped over the lazy dog.')) - self.assertEqual('The quick brown fox…', truncator.words(4)) + truncator = text.Truncator( + lazystr("The quick brown fox jumped over the lazy dog.") + ) + self.assertEqual("The quick brown fox…", truncator.words(4)) def test_truncate_html_words(self): truncator = text.Truncator( @@ -115,19 +126,19 @@ class TestUtilsText(SimpleTestCase): ) self.assertEqual( '<p id="par"><strong><em>The quick brown fox jumped over the lazy dog.</em></strong></p>', - truncator.words(10, html=True) + truncator.words(10, html=True), ) self.assertEqual( '<p id="par"><strong><em>The quick brown fox…</em></strong></p>', - truncator.words(4, html=True) + truncator.words(4, html=True), ) self.assertEqual( '<p id="par"><strong><em>The quick brown fox....</em></strong></p>', - truncator.words(4, '....', html=True) + truncator.words(4, "....", html=True), ) self.assertEqual( '<p id="par"><strong><em>The quick brown fox</em></strong></p>', - truncator.words(4, '', html=True) + truncator.words(4, "", html=True), ) # Test with new line inside tag @@ -136,25 +147,36 @@ class TestUtilsText(SimpleTestCase): ) self.assertEqual( '<p>The quick <a href="xyz.html"\n id="mylink">brown…</a></p>', - truncator.words(3, html=True) + truncator.words(3, html=True), ) # Test self-closing tags - truncator = text.Truncator('<br/>The <hr />quick brown fox jumped over the lazy dog.') - self.assertEqual('<br/>The <hr />quick brown…', truncator.words(3, html=True)) - truncator = text.Truncator('<br>The <hr/>quick <em>brown fox</em> jumped over the lazy dog.') - self.assertEqual('<br>The <hr/>quick <em>brown…</em>', truncator.words(3, html=True)) + truncator = text.Truncator( + "<br/>The <hr />quick brown fox jumped over the lazy dog." + ) + self.assertEqual("<br/>The <hr />quick brown…", truncator.words(3, html=True)) + truncator = text.Truncator( + "<br>The <hr/>quick <em>brown fox</em> jumped over the lazy dog." + ) + self.assertEqual( + "<br>The <hr/>quick <em>brown…</em>", truncator.words(3, html=True) + ) # Test html entities - truncator = text.Truncator('<i>Buenos días! ¿Cómo está?</i>') - self.assertEqual('<i>Buenos días! ¿Cómo…</i>', truncator.words(3, html=True)) - truncator = text.Truncator('<p>I <3 python, what about you?</p>') - self.assertEqual('<p>I <3 python,…</p>', truncator.words(3, html=True)) + truncator = text.Truncator( + "<i>Buenos días! ¿Cómo está?</i>" + ) + self.assertEqual( + "<i>Buenos días! ¿Cómo…</i>", + truncator.words(3, html=True), + ) + truncator = text.Truncator("<p>I <3 python, what about you?</p>") + self.assertEqual("<p>I <3 python,…</p>", truncator.words(3, html=True)) perf_test_values = [ - ('</a' + '\t' * 50000) + '//>', - '&' * 50000, - '_X<<<<<<<<<<<>', + ("</a" + "\t" * 50000) + "//>", + "&" * 50000, + "_X<<<<<<<<<<<>", ] for value in perf_test_values: with self.subTest(value=value): @@ -162,63 +184,72 @@ class TestUtilsText(SimpleTestCase): self.assertEqual(value, truncator.words(50, html=True)) def test_wrap(self): - digits = '1234 67 9' - self.assertEqual(text.wrap(digits, 100), '1234 67 9') - self.assertEqual(text.wrap(digits, 9), '1234 67 9') - self.assertEqual(text.wrap(digits, 8), '1234 67\n9') + digits = "1234 67 9" + self.assertEqual(text.wrap(digits, 100), "1234 67 9") + self.assertEqual(text.wrap(digits, 9), "1234 67 9") + self.assertEqual(text.wrap(digits, 8), "1234 67\n9") - self.assertEqual(text.wrap('short\na long line', 7), 'short\na long\nline') - self.assertEqual(text.wrap('do-not-break-long-words please? ok', 8), 'do-not-break-long-words\nplease?\nok') + self.assertEqual(text.wrap("short\na long line", 7), "short\na long\nline") + self.assertEqual( + text.wrap("do-not-break-long-words please? ok", 8), + "do-not-break-long-words\nplease?\nok", + ) - long_word = 'l%sng' % ('o' * 20) + long_word = "l%sng" % ("o" * 20) self.assertEqual(text.wrap(long_word, 20), long_word) - self.assertEqual(text.wrap('a %s word' % long_word, 10), 'a\n%s\nword' % long_word) - self.assertEqual(text.wrap(lazystr(digits), 100), '1234 67 9') + self.assertEqual( + text.wrap("a %s word" % long_word, 10), "a\n%s\nword" % long_word + ) + self.assertEqual(text.wrap(lazystr(digits), 100), "1234 67 9") def test_normalize_newlines(self): - self.assertEqual(text.normalize_newlines("abc\ndef\rghi\r\n"), "abc\ndef\nghi\n") + self.assertEqual( + text.normalize_newlines("abc\ndef\rghi\r\n"), "abc\ndef\nghi\n" + ) self.assertEqual(text.normalize_newlines("\n\r\r\n\r"), "\n\n\n\n") self.assertEqual(text.normalize_newlines("abcdefghi"), "abcdefghi") self.assertEqual(text.normalize_newlines(""), "") - self.assertEqual(text.normalize_newlines(lazystr("abc\ndef\rghi\r\n")), "abc\ndef\nghi\n") + self.assertEqual( + text.normalize_newlines(lazystr("abc\ndef\rghi\r\n")), "abc\ndef\nghi\n" + ) def test_phone2numeric(self): - numeric = text.phone2numeric('0800 flowers') - self.assertEqual(numeric, '0800 3569377') - lazy_numeric = lazystr(text.phone2numeric('0800 flowers')) - self.assertEqual(lazy_numeric, '0800 3569377') + numeric = text.phone2numeric("0800 flowers") + self.assertEqual(numeric, "0800 3569377") + lazy_numeric = lazystr(text.phone2numeric("0800 flowers")) + self.assertEqual(lazy_numeric, "0800 3569377") def test_slugify(self): items = ( # given - expected - Unicode? - ('Hello, World!', 'hello-world', False), - ('spam & eggs', 'spam-eggs', False), - (' multiple---dash and space ', 'multiple-dash-and-space', False), - ('\t whitespace-in-value \n', 'whitespace-in-value', False), - ('underscore_in-value', 'underscore_in-value', False), - ('__strip__underscore-value___', 'strip__underscore-value', False), - ('--strip-dash-value---', 'strip-dash-value', False), - ('__strip-mixed-value---', 'strip-mixed-value', False), - ('_ -strip-mixed-value _-', 'strip-mixed-value', False), - ('spam & ıçüş', 'spam-ıçüş', True), - ('foo ıç bar', 'foo-ıç-bar', True), - (' foo ıç bar', 'foo-ıç-bar', True), - ('你好', '你好', True), - ('İstanbul', 'istanbul', True), + ("Hello, World!", "hello-world", False), + ("spam & eggs", "spam-eggs", False), + (" multiple---dash and space ", "multiple-dash-and-space", False), + ("\t whitespace-in-value \n", "whitespace-in-value", False), + ("underscore_in-value", "underscore_in-value", False), + ("__strip__underscore-value___", "strip__underscore-value", False), + ("--strip-dash-value---", "strip-dash-value", False), + ("__strip-mixed-value---", "strip-mixed-value", False), + ("_ -strip-mixed-value _-", "strip-mixed-value", False), + ("spam & ıçüş", "spam-ıçüş", True), + ("foo ıç bar", "foo-ıç-bar", True), + (" foo ıç bar", "foo-ıç-bar", True), + ("你好", "你好", True), + ("İstanbul", "istanbul", True), ) for value, output, is_unicode in items: with self.subTest(value=value): self.assertEqual(text.slugify(value, allow_unicode=is_unicode), output) # Interning the result may be useful, e.g. when fed to Path. - with self.subTest('intern'): - self.assertEqual(sys.intern(text.slugify('a')), 'a') + with self.subTest("intern"): + self.assertEqual(sys.intern(text.slugify("a")), "a") def test_unescape_string_literal(self): items = [ - ('"abc"', 'abc'), - ("'abc'", 'abc'), - ('"a \"bc\""', 'a "bc"'), - ("'\'ab\' c'", "'ab' c"), + ('"abc"', "abc"), + ("'abc'", "abc"), + ('"a "bc""', 'a "bc"'), + ("''ab' c'", "'ab' c"), ] for value, output in items: with self.subTest(value=value): @@ -226,9 +257,9 @@ class TestUtilsText(SimpleTestCase): self.assertEqual(text.unescape_string_literal(lazystr(value)), output) def test_unescape_string_literal_invalid_value(self): - items = ['', 'abc', "'abc\""] + items = ["", "abc", "'abc\""] for item in items: - msg = f'Not a string literal: {item!r}' + msg = f"Not a string literal: {item!r}" with self.assertRaisesMessage(ValueError, msg): text.unescape_string_literal(item) @@ -238,38 +269,43 @@ class TestUtilsText(SimpleTestCase): self.assertEqual(text.get_valid_filename(lazystr(filename)), "-_123.txt") msg = "Could not derive file name from '???'" with self.assertRaisesMessage(SuspiciousFileOperation, msg): - text.get_valid_filename('???') + text.get_valid_filename("???") # After sanitizing this would yield '..'. msg = "Could not derive file name from '$.$.$'" with self.assertRaisesMessage(SuspiciousFileOperation, msg): - text.get_valid_filename('$.$.$') + text.get_valid_filename("$.$.$") def test_compress_sequence(self): - data = [{'key': i} for i in range(10)] + data = [{"key": i} for i in range(10)] seq = list(json.JSONEncoder().iterencode(data)) seq = [s.encode() for s in seq] - actual_length = len(b''.join(seq)) + actual_length = len(b"".join(seq)) out = text.compress_sequence(seq) - compressed_length = len(b''.join(out)) + compressed_length = len(b"".join(out)) self.assertLess(compressed_length, actual_length) def test_format_lazy(self): - self.assertEqual('django/test', format_lazy('{}/{}', 'django', lazystr('test'))) - self.assertEqual('django/test', format_lazy('{0}/{1}', *('django', 'test'))) - self.assertEqual('django/test', format_lazy('{a}/{b}', **{'a': 'django', 'b': 'test'})) - self.assertEqual('django/test', format_lazy('{a[0]}/{a[1]}', a=('django', 'test'))) + self.assertEqual("django/test", format_lazy("{}/{}", "django", lazystr("test"))) + self.assertEqual("django/test", format_lazy("{0}/{1}", *("django", "test"))) + self.assertEqual( + "django/test", format_lazy("{a}/{b}", **{"a": "django", "b": "test"}) + ) + self.assertEqual( + "django/test", format_lazy("{a[0]}/{a[1]}", a=("django", "test")) + ) t = {} - s = format_lazy('{0[a]}-{p[a]}', t, p=t) - t['a'] = lazystr('django') - self.assertEqual('django-django', s) - t['a'] = 'update' - self.assertEqual('update-update', s) + s = format_lazy("{0[a]}-{p[a]}", t, p=t) + t["a"] = lazystr("django") + self.assertEqual("django-django", s) + t["a"] = "update" + self.assertEqual("update-update", s) # The format string can be lazy. (string comes from contrib.admin) s = format_lazy( - gettext_lazy('Added {name} “{object}”.'), - name='article', object='My first try', + gettext_lazy("Added {name} “{object}”."), + name="article", + object="My first try", ) - with override('fr'): - self.assertEqual('Ajout de article «\xa0My first try\xa0».', s) + with override("fr"): + self.assertEqual("Ajout de article «\xa0My first try\xa0».", s) diff --git a/tests/utils_tests/test_timesince.py b/tests/utils_tests/test_timesince.py index d080f1b1c5..4ab8e49e8d 100644 --- a/tests/utils_tests/test_timesince.py +++ b/tests/utils_tests/test_timesince.py @@ -8,7 +8,6 @@ from django.utils.translation import npgettext_lazy class TimesinceTests(TestCase): - def setUp(self): self.t = datetime.datetime(2007, 8, 14, 13, 46, 0) self.onemicrosecond = datetime.timedelta(microseconds=1) @@ -21,28 +20,36 @@ class TimesinceTests(TestCase): self.oneyear = datetime.timedelta(days=365) def test_equal_datetimes(self): - """ equal datetimes. """ + """equal datetimes.""" # NOTE: \xa0 avoids wrapping between value and unit - self.assertEqual(timesince(self.t, self.t), '0\xa0minutes') + self.assertEqual(timesince(self.t, self.t), "0\xa0minutes") def test_ignore_microseconds_and_seconds(self): - """ Microseconds and seconds are ignored. """ - self.assertEqual(timesince(self.t, self.t + self.onemicrosecond), '0\xa0minutes') - self.assertEqual(timesince(self.t, self.t + self.onesecond), '0\xa0minutes') + """Microseconds and seconds are ignored.""" + self.assertEqual( + timesince(self.t, self.t + self.onemicrosecond), "0\xa0minutes" + ) + self.assertEqual(timesince(self.t, self.t + self.onesecond), "0\xa0minutes") def test_other_units(self): - """ Test other units. """ - self.assertEqual(timesince(self.t, self.t + self.oneminute), '1\xa0minute') - self.assertEqual(timesince(self.t, self.t + self.onehour), '1\xa0hour') - self.assertEqual(timesince(self.t, self.t + self.oneday), '1\xa0day') - self.assertEqual(timesince(self.t, self.t + self.oneweek), '1\xa0week') - self.assertEqual(timesince(self.t, self.t + self.onemonth), '1\xa0month') - self.assertEqual(timesince(self.t, self.t + self.oneyear), '1\xa0year') + """Test other units.""" + self.assertEqual(timesince(self.t, self.t + self.oneminute), "1\xa0minute") + self.assertEqual(timesince(self.t, self.t + self.onehour), "1\xa0hour") + self.assertEqual(timesince(self.t, self.t + self.oneday), "1\xa0day") + self.assertEqual(timesince(self.t, self.t + self.oneweek), "1\xa0week") + self.assertEqual(timesince(self.t, self.t + self.onemonth), "1\xa0month") + self.assertEqual(timesince(self.t, self.t + self.oneyear), "1\xa0year") def test_multiple_units(self): - """ Test multiple units. """ - self.assertEqual(timesince(self.t, self.t + 2 * self.oneday + 6 * self.onehour), '2\xa0days, 6\xa0hours') - self.assertEqual(timesince(self.t, self.t + 2 * self.oneweek + 2 * self.oneday), '2\xa0weeks, 2\xa0days') + """Test multiple units.""" + self.assertEqual( + timesince(self.t, self.t + 2 * self.oneday + 6 * self.onehour), + "2\xa0days, 6\xa0hours", + ) + self.assertEqual( + timesince(self.t, self.t + 2 * self.oneweek + 2 * self.oneday), + "2\xa0weeks, 2\xa0days", + ) def test_display_first_unit(self): """ @@ -50,119 +57,148 @@ class TimesinceTests(TestCase): displayed. """ self.assertEqual( - timesince(self.t, self.t + 2 * self.oneweek + 3 * self.onehour + 4 * self.oneminute), - '2\xa0weeks' + timesince( + self.t, + self.t + 2 * self.oneweek + 3 * self.onehour + 4 * self.oneminute, + ), + "2\xa0weeks", + ) + self.assertEqual( + timesince(self.t, self.t + 4 * self.oneday + 5 * self.oneminute), + "4\xa0days", ) - self.assertEqual(timesince(self.t, self.t + 4 * self.oneday + 5 * self.oneminute), '4\xa0days') def test_display_second_before_first(self): """ When the second date occurs before the first, we should always get 0 minutes. """ - self.assertEqual(timesince(self.t, self.t - self.onemicrosecond), '0\xa0minutes') - self.assertEqual(timesince(self.t, self.t - self.onesecond), '0\xa0minutes') - self.assertEqual(timesince(self.t, self.t - self.oneminute), '0\xa0minutes') - self.assertEqual(timesince(self.t, self.t - self.onehour), '0\xa0minutes') - self.assertEqual(timesince(self.t, self.t - self.oneday), '0\xa0minutes') - self.assertEqual(timesince(self.t, self.t - self.oneweek), '0\xa0minutes') - self.assertEqual(timesince(self.t, self.t - self.onemonth), '0\xa0minutes') - self.assertEqual(timesince(self.t, self.t - self.oneyear), '0\xa0minutes') - self.assertEqual(timesince(self.t, self.t - 2 * self.oneday - 6 * self.onehour), '0\xa0minutes') - self.assertEqual(timesince(self.t, self.t - 2 * self.oneweek - 2 * self.oneday), '0\xa0minutes') self.assertEqual( - timesince(self.t, self.t - 2 * self.oneweek - 3 * self.onehour - 4 * self.oneminute), '0\xa0minutes' + timesince(self.t, self.t - self.onemicrosecond), "0\xa0minutes" + ) + self.assertEqual(timesince(self.t, self.t - self.onesecond), "0\xa0minutes") + self.assertEqual(timesince(self.t, self.t - self.oneminute), "0\xa0minutes") + self.assertEqual(timesince(self.t, self.t - self.onehour), "0\xa0minutes") + self.assertEqual(timesince(self.t, self.t - self.oneday), "0\xa0minutes") + self.assertEqual(timesince(self.t, self.t - self.oneweek), "0\xa0minutes") + self.assertEqual(timesince(self.t, self.t - self.onemonth), "0\xa0minutes") + self.assertEqual(timesince(self.t, self.t - self.oneyear), "0\xa0minutes") + self.assertEqual( + timesince(self.t, self.t - 2 * self.oneday - 6 * self.onehour), + "0\xa0minutes", + ) + self.assertEqual( + timesince(self.t, self.t - 2 * self.oneweek - 2 * self.oneday), + "0\xa0minutes", + ) + self.assertEqual( + timesince( + self.t, + self.t - 2 * self.oneweek - 3 * self.onehour - 4 * self.oneminute, + ), + "0\xa0minutes", + ) + self.assertEqual( + timesince(self.t, self.t - 4 * self.oneday - 5 * self.oneminute), + "0\xa0minutes", ) - self.assertEqual(timesince(self.t, self.t - 4 * self.oneday - 5 * self.oneminute), '0\xa0minutes') def test_second_before_equal_first_humanize_time_strings(self): time_strings = { - 'minute': npgettext_lazy( - 'naturaltime-future', - '%(num)d minute', - '%(num)d minutes', - 'num', + "minute": npgettext_lazy( + "naturaltime-future", + "%(num)d minute", + "%(num)d minutes", + "num", ), } - with translation.override('cs'): + with translation.override("cs"): for now in [self.t, self.t - self.onemicrosecond, self.t - self.oneday]: with self.subTest(now): self.assertEqual( timesince(self.t, now, time_strings=time_strings), - '0\xa0minut', + "0\xa0minut", ) @requires_tz_support def test_different_timezones(self): - """ When using two different timezones. """ + """When using two different timezones.""" now = datetime.datetime.now() now_tz = timezone.make_aware(now, timezone.get_default_timezone()) now_tz_i = timezone.localtime(now_tz, timezone.get_fixed_timezone(195)) - self.assertEqual(timesince(now), '0\xa0minutes') - self.assertEqual(timesince(now_tz), '0\xa0minutes') - self.assertEqual(timesince(now_tz_i), '0\xa0minutes') - self.assertEqual(timesince(now_tz, now_tz_i), '0\xa0minutes') - self.assertEqual(timeuntil(now), '0\xa0minutes') - self.assertEqual(timeuntil(now_tz), '0\xa0minutes') - self.assertEqual(timeuntil(now_tz_i), '0\xa0minutes') - self.assertEqual(timeuntil(now_tz, now_tz_i), '0\xa0minutes') + self.assertEqual(timesince(now), "0\xa0minutes") + self.assertEqual(timesince(now_tz), "0\xa0minutes") + self.assertEqual(timesince(now_tz_i), "0\xa0minutes") + self.assertEqual(timesince(now_tz, now_tz_i), "0\xa0minutes") + self.assertEqual(timeuntil(now), "0\xa0minutes") + self.assertEqual(timeuntil(now_tz), "0\xa0minutes") + self.assertEqual(timeuntil(now_tz_i), "0\xa0minutes") + self.assertEqual(timeuntil(now_tz, now_tz_i), "0\xa0minutes") def test_date_objects(self): - """ Both timesince and timeuntil should work on date objects (#17937). """ + """Both timesince and timeuntil should work on date objects (#17937).""" today = datetime.date.today() - self.assertEqual(timesince(today + self.oneday), '0\xa0minutes') - self.assertEqual(timeuntil(today - self.oneday), '0\xa0minutes') + self.assertEqual(timesince(today + self.oneday), "0\xa0minutes") + self.assertEqual(timeuntil(today - self.oneday), "0\xa0minutes") def test_both_date_objects(self): - """ Timesince should work with both date objects (#9672) """ + """Timesince should work with both date objects (#9672)""" today = datetime.date.today() - self.assertEqual(timeuntil(today + self.oneday, today), '1\xa0day') - self.assertEqual(timeuntil(today - self.oneday, today), '0\xa0minutes') - self.assertEqual(timeuntil(today + self.oneweek, today), '1\xa0week') + self.assertEqual(timeuntil(today + self.oneday, today), "1\xa0day") + self.assertEqual(timeuntil(today - self.oneday, today), "0\xa0minutes") + self.assertEqual(timeuntil(today + self.oneweek, today), "1\xa0week") def test_leap_year(self): start_date = datetime.date(2016, 12, 25) - self.assertEqual(timeuntil(start_date + self.oneweek, start_date), '1\xa0week') - self.assertEqual(timesince(start_date, start_date + self.oneweek), '1\xa0week') + self.assertEqual(timeuntil(start_date + self.oneweek, start_date), "1\xa0week") + self.assertEqual(timesince(start_date, start_date + self.oneweek), "1\xa0week") def test_leap_year_new_years_eve(self): t = datetime.date(2016, 12, 31) now = datetime.datetime(2016, 12, 31, 18, 0, 0) - self.assertEqual(timesince(t + self.oneday, now), '0\xa0minutes') - self.assertEqual(timeuntil(t - self.oneday, now), '0\xa0minutes') + self.assertEqual(timesince(t + self.oneday, now), "0\xa0minutes") + self.assertEqual(timeuntil(t - self.oneday, now), "0\xa0minutes") def test_naive_datetime_with_tzinfo_attribute(self): class naive(datetime.tzinfo): def utcoffset(self, dt): return None + future = datetime.datetime(2080, 1, 1, tzinfo=naive()) - self.assertEqual(timesince(future), '0\xa0minutes') + self.assertEqual(timesince(future), "0\xa0minutes") past = datetime.datetime(1980, 1, 1, tzinfo=naive()) - self.assertEqual(timeuntil(past), '0\xa0minutes') + self.assertEqual(timeuntil(past), "0\xa0minutes") def test_thousand_years_ago(self): t = datetime.datetime(1007, 8, 14, 13, 46, 0) - self.assertEqual(timesince(t, self.t), '1000\xa0years') - self.assertEqual(timeuntil(self.t, t), '1000\xa0years') + self.assertEqual(timesince(t, self.t), "1000\xa0years") + self.assertEqual(timeuntil(self.t, t), "1000\xa0years") def test_depth(self): - t = self.t + self.oneyear + self.onemonth + self.oneweek + self.oneday + self.onehour + t = ( + self.t + + self.oneyear + + self.onemonth + + self.oneweek + + self.oneday + + self.onehour + ) tests = [ - (t, 1, '1\xa0year'), - (t, 2, '1\xa0year, 1\xa0month'), - (t, 3, '1\xa0year, 1\xa0month, 1\xa0week'), - (t, 4, '1\xa0year, 1\xa0month, 1\xa0week, 1\xa0day'), - (t, 5, '1\xa0year, 1\xa0month, 1\xa0week, 1\xa0day, 1\xa0hour'), - (t, 6, '1\xa0year, 1\xa0month, 1\xa0week, 1\xa0day, 1\xa0hour'), - (self.t + self.onehour, 5, '1\xa0hour'), - (self.t + (4 * self.oneminute), 3, '4\xa0minutes'), - (self.t + self.onehour + self.oneminute, 1, '1\xa0hour'), - (self.t + self.oneday + self.onehour, 1, '1\xa0day'), - (self.t + self.oneweek + self.oneday, 1, '1\xa0week'), - (self.t + self.onemonth + self.oneweek, 1, '1\xa0month'), - (self.t + self.oneyear + self.onemonth, 1, '1\xa0year'), - (self.t + self.oneyear + self.oneweek + self.oneday, 3, '1\xa0year'), + (t, 1, "1\xa0year"), + (t, 2, "1\xa0year, 1\xa0month"), + (t, 3, "1\xa0year, 1\xa0month, 1\xa0week"), + (t, 4, "1\xa0year, 1\xa0month, 1\xa0week, 1\xa0day"), + (t, 5, "1\xa0year, 1\xa0month, 1\xa0week, 1\xa0day, 1\xa0hour"), + (t, 6, "1\xa0year, 1\xa0month, 1\xa0week, 1\xa0day, 1\xa0hour"), + (self.t + self.onehour, 5, "1\xa0hour"), + (self.t + (4 * self.oneminute), 3, "4\xa0minutes"), + (self.t + self.onehour + self.oneminute, 1, "1\xa0hour"), + (self.t + self.oneday + self.onehour, 1, "1\xa0day"), + (self.t + self.oneweek + self.oneday, 1, "1\xa0week"), + (self.t + self.onemonth + self.oneweek, 1, "1\xa0month"), + (self.t + self.oneyear + self.onemonth, 1, "1\xa0year"), + (self.t + self.oneyear + self.oneweek + self.oneday, 3, "1\xa0year"), ] for value, depth, expected in tests: with self.subTest(): @@ -170,6 +206,6 @@ class TimesinceTests(TestCase): self.assertEqual(timeuntil(value, self.t, depth=depth), expected) def test_depth_invalid(self): - msg = 'depth must be greater than 0.' + msg = "depth must be greater than 0." with self.assertRaisesMessage(ValueError, msg): timesince(self.t, self.t, depth=0) diff --git a/tests/utils_tests/test_timezone.py b/tests/utils_tests/test_timezone.py index a61bb4acb0..ed8386945d 100644 --- a/tests/utils_tests/test_timezone.py +++ b/tests/utils_tests/test_timezone.py @@ -16,9 +16,9 @@ from django.test import SimpleTestCase, ignore_warnings, override_settings from django.utils import timezone from django.utils.deprecation import RemovedInDjango50Warning -PARIS_ZI = zoneinfo.ZoneInfo('Europe/Paris') -EAT = timezone.get_fixed_timezone(180) # Africa/Nairobi -ICT = timezone.get_fixed_timezone(420) # Asia/Bangkok +PARIS_ZI = zoneinfo.ZoneInfo("Europe/Paris") +EAT = timezone.get_fixed_timezone(180) # Africa/Nairobi +ICT = timezone.get_fixed_timezone(420) # Asia/Bangkok UTC = datetime.timezone.utc HAS_PYTZ = pytz is not None @@ -26,9 +26,9 @@ if not HAS_PYTZ: CET = None PARIS_IMPLS = (PARIS_ZI,) - needs_pytz = unittest.skip('Test requires pytz') + needs_pytz = unittest.skip("Test requires pytz") else: - CET = pytz.timezone('Europe/Paris') + CET = pytz.timezone("Europe/Paris") PARIS_IMPLS = (PARIS_ZI, CET) def needs_pytz(f): @@ -36,7 +36,6 @@ else: class TimezoneTests(SimpleTestCase): - def setUp(self): # RemovedInDjango50Warning timezone.get_default_timezone.cache_clear() @@ -62,18 +61,26 @@ class TimezoneTests(SimpleTestCase): def test_localdate(self): naive = datetime.datetime(2015, 1, 1, 0, 0, 1) - with self.assertRaisesMessage(ValueError, 'localtime() cannot be applied to a naive datetime'): + with self.assertRaisesMessage( + ValueError, "localtime() cannot be applied to a naive datetime" + ): timezone.localdate(naive) - with self.assertRaisesMessage(ValueError, 'localtime() cannot be applied to a naive datetime'): + with self.assertRaisesMessage( + ValueError, "localtime() cannot be applied to a naive datetime" + ): timezone.localdate(naive, timezone=EAT) aware = datetime.datetime(2015, 1, 1, 0, 0, 1, tzinfo=ICT) - self.assertEqual(timezone.localdate(aware, timezone=EAT), datetime.date(2014, 12, 31)) + self.assertEqual( + timezone.localdate(aware, timezone=EAT), datetime.date(2014, 12, 31) + ) with timezone.override(EAT): self.assertEqual(timezone.localdate(aware), datetime.date(2014, 12, 31)) - with mock.patch('django.utils.timezone.now', return_value=aware): - self.assertEqual(timezone.localdate(timezone=EAT), datetime.date(2014, 12, 31)) + with mock.patch("django.utils.timezone.now", return_value=aware): + self.assertEqual( + timezone.localdate(timezone=EAT), datetime.date(2014, 12, 31) + ) with timezone.override(EAT): self.assertEqual(timezone.localdate(), datetime.date(2014, 12, 31)) @@ -133,92 +140,128 @@ class TimezoneTests(SimpleTestCase): timezone.deactivate() def test_override_string_tz(self): - with timezone.override('Asia/Bangkok'): - self.assertEqual(timezone.get_current_timezone_name(), 'Asia/Bangkok') + with timezone.override("Asia/Bangkok"): + self.assertEqual(timezone.get_current_timezone_name(), "Asia/Bangkok") def test_override_fixed_offset(self): - with timezone.override(datetime.timezone(datetime.timedelta(), 'tzname')): - self.assertEqual(timezone.get_current_timezone_name(), 'tzname') + with timezone.override(datetime.timezone(datetime.timedelta(), "tzname")): + self.assertEqual(timezone.get_current_timezone_name(), "tzname") def test_activate_invalid_timezone(self): - with self.assertRaisesMessage(ValueError, 'Invalid timezone: None'): + with self.assertRaisesMessage(ValueError, "Invalid timezone: None"): timezone.activate(None) def test_is_aware(self): - self.assertTrue(timezone.is_aware(datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT))) + self.assertTrue( + timezone.is_aware(datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT)) + ) self.assertFalse(timezone.is_aware(datetime.datetime(2011, 9, 1, 13, 20, 30))) def test_is_naive(self): - self.assertFalse(timezone.is_naive(datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT))) + self.assertFalse( + timezone.is_naive(datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT)) + ) self.assertTrue(timezone.is_naive(datetime.datetime(2011, 9, 1, 13, 20, 30))) def test_make_aware(self): self.assertEqual( timezone.make_aware(datetime.datetime(2011, 9, 1, 13, 20, 30), EAT), - datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT)) + datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT), + ) with self.assertRaises(ValueError): - timezone.make_aware(datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT), EAT) + timezone.make_aware( + datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT), EAT + ) def test_make_naive(self): self.assertEqual( - timezone.make_naive(datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT), EAT), - datetime.datetime(2011, 9, 1, 13, 20, 30)) + timezone.make_naive( + datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT), EAT + ), + datetime.datetime(2011, 9, 1, 13, 20, 30), + ) self.assertEqual( - timezone.make_naive(datetime.datetime(2011, 9, 1, 17, 20, 30, tzinfo=ICT), EAT), - datetime.datetime(2011, 9, 1, 13, 20, 30)) + timezone.make_naive( + datetime.datetime(2011, 9, 1, 17, 20, 30, tzinfo=ICT), EAT + ), + datetime.datetime(2011, 9, 1, 13, 20, 30), + ) - with self.assertRaisesMessage(ValueError, 'make_naive() cannot be applied to a naive datetime'): + with self.assertRaisesMessage( + ValueError, "make_naive() cannot be applied to a naive datetime" + ): timezone.make_naive(datetime.datetime(2011, 9, 1, 13, 20, 30), EAT) def test_make_naive_no_tz(self): self.assertEqual( timezone.make_naive(datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT)), - datetime.datetime(2011, 9, 1, 5, 20, 30) + datetime.datetime(2011, 9, 1, 5, 20, 30), ) def test_make_aware_no_tz(self): self.assertEqual( timezone.make_aware(datetime.datetime(2011, 9, 1, 13, 20, 30)), - datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=timezone.get_fixed_timezone(-300)) + datetime.datetime( + 2011, 9, 1, 13, 20, 30, tzinfo=timezone.get_fixed_timezone(-300) + ), ) def test_make_aware2(self): - CEST = datetime.timezone(datetime.timedelta(hours=2), 'CEST') + CEST = datetime.timezone(datetime.timedelta(hours=2), "CEST") for tz in PARIS_IMPLS: with self.subTest(repr(tz)): self.assertEqual( timezone.make_aware(datetime.datetime(2011, 9, 1, 12, 20, 30), tz), - datetime.datetime(2011, 9, 1, 12, 20, 30, tzinfo=CEST)) + datetime.datetime(2011, 9, 1, 12, 20, 30, tzinfo=CEST), + ) if HAS_PYTZ: with self.assertRaises(ValueError): - timezone.make_aware(CET.localize(datetime.datetime(2011, 9, 1, 12, 20, 30)), CET) + timezone.make_aware( + CET.localize(datetime.datetime(2011, 9, 1, 12, 20, 30)), CET + ) with self.assertRaises(ValueError): - timezone.make_aware(datetime.datetime(2011, 9, 1, 12, 20, 30, tzinfo=PARIS_ZI), PARIS_ZI) + timezone.make_aware( + datetime.datetime(2011, 9, 1, 12, 20, 30, tzinfo=PARIS_ZI), PARIS_ZI + ) @needs_pytz def test_make_naive_pytz(self): self.assertEqual( - timezone.make_naive(CET.localize(datetime.datetime(2011, 9, 1, 12, 20, 30)), CET), - datetime.datetime(2011, 9, 1, 12, 20, 30)) + timezone.make_naive( + CET.localize(datetime.datetime(2011, 9, 1, 12, 20, 30)), CET + ), + datetime.datetime(2011, 9, 1, 12, 20, 30), + ) self.assertEqual( timezone.make_naive( - pytz.timezone("Asia/Bangkok").localize(datetime.datetime(2011, 9, 1, 17, 20, 30)), CET + pytz.timezone("Asia/Bangkok").localize( + datetime.datetime(2011, 9, 1, 17, 20, 30) + ), + CET, ), - datetime.datetime(2011, 9, 1, 12, 20, 30)) - with self.assertRaisesMessage(ValueError, 'make_naive() cannot be applied to a naive datetime'): + datetime.datetime(2011, 9, 1, 12, 20, 30), + ) + with self.assertRaisesMessage( + ValueError, "make_naive() cannot be applied to a naive datetime" + ): timezone.make_naive(datetime.datetime(2011, 9, 1, 12, 20, 30), CET) def test_make_naive_zoneinfo(self): self.assertEqual( - timezone.make_naive(datetime.datetime(2011, 9, 1, 12, 20, 30, tzinfo=PARIS_ZI), PARIS_ZI), - datetime.datetime(2011, 9, 1, 12, 20, 30) + timezone.make_naive( + datetime.datetime(2011, 9, 1, 12, 20, 30, tzinfo=PARIS_ZI), PARIS_ZI + ), + datetime.datetime(2011, 9, 1, 12, 20, 30), ) self.assertEqual( - timezone.make_naive(datetime.datetime(2011, 9, 1, 12, 20, 30, fold=1, tzinfo=PARIS_ZI), PARIS_ZI), - datetime.datetime(2011, 9, 1, 12, 20, 30, fold=1) + timezone.make_naive( + datetime.datetime(2011, 9, 1, 12, 20, 30, fold=1, tzinfo=PARIS_ZI), + PARIS_ZI, + ), + datetime.datetime(2011, 9, 1, 12, 20, 30, fold=1), ) @needs_pytz @@ -244,8 +287,7 @@ class TimezoneTests(SimpleTestCase): dst = timezone.make_aware(ambiguous, timezone=PARIS_ZI) self.assertEqual( - std.astimezone(UTC) - dst.astimezone(UTC), - datetime.timedelta(hours=1) + std.astimezone(UTC) - dst.astimezone(UTC), datetime.timedelta(hours=1) ) self.assertEqual(std.utcoffset(), datetime.timedelta(hours=1)) self.assertEqual(dst.utcoffset(), datetime.timedelta(hours=2)) @@ -273,20 +315,21 @@ class TimezoneTests(SimpleTestCase): dst = timezone.make_aware(non_existent.replace(fold=1), PARIS_ZI) self.assertEqual( - std.astimezone(UTC) - dst.astimezone(UTC), - datetime.timedelta(hours=1) + std.astimezone(UTC) - dst.astimezone(UTC), datetime.timedelta(hours=1) ) self.assertEqual(std.utcoffset(), datetime.timedelta(hours=1)) self.assertEqual(dst.utcoffset(), datetime.timedelta(hours=2)) def test_make_aware_is_dst_deprecation_warning(self): msg = ( - 'The is_dst argument to make_aware(), used by the Trunc() ' - 'database functions and QuerySet.datetimes(), is deprecated as it ' - 'has no effect with zoneinfo time zones.' + "The is_dst argument to make_aware(), used by the Trunc() " + "database functions and QuerySet.datetimes(), is deprecated as it " + "has no effect with zoneinfo time zones." ) with self.assertRaisesMessage(RemovedInDjango50Warning, msg): - timezone.make_aware(datetime.datetime(2011, 9, 1, 13, 20, 30), EAT, is_dst=True) + timezone.make_aware( + datetime.datetime(2011, 9, 1, 13, 20, 30), EAT, is_dst=True + ) def test_get_timezone_name(self): """ @@ -297,24 +340,27 @@ class TimezoneTests(SimpleTestCase): """ tests = [ # datetime.timezone, fixed offset with and without `name`. - (datetime.timezone(datetime.timedelta(hours=10)), 'UTC+10:00'), - (datetime.timezone(datetime.timedelta(hours=10), name='Etc/GMT-10'), 'Etc/GMT-10'), + (datetime.timezone(datetime.timedelta(hours=10)), "UTC+10:00"), + ( + datetime.timezone(datetime.timedelta(hours=10), name="Etc/GMT-10"), + "Etc/GMT-10", + ), # zoneinfo, named and fixed offset. - (zoneinfo.ZoneInfo('Europe/Madrid'), 'Europe/Madrid'), - (zoneinfo.ZoneInfo('Etc/GMT-10'), '+10'), + (zoneinfo.ZoneInfo("Europe/Madrid"), "Europe/Madrid"), + (zoneinfo.ZoneInfo("Etc/GMT-10"), "+10"), ] if HAS_PYTZ: tests += [ # pytz, named and fixed offset. - (pytz.timezone('Europe/Madrid'), 'Europe/Madrid'), - (pytz.timezone('Etc/GMT-10'), '+10'), + (pytz.timezone("Europe/Madrid"), "Europe/Madrid"), + (pytz.timezone("Etc/GMT-10"), "+10"), ] for tz, expected in tests: with self.subTest(tz=tz, expected=expected): self.assertEqual(timezone._get_timezone_name(tz), expected) def test_get_default_timezone(self): - self.assertEqual(timezone.get_default_timezone_name(), 'America/Chicago') + self.assertEqual(timezone.get_default_timezone_name(), "America/Chicago") def test_fixedoffset_timedelta(self): delta = datetime.timedelta(hours=1) diff --git a/tests/utils_tests/test_topological_sort.py b/tests/utils_tests/test_topological_sort.py index 25e0cf4ce9..917cfd5d4a 100644 --- a/tests/utils_tests/test_topological_sort.py +++ b/tests/utils_tests/test_topological_sort.py @@ -1,11 +1,12 @@ from django.test import SimpleTestCase from django.utils.topological_sort import ( - CyclicDependencyError, stable_topological_sort, topological_sort_as_sets, + CyclicDependencyError, + stable_topological_sort, + topological_sort_as_sets, ) class TopologicalSortTests(SimpleTestCase): - def test_basic(self): dependency_graph = { 1: {2, 3}, @@ -15,10 +16,15 @@ class TopologicalSortTests(SimpleTestCase): 5: set(), 6: {5}, } - self.assertEqual(list(topological_sort_as_sets(dependency_graph)), [{2, 3, 5}, {1, 6}, {4}]) - self.assertEqual(stable_topological_sort([1, 2, 3, 4, 5, 6], dependency_graph), [2, 3, 5, 1, 6, 4]) + self.assertEqual( + list(topological_sort_as_sets(dependency_graph)), [{2, 3, 5}, {1, 6}, {4}] + ) + self.assertEqual( + stable_topological_sort([1, 2, 3, 4, 5, 6], dependency_graph), + [2, 3, 5, 1, 6, 4], + ) def test_cyclic_dependency(self): - msg = 'Cyclic dependency in graph: (1, {2}), (2, {1})' + msg = "Cyclic dependency in graph: (1, {2}), (2, {1})" with self.assertRaisesMessage(CyclicDependencyError, msg): list(topological_sort_as_sets({1: {2}, 2: {1}})) diff --git a/tests/utils_tests/test_tree.py b/tests/utils_tests/test_tree.py index 279e8813b9..fe59f778cd 100644 --- a/tests/utils_tests/test_tree.py +++ b/tests/utils_tests/test_tree.py @@ -6,7 +6,7 @@ from django.utils.tree import Node class NodeTests(unittest.TestCase): def setUp(self): - self.node1_children = [('a', 1), ('b', 2)] + self.node1_children = [("a", 1), ("b", 2)] self.node1 = Node(self.node1_children) self.node2 = Node() @@ -15,17 +15,16 @@ class NodeTests(unittest.TestCase): self.assertEqual(str(self.node2), "(DEFAULT: )") def test_repr(self): - self.assertEqual(repr(self.node1), - "<Node: (DEFAULT: ('a', 1), ('b', 2))>") + self.assertEqual(repr(self.node1), "<Node: (DEFAULT: ('a', 1), ('b', 2))>") self.assertEqual(repr(self.node2), "<Node: (DEFAULT: )>") def test_hash(self): node3 = Node(self.node1_children, negated=True) - node4 = Node(self.node1_children, connector='OTHER') + node4 = Node(self.node1_children, connector="OTHER") node5 = Node(self.node1_children) - node6 = Node([['a', 1], ['b', 2]]) - node7 = Node([('a', [1, 2])]) - node8 = Node([('a', (1, 2))]) + node6 = Node([["a", 1], ["b", 2]]) + node7 = Node([("a", [1, 2])]) + node8 = Node([("a", (1, 2))]) self.assertNotEqual(hash(self.node1), hash(self.node2)) self.assertNotEqual(hash(self.node1), hash(node3)) self.assertNotEqual(hash(self.node1), hash(node4)) @@ -43,24 +42,23 @@ class NodeTests(unittest.TestCase): self.assertFalse(self.node2) def test_contains(self): - self.assertIn(('a', 1), self.node1) - self.assertNotIn(('a', 1), self.node2) + self.assertIn(("a", 1), self.node1) + self.assertNotIn(("a", 1), self.node2) def test_add(self): # start with the same children of node1 then add an item node3 = Node(self.node1_children) - node3_added_child = ('c', 3) + node3_added_child = ("c", 3) # add() returns the added data - self.assertEqual(node3.add(node3_added_child, Node.default), - node3_added_child) + self.assertEqual(node3.add(node3_added_child, Node.default), node3_added_child) # we added exactly one item, len() should reflect that self.assertEqual(len(self.node1) + 1, len(node3)) self.assertEqual(str(node3), "(DEFAULT: ('a', 1), ('b', 2), ('c', 3))") def test_add_eq_child_mixed_connector(self): - node = Node(['a', 'b'], 'OR') - self.assertEqual(node.add('a', 'AND'), 'a') - self.assertEqual(node, Node([Node(['a', 'b'], 'OR'), 'a'], 'AND')) + node = Node(["a", "b"], "OR") + self.assertEqual(node.add("a", "AND"), "a") + self.assertEqual(node, Node([Node(["a", "b"], "OR"), "a"], "AND")) def test_negate(self): # negated is False by default @@ -82,8 +80,8 @@ class NodeTests(unittest.TestCase): self.assertNotEqual(node, self.node2) def test_eq_connector(self): - new_node = Node(connector='NEW') - default_node = Node(connector='DEFAULT') + new_node = Node(connector="NEW") + default_node = Node(connector="DEFAULT") self.assertEqual(default_node, self.node2) self.assertNotEqual(default_node, new_node) diff --git a/tests/utils_tests/utils.py b/tests/utils_tests/utils.py index 2aa207287a..b17bd1b097 100644 --- a/tests/utils_tests/utils.py +++ b/tests/utils_tests/utils.py @@ -8,7 +8,7 @@ def on_macos_with_hfs(): some of the tests. """ macos_version = platform.mac_ver()[0] - if macos_version != '': - parsed_macos_version = tuple(int(x) for x in macos_version.split('.')) + if macos_version != "": + parsed_macos_version = tuple(int(x) for x in macos_version.split(".")) return parsed_macos_version < (10, 14) return False |