aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/alembic/script/write_hooks.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/alembic/script/write_hooks.py')
-rw-r--r--.venv/lib/python3.12/site-packages/alembic/script/write_hooks.py179
1 files changed, 179 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/alembic/script/write_hooks.py b/.venv/lib/python3.12/site-packages/alembic/script/write_hooks.py
new file mode 100644
index 00000000..99771479
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/alembic/script/write_hooks.py
@@ -0,0 +1,179 @@
+# mypy: allow-untyped-defs, allow-incomplete-defs, allow-untyped-calls
+# mypy: no-warn-return-any, allow-any-generics
+
+from __future__ import annotations
+
+import shlex
+import subprocess
+import sys
+from typing import Any
+from typing import Callable
+from typing import Dict
+from typing import List
+from typing import Mapping
+from typing import Optional
+from typing import Union
+
+from .. import util
+from ..util import compat
+
+
+REVISION_SCRIPT_TOKEN = "REVISION_SCRIPT_FILENAME"
+
+_registry: dict = {}
+
+
+def register(name: str) -> Callable:
+ """A function decorator that will register that function as a write hook.
+
+ See the documentation linked below for an example.
+
+ .. seealso::
+
+ :ref:`post_write_hooks_custom`
+
+
+ """
+
+ def decorate(fn):
+ _registry[name] = fn
+ return fn
+
+ return decorate
+
+
+def _invoke(
+ name: str, revision: str, options: Mapping[str, Union[str, int]]
+) -> Any:
+ """Invokes the formatter registered for the given name.
+
+ :param name: The name of a formatter in the registry
+ :param revision: A :class:`.MigrationRevision` instance
+ :param options: A dict containing kwargs passed to the
+ specified formatter.
+ :raises: :class:`alembic.util.CommandError`
+ """
+ try:
+ hook = _registry[name]
+ except KeyError as ke:
+ raise util.CommandError(
+ f"No formatter with name '{name}' registered"
+ ) from ke
+ else:
+ return hook(revision, options)
+
+
+def _run_hooks(path: str, hook_config: Mapping[str, str]) -> None:
+ """Invoke hooks for a generated revision."""
+
+ from .base import _split_on_space_comma
+
+ names = _split_on_space_comma.split(hook_config.get("hooks", ""))
+
+ for name in names:
+ if not name:
+ continue
+ opts = {
+ key[len(name) + 1 :]: hook_config[key]
+ for key in hook_config
+ if key.startswith(name + ".")
+ }
+ opts["_hook_name"] = name
+ try:
+ type_ = opts["type"]
+ except KeyError as ke:
+ raise util.CommandError(
+ f"Key {name}.type is required for post write hook {name!r}"
+ ) from ke
+ else:
+ with util.status(
+ f"Running post write hook {name!r}", newline=True
+ ):
+ _invoke(type_, path, opts)
+
+
+def _parse_cmdline_options(cmdline_options_str: str, path: str) -> List[str]:
+ """Parse options from a string into a list.
+
+ Also substitutes the revision script token with the actual filename of
+ the revision script.
+
+ If the revision script token doesn't occur in the options string, it is
+ automatically prepended.
+ """
+ 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, posix=compat.is_posix
+ )
+ cmdline_options_list = [
+ option.replace(REVISION_SCRIPT_TOKEN, path)
+ for option in cmdline_options_list
+ ]
+ return cmdline_options_list
+
+
+@register("console_scripts")
+def console_scripts(
+ path: str, options: dict, ignore_output: bool = False
+) -> None:
+ try:
+ entrypoint_name = options["entrypoint"]
+ except KeyError as ke:
+ raise util.CommandError(
+ f"Key {options['_hook_name']}.entrypoint is required for post "
+ f"write hook {options['_hook_name']!r}"
+ ) from ke
+ for entry in compat.importlib_metadata_get("console_scripts"):
+ if entry.name == entrypoint_name:
+ impl: Any = entry
+ break
+ else:
+ raise util.CommandError(
+ f"Could not find entrypoint console_scripts.{entrypoint_name}"
+ )
+ cwd: Optional[str] = options.get("cwd", None)
+ cmdline_options_str = options.get("options", "")
+ cmdline_options_list = _parse_cmdline_options(cmdline_options_str, path)
+
+ kw: Dict[str, Any] = {}
+ if ignore_output:
+ kw["stdout"] = kw["stderr"] = subprocess.DEVNULL
+
+ subprocess.run(
+ [
+ sys.executable,
+ "-c",
+ f"import {impl.module}; {impl.module}.{impl.attr}()",
+ ]
+ + cmdline_options_list,
+ cwd=cwd,
+ **kw,
+ )
+
+
+@register("exec")
+def exec_(path: str, options: dict, ignore_output: bool = False) -> None:
+ try:
+ executable = options["executable"]
+ except KeyError as ke:
+ raise util.CommandError(
+ f"Key {options['_hook_name']}.executable is required for post "
+ f"write hook {options['_hook_name']!r}"
+ ) from ke
+ cwd: Optional[str] = options.get("cwd", None)
+ cmdline_options_str = options.get("options", "")
+ cmdline_options_list = _parse_cmdline_options(cmdline_options_str, path)
+
+ kw: Dict[str, Any] = {}
+ if ignore_output:
+ kw["stdout"] = kw["stderr"] = subprocess.DEVNULL
+
+ subprocess.run(
+ [
+ executable,
+ *cmdline_options_list,
+ ],
+ cwd=cwd,
+ **kw,
+ )