diff options
author | CaselIT <cfederico87@gmail.com> | 2021-06-15 22:32:05 +0200 |
---|---|---|
committer | CaselIT <cfederico87@gmail.com> | 2021-06-15 23:38:07 +0200 |
commit | 7756b35e23ec11b64a1ac37afcb41dda3ca29913 (patch) | |
tree | a2c46870a195f22c7489bface5a890cf90acff5c /tests | |
parent | c0f0a3238fe1ec8029d66ad6ac518b60c78c36ed (diff) | |
download | alembic-7756b35e23ec11b64a1ac37afcb41dda3ca29913.tar.gz |
Revendor editor and make dateutil optional
Re-implemented the ``python-editor`` dependency as a small internal
function to avoid the need for external dependencies.
The implementation is based on the original
version in 7b91b325ff43a0e9235e0f15b57391fa92352626.
Make the ``python-dateutil`` library an optional dependency.
This library is only required if the ``timezone`` option
is used in the Alembic configuration.
An extra require named ``tz`` is available with
``pip install alembic[tz]`` to install it.
Fixes: #674
Fixes: #856
Change-Id: I07f17b2fea01e3a3d677ce95333fe3e8d8d438fd
Diffstat (limited to 'tests')
-rw-r--r-- | tests/test_command.py | 20 | ||||
-rw-r--r-- | tests/test_editor.py | 106 | ||||
-rw-r--r-- | tests/test_script_production.py | 16 |
3 files changed, 125 insertions, 17 deletions
diff --git a/tests/test_command.py b/tests/test_command.py index 4114be0..a477a1d 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -11,12 +11,10 @@ from sqlalchemy import text from alembic import __version__ from alembic import command from alembic import config -from alembic import testing from alembic import util from alembic.script import ScriptDirectory from alembic.testing import assert_raises from alembic.testing import assert_raises_message -from alembic.testing import config as testing_config from alembic.testing import eq_ from alembic.testing import is_false from alembic.testing import is_true @@ -924,7 +922,7 @@ class EditTest(TestBase): % (EditTest.cfg.config_args["here"], EditTest.c) ) - with mock.patch("alembic.util.edit") as edit: + with mock.patch("alembic.util.open_in_editor") as edit: command.edit(self.cfg, "head") edit.assert_called_with(expected_call_arg) @@ -934,22 +932,10 @@ class EditTest(TestBase): % (EditTest.cfg.config_args["here"], EditTest.b) ) - with mock.patch("alembic.util.edit") as edit: + with mock.patch("alembic.util.open_in_editor") as edit: command.edit(self.cfg, self.b[0:3]) edit.assert_called_with(expected_call_arg) - @testing_config.requirements.editor_installed - @testing.emits_python_deprecation_warning("the imp module is deprecated") - def test_edit_with_missing_editor(self): - with mock.patch("editor.edit") as edit_mock: - edit_mock.side_effect = OSError("file not found") - assert_raises_message( - util.CommandError, - "file not found", - util.edit, - "/not/a/file.txt", - ) - def test_edit_no_revs(self): assert_raises_message( util.CommandError, @@ -975,7 +961,7 @@ class EditTest(TestBase): ) command.stamp(self.cfg, self.b) - with mock.patch("alembic.util.edit") as edit: + with mock.patch("alembic.util.open_in_editor") as edit: command.edit(self.cfg, "current") edit.assert_called_with(expected_call_arg) diff --git a/tests/test_editor.py b/tests/test_editor.py new file mode 100644 index 0000000..0ec6f5f --- /dev/null +++ b/tests/test_editor.py @@ -0,0 +1,106 @@ +import os +from os.path import join +from unittest.mock import patch + +from alembic import util +from alembic.testing import combinations +from alembic.testing import expect_raises_message +from alembic.testing.fixtures import TestBase + + +class TestHelpers(TestBase): + def common(self, cb, is_posix=True): + with patch("alembic.util.editor.check_call") as check_call, patch( + "alembic.util.editor.exists" + ) as exists, patch( + "alembic.util.editor.is_posix", + new=is_posix, + ), patch( + "os.pathsep", new=":" if is_posix else ";" + ): + cb(check_call, exists) + + @combinations((True,), (False,)) + def test_edit_with_user_editor(self, posix): + def go(check_call, exists): + test_environ = {"EDITOR": "myvim", "PATH": "/usr/bin"} + executable = join("/usr/bin", "myvim") + if not posix: + executable += ".exe" + + exists.side_effect = lambda fname: fname == executable + util.open_in_editor("myfile", test_environ) + check_call.assert_called_with([executable, "myfile"]) + + self.common(go, posix) + + @combinations(("EDITOR",), ("VISUAL",)) + def test_edit_with_user_editor_exists(self, key): + def go(check_call, exists): + test_environ = {key: "myvim", "PATH": "/usr/bin"} + exists.side_effect = lambda fname: fname == "myvim" + util.open_in_editor("myfile", test_environ) + check_call.assert_called_with(["myvim", "myfile"]) + + self.common(go) + + @combinations((True,), (False,)) + def test_edit_with_user_editor_precedence(self, with_path): + def go(check_call, exists): + test_environ = { + "EDITOR": "myvim", + "VISUAL": "myvisual", + "PATH": "/usr/bin", + } + exes = ["myvim", "myvisual"] + if with_path: + exes = [join("/usr/bin", n) for n in exes] + exists.side_effect = lambda fname: fname in exes + util.open_in_editor("myfile", test_environ) + check_call.assert_called_with([exes[0], "myfile"]) + + self.common(go) + + def test_edit_with_user_editor_abs(self): + def go(check_call, exists): + test_environ = {"EDITOR": "/foo/myvim", "PATH": "/usr/bin"} + exists.side_effect = lambda fname: fname == "/usr/bin/foo/myvim" + with expect_raises_message(util.CommandError, "EDITOR"): + util.open_in_editor("myfile", test_environ) + + self.common(go) + + def test_edit_with_default_editor(self): + def go(check_call, exists): + test_environ = {"PATH": os.pathsep.join(["/usr/bin", "/bin"])} + executable = join("/bin", "vim") + + exists.side_effect = lambda fname: fname == executable + util.open_in_editor("myfile", test_environ) + check_call.assert_called_with([executable, "myfile"]) + + self.common(go) + + def test_edit_with_default_editor_windows(self): + def go(check_call, exists): + test_environ = { + "PATH": os.pathsep.join( + [r"C:\Windows\System32", r"C:\Users\user\bin"] + ) + } + executable = join(r"C:\Users\user\bin", "notepad.exe") + + exists.side_effect = lambda fname: fname == executable + util.open_in_editor("myfile", test_environ) + check_call.assert_called_with([executable, "myfile"]) + + self.common(go, False) + + def test_edit_with_missing_editor(self): + def go(check_call, exists): + test_environ = {} + exists.return_value = False + with expect_raises_message(util.CommandError, "EDITOR"): + util.open_in_editor("myfile", test_environ) + + self.common(go) diff --git a/tests/test_script_production.py b/tests/test_script_production.py index 15d9366..2edae26 100644 --- a/tests/test_script_production.py +++ b/tests/test_script_production.py @@ -15,6 +15,7 @@ from alembic.script import ScriptDirectory from alembic.testing import assert_raises_message from alembic.testing import assertions from alembic.testing import eq_ +from alembic.testing import expect_raises_message from alembic.testing import is_ from alembic.testing import mock from alembic.testing import ne_ @@ -34,6 +35,10 @@ from alembic.testing.env import write_script from alembic.testing.fixtures import TestBase from alembic.util import CommandError +try: + from unittest.mock import patch +except ImportError: + from mock import patch # noqa env, abc, def_ = None, None, None @@ -250,6 +255,17 @@ class ScriptNamingTest(TestBase): datetime.datetime(2012, 7, 25, 15, 8, 5), ) + def test_no_dateutil_module(self): + with patch("alembic.script.base.tz", new=None): + with expect_raises_message( + CommandError, "The library 'python-dateutil' is required" + ): + self._test_tz( + "utc", + datetime.datetime(2012, 7, 25, 15, 8, 5), + datetime.datetime(2012, 7, 25, 15, 8, 5), + ) + class RevisionCommandTest(TestBase): def setUp(self): |