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 /alembic/util | |
| 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 'alembic/util')
| -rw-r--r-- | alembic/util/__init__.py | 2 | ||||
| -rw-r--r-- | alembic/util/editor.py | 71 | ||||
| -rw-r--r-- | alembic/util/pyfiles.py | 12 |
3 files changed, 72 insertions, 13 deletions
diff --git a/alembic/util/__init__.py b/alembic/util/__init__.py index cfdab49..2a3d8a8 100644 --- a/alembic/util/__init__.py +++ b/alembic/util/__init__.py @@ -1,4 +1,5 @@ from .compat import raise_ # noqa +from .editor import open_in_editor # noqa from .exc import CommandError from .langhelpers import _with_legacy_names # noqa from .langhelpers import asbool # noqa @@ -19,7 +20,6 @@ from .messaging import status # noqa from .messaging import warn # noqa from .messaging import write_outstream # noqa from .pyfiles import coerce_resource_to_filename # noqa -from .pyfiles import edit # noqa from .pyfiles import load_python_file # noqa from .pyfiles import pyc_file_from_path # noqa from .pyfiles import template_to_file # noqa diff --git a/alembic/util/editor.py b/alembic/util/editor.py new file mode 100644 index 0000000..c27f0f3 --- /dev/null +++ b/alembic/util/editor.py @@ -0,0 +1,71 @@ +import os +from os.path import exists +from os.path import join +from os.path import splitext +from subprocess import check_call + +from .compat import is_posix +from .exc import CommandError + + +def open_in_editor(filename, environ=None): + """ + Opens the given file in a text editor. If the environment variable + ``EDITOR`` is set, this is taken as preference. + + Otherwise, a list of commonly installed editors is tried. + + If no editor matches, an :py:exc:`OSError` is raised. + + :param filename: The filename to open. Will be passed verbatim to the + editor command. + :param environ: An optional drop-in replacement for ``os.environ``. Used + mainly for testing. + """ + + try: + editor = _find_editor(environ) + check_call([editor, filename]) + except Exception as exc: + raise CommandError("Error executing editor (%s)" % (exc,)) from exc + + +def _find_editor(environ=None): + candidates = _default_editors() + for i, var in enumerate(("EDITOR", "VISUAL")): + if var in environ: + user_choice = environ[var] + if exists(user_choice): + return user_choice + if os.sep not in user_choice: + candidates.insert(i, user_choice) + + for candidate in candidates: + path = _find_executable(candidate, environ) + if path is not None: + return path + raise OSError( + "No suitable editor found. Please set the " + '"EDITOR" or "VISUAL" environment variables' + ) + + +def _find_executable(candidate, environ): + # Assuming this is on the PATH, we need to determine it's absolute + # location. Otherwise, ``check_call`` will fail + if not is_posix and splitext(candidate)[1] != ".exe": + candidate += ".exe" + for path in environ.get("PATH", "").split(os.pathsep): + value = join(path, candidate) + if exists(value): + return value + return None + + +def _default_editors(): + # Look for an editor. Prefer the user's choice by env-var, fall back to + # most commonly installed editor (nano/vim) + if is_posix: + return ["sensible-editor", "editor", "nano", "vim", "code"] + else: + return ["code.exe", "notepad++.exe", "notepad.exe"] diff --git a/alembic/util/pyfiles.py b/alembic/util/pyfiles.py index 8dfb9db..1bc5be3 100644 --- a/alembic/util/pyfiles.py +++ b/alembic/util/pyfiles.py @@ -10,7 +10,6 @@ from .compat import has_pep3147 from .compat import load_module_py from .compat import load_module_pyc from .compat import py3k -from .compat import raise_ from .exc import CommandError @@ -75,17 +74,6 @@ def pyc_file_from_path(path): return None -def edit(path): - """Given a source path, run the EDITOR for it""" - - import editor - - try: - editor.edit(path) - except Exception as exc: - raise_(CommandError("Error executing editor (%s)" % (exc,)), from_=exc) - - def load_python_file(dir_, filename): """Load a file from the given path as a Python module.""" |
