From: Ben Mares <15216687+maresb@users.noreply.github.com> Date: Mon, 29 Mar 2021 20:44:36 +0000 (-0400) Subject: Add cwd post-write hook option X-Git-Tag: rel_1_6_0~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e49691ef7e822ec24c2c733a1c442be9ba3cccda;p=thirdparty%2Fsqlalchemy%2Falembic.git Add cwd post-write hook option Fixes #822 Implements a `.cwd` suboption for post-write hooks. For example, one can do ```ini [post_write_hooks] hooks = pre-commit pre-commit.type = console_scripts pre-commit.entrypoint = pre-commit pre-commit.options = run --files REVISION_SCRIPT_FILENAME pre-commit.cwd = %(here)s ``` This feature is illustrated by the last line above. ### Description * Improve the names of some variables recently created in #820 in order to make the code more readable. * Add `cwd` as an option which is passed directly into `subprocess.run()` * Add a brief description to the documentation, together with an example with `pre-commit`. ### Checklist This pull request is: A new feature implementation - [X] please include the issue number, and create an issue if none exists, which must - [X] include a complete example of how the feature would look. - [X] Please include: `Fixes: #` in the commit message - [x] **please include tests.** **Help requested:** I can't think of any simple way to write a test. Does anyone have a suggestion??? Closes: #823 Pull-request: https://github.com/sqlalchemy/alembic/pull/823 Pull-request-sha: 9a694a7fdfc55160d1e124f6119a7a5677ce019a Change-Id: Iacbb06d52acc362588cff2cdfec442393be8594a --- diff --git a/alembic/script/write_hooks.py b/alembic/script/write_hooks.py index 27e9a484..133bf046 100644 --- a/alembic/script/write_hooks.py +++ b/alembic/script/write_hooks.py @@ -88,7 +88,7 @@ def _run_hooks(path, hook_config): ) -def _parse_options(options_str, path): +def _parse_cmdline_options(cmdline_options_str, path): """Parse options from a string into a list. Also substitutes the revision script token with the actual filename of @@ -97,13 +97,14 @@ def _parse_options(options_str, path): If the revision script token doesn't occur in the options string, it is automatically prepended. """ - if REVISION_SCRIPT_TOKEN not in options_str: - options_str = REVISION_SCRIPT_TOKEN + " " + options_str - options_list = shlex.split(options_str) - options_list = [ - option.replace(REVISION_SCRIPT_TOKEN, path) for option in options_list + if REVISION_SCRIPT_TOKEN not in cmdline_options_str: + cmdline_options_str = REVISION_SCRIPT_TOKEN + " " + cmdline_options_str + cmdline_options_list = shlex.split(cmdline_options_str) + cmdline_options_list = [ + option.replace(REVISION_SCRIPT_TOKEN, path) + for option in cmdline_options_list ] - return options_list + return cmdline_options_list @register("console_scripts") @@ -122,8 +123,9 @@ def console_scripts(path, options): ) iter_ = pkg_resources.iter_entry_points("console_scripts", entrypoint_name) impl = next(iter_) - options_str = options.get("options", "") - options_list = _parse_options(options_str, path) + cwd = options.get("cwd", None) + cmdline_options_str = options.get("options", "") + cmdline_options_list = _parse_cmdline_options(cmdline_options_str, path) subprocess.run( [ @@ -132,5 +134,6 @@ def console_scripts(path, options): "import %s; %s()" % (impl.module_name, ".".join((impl.module_name,) + impl.attrs)), ] - + options_list + + cmdline_options_list, + cwd=cwd, ) diff --git a/docs/build/autogenerate.rst b/docs/build/autogenerate.rst index a5129f8b..4a5b27ac 100644 --- a/docs/build/autogenerate.rst +++ b/docs/build/autogenerate.rst @@ -753,15 +753,16 @@ configuration for the ``"black"`` post write hook, which includes: function, this configuration variable would refer to the name under which the custom hook was registered; see the next section for an example. -* ``entrypoint`` - this part of the configuration is specific to the - ``"console_scripts"`` hook runner. This is the name of the `setuptools entrypoint `_ +The following configuration options are specific to the ``"console_scripts"`` +hook runner: + +* ``entrypoint`` - the name of the `setuptools entrypoint `_ that is used to define the console script. Within the scope of standard Python console scripts, this name will match the name of the shell command that is usually run for the code formatting tool, in this case ``black``. -* ``options`` - this is also specific to the ``"console_scripts"`` hook runner. - This is a line of command-line options that will be passed to the - code formatting tool. In this case, we want to run the command +* ``options`` - a line of command-line options that will be passed to + the code formatting tool. In this case, we want to run the command ``black /path/to/revision.py -l 79``. By default, the revision path is positioned as the first argument. In order specify a different position, we can use the ``REVISION_SCRIPT_FILENAME`` token as illustrated by the @@ -777,6 +778,7 @@ configuration for the ``"black"`` post write hook, which includes: autopep8.entrypoint = autopep8 autopep8.options = --in-place REVISION_SCRIPT_FILENAME +* ``cwd`` - optional working directory from which the console script is run. When running ``alembic revision -m "rev1"``, we will now see the ``black`` tool's output as well:: @@ -811,6 +813,20 @@ configuration as follows:: When using the above configuration, a newly generated revision file will be processed first by the "black" tool, then by the "zimports" tool. +Alternatively, one can run pre-commit itself as follows:: + + [post_write_hooks] + + hooks = pre-commit + + pre-commit.type = console_scripts + pre-commit.entrypoint = pre-commit + pre-commit.options = run --files REVISION_SCRIPT_FILENAME + pre-commit.cwd = %(here)s + +(The last line helps to ensure that the ``.pre-commit-config.yaml`` file +will always be found, regardless of from where the hook was called.) + .. _post_write_hooks_custom: Writing Custom Hooks as Python Functions diff --git a/docs/build/unreleased/822.rst b/docs/build/unreleased/822.rst new file mode 100644 index 00000000..d3e16cea --- /dev/null +++ b/docs/build/unreleased/822.rst @@ -0,0 +1,9 @@ +.. change:: + :tags: feature + :tickets: 822 + + Implement a ``.cwd`` (current working directory) suboption for post-write hooks + (of type ``console_scripts``). This is useful for tools like pre-commit, which + rely on the working directory to locate the necessary config files. Add + pre-commit as an example to the documentation. Minor change: rename some variables + from ticket #819 to improve readability. diff --git a/tests/test_post_write.py b/tests/test_post_write.py index 653e09cd..9beb1f6a 100644 --- a/tests/test_post_write.py +++ b/tests/test_post_write.py @@ -126,7 +126,7 @@ class RunHookTest(TestBase): ) def _run_black_with_config( - self, input_config, expected_additional_arguments_fn + self, input_config, expected_additional_arguments_fn, cwd=None ): self.cfg = _no_sql_testing_config(directives=input_config) impl = mock.Mock(attrs=("foo", "bar"), module_name="black_module") @@ -149,7 +149,8 @@ class RunHookTest(TestBase): "-c", "import black_module; black_module.foo.bar()", ] - + expected_additional_arguments_fn(rev.path) + + expected_additional_arguments_fn(rev.path), + cwd=cwd, ) ], ) @@ -186,3 +187,19 @@ black.options = arg1 REVISION_SCRIPT_FILENAME 'multi-word arg' \ self._run_black_with_config( input_config, expected_additional_arguments_fn ) + + def test_black_with_cwd(self): + input_config = """ +[post_write_hooks] +hooks = black +black.type = console_scripts +black.entrypoint = black +black.cwd = /path/to/cwd + """ + + def expected_additional_arguments_fn(rev_path): + return [rev_path] + + self._run_black_with_config( + input_config, expected_additional_arguments_fn, cwd="/path/to/cwd" + )