Skip to content

Commit

Permalink
Add cloup.get_current_context
Browse files Browse the repository at this point in the history
  • Loading branch information
janluke committed Nov 13, 2023
1 parent 170d0d3 commit edea710
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 21 deletions.
3 changes: 2 additions & 1 deletion cloup/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
HelpFormatter,
HelpSection,
)
from ._context import Context, pass_context
from ._context import Context, get_current_context, pass_context
from ._params import Argument, Option, argument, option
from ._option_groups import (
OptionGroup,
Expand Down Expand Up @@ -103,6 +103,7 @@
"constraint",
"dir_path",
"file_path",
"get_current_context",
"group",
"help_option",
"option",
Expand Down
58 changes: 38 additions & 20 deletions cloup/_context.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from __future__ import annotations

import warnings
from typing import Any, Callable, cast, Dict, List, Optional, Type, TypeVar, TYPE_CHECKING
from functools import update_wrapper
from typing import (
Any, Callable, cast, Dict, List, Optional, Type, TypeVar, TYPE_CHECKING, overload,
)

import click

Expand All @@ -11,6 +13,41 @@
from cloup.formatting import HelpFormatter
from cloup.typing import MISSING, Possibly

if TYPE_CHECKING:
import typing_extensions as te

P = te.ParamSpec("P")

R = TypeVar("R")


@overload
def get_current_context() -> "Context":
...


@overload
def get_current_context(silent: bool = False) -> "Optional[Context]":
...


def get_current_context(silent: bool = False) -> "Optional[Context]":
"""Equivalent to :func:`click.get_current_context` but casts the returned
:class:`click.Context` object to :class:`cloup.Context` (which is safe when using
cloup commands classes and decorators)."""
return cast(Optional[Context], click.get_current_context(silent=silent))


def pass_context(f: "Callable[te.Concatenate[Context, P], R]") -> "Callable[P, R]":
"""Marks a callback as wanting to receive the current context object as first
argument. Equivalent to :func:`click.pass_context` but assumes the current context
is of type :class:`cloup.Context`."""

def new_func(*args: "P.args", **kwargs: "P.kwargs") -> R:
return f(get_current_context(), *args, **kwargs)

return update_wrapper(new_func, f)


def _warn_if_formatter_settings_conflict(
ctx_key: str,
Expand Down Expand Up @@ -225,22 +262,3 @@ def settings(
dictionary, so that you can be guided by your IDE.
"""
return pick_non_missing(locals())


if TYPE_CHECKING:
import typing_extensions as te

P = te.ParamSpec("P")

R = TypeVar("R")


def pass_context(f: Callable[te.Concatenate[Context, P], R]) -> Callable[P, R]:
"""Marks a callback as wanting to receive the current context
object as first argument.
"""

def new_func(*args: P.args, **kwargs: P.kwargs) -> R:
return f(cast(Context, click.get_current_context()), *args, **kwargs)

return update_wrapper(new_func, f)

0 comments on commit edea710

Please sign in to comment.