From b12f3719b2752165cf783c2fe60266d86ecbb8d9 Mon Sep 17 00:00:00 2001 From: Hoel Bagard Date: Thu, 12 Mar 2026 11:59:56 +0900 Subject: [PATCH 1/9] behave: add given, when, then, step, use_fixture, fixture and Context --- stubs/behave/METADATA.toml | 2 ++ stubs/behave/behave/__init__.pyi | 13 ++++++++++++ stubs/behave/behave/fixture.pyi | 13 ++++++++++++ stubs/behave/behave/runner.pyi | 30 +++++++++++++++++++++++++++ stubs/behave/behave/step_registry.pyi | 17 +++++++++++++++ 5 files changed, 75 insertions(+) create mode 100644 stubs/behave/METADATA.toml create mode 100644 stubs/behave/behave/__init__.pyi create mode 100644 stubs/behave/behave/fixture.pyi create mode 100644 stubs/behave/behave/runner.pyi create mode 100644 stubs/behave/behave/step_registry.pyi diff --git a/stubs/behave/METADATA.toml b/stubs/behave/METADATA.toml new file mode 100644 index 000000000000..1f6ffdf4b157 --- /dev/null +++ b/stubs/behave/METADATA.toml @@ -0,0 +1,2 @@ +version = "1.3.*" +upstream_repository = "https://github.com/behave/behave" diff --git a/stubs/behave/behave/__init__.pyi b/stubs/behave/behave/__init__.pyi new file mode 100644 index 000000000000..70422a43ef94 --- /dev/null +++ b/stubs/behave/behave/__init__.pyi @@ -0,0 +1,13 @@ +from behave.fixture import fixture as fixture, use_fixture as use_fixture +from behave.step_registry import ( + Given as Given, + Step as Step, + Then as Then, + When as When, + given as given, + step as step, + then as then, + when as when, +) + +__all__ = ["given", "when", "then", "step", "Given", "When", "Then", "Step", "use_fixture", "fixture"] diff --git a/stubs/behave/behave/fixture.pyi b/stubs/behave/behave/fixture.pyi new file mode 100644 index 000000000000..156f84350a55 --- /dev/null +++ b/stubs/behave/behave/fixture.pyi @@ -0,0 +1,13 @@ +from collections.abc import Callable +from typing import Any, Concatenate, ParamSpec, TypeVar + +from behave.runner import Context + +_T = TypeVar("_T") +_F = TypeVar("_F", bound=Callable[..., Any]) +_P = ParamSpec("_P") + +def use_fixture( + fixture_func: Callable[Concatenate[Context, _P], _T], context: Context, *fixture_args: _P.args, **fixture_kwargs: _P.kwargs +) -> _T: ... +def fixture(func: _F | None = None, name: str | None = None, pattern: str | None = None) -> _F: ... diff --git a/stubs/behave/behave/runner.pyi b/stubs/behave/behave/runner.pyi new file mode 100644 index 000000000000..3cff4de4e1b5 --- /dev/null +++ b/stubs/behave/behave/runner.pyi @@ -0,0 +1,30 @@ +from collections.abc import Callable +from contextlib import AbstractContextManager +from typing import Any, ParamSpec + +_P = ParamSpec("_P") + +class Context: + LAYER_NAMES: list[str] + FAIL_ON_CLEANUP_ERRORS: bool + + feature: Any + scenario: Any + tags: set[str] + aborted: bool + failed: bool + table: Any + text: str | None + config: Any + active_outline: Any + + def __init__(self, runner: Any) -> None: ... + def abort(self, reason: str | None = None) -> None: ... + def use_or_assign_param(self, name: str, value: Any) -> Any: ... + def use_or_create_param(self, name: str, factory_func: Callable[_P, Any], *args: _P.args, **kwargs: _P.kwargs) -> Any: ... + def use_with_user_mode(self) -> AbstractContextManager[None]: ... + def execute_steps(self, steps_text: str) -> bool: ... + def add_cleanup(self, cleanup_func: Callable[_P, Any], *args: _P.args, **kwargs: _P.kwargs) -> None: ... + @property + def captured(self) -> Any: ... + def attach(self, mime_type: str, data: bytes) -> None: ... diff --git a/stubs/behave/behave/step_registry.pyi b/stubs/behave/behave/step_registry.pyi new file mode 100644 index 000000000000..e9ec4a653313 --- /dev/null +++ b/stubs/behave/behave/step_registry.pyi @@ -0,0 +1,17 @@ +from collections.abc import Callable +from typing import Any, Concatenate, TypeVar + +from behave.runner import Context as Context + +_F = TypeVar("_F", bound=Callable[Concatenate[Context, ...], None]) + +def given(pattern: str, **kwargs: Any) -> Callable[[_F], _F]: ... +def when(pattern: str, **kwargs: Any) -> Callable[[_F], _F]: ... +def then(pattern: str, **kwargs: Any) -> Callable[[_F], _F]: ... +def step(pattern: str, **kwargs: Any) -> Callable[[_F], _F]: ... + +# Title-case aliases +Given = given +When = when +Then = then +Step = step From a47c17ad46f931f12da9b9aac0f445a7e0a04dfa Mon Sep 17 00:00:00 2001 From: Hoel Bagard Date: Thu, 12 Mar 2026 13:56:49 +0900 Subject: [PATCH 2/9] mark as partial stub --- stubs/behave/METADATA.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/stubs/behave/METADATA.toml b/stubs/behave/METADATA.toml index 1f6ffdf4b157..7b2e7bf0f0b8 100644 --- a/stubs/behave/METADATA.toml +++ b/stubs/behave/METADATA.toml @@ -1,2 +1,3 @@ version = "1.3.*" upstream_repository = "https://github.com/behave/behave" +partial_stub = true From d121d19149dcd2c0e92ccf6fe7d3d77ca3e2d083 Mon Sep 17 00:00:00 2001 From: Hoel Bagard Date: Thu, 12 Mar 2026 15:07:51 +0900 Subject: [PATCH 3/9] add dunder methods --- stubs/behave/behave/runner.pyi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stubs/behave/behave/runner.pyi b/stubs/behave/behave/runner.pyi index 3cff4de4e1b5..38703e64eaeb 100644 --- a/stubs/behave/behave/runner.pyi +++ b/stubs/behave/behave/runner.pyi @@ -19,6 +19,10 @@ class Context: active_outline: Any def __init__(self, runner: Any) -> None: ... + def __getattr__(self, name: str) -> Any: ... + def __setattr__(self, name: str, value: Any) -> None: ... + def __delattr__(self, name: str) -> None: ... + def __contains__(self, name: str) -> bool: ... def abort(self, reason: str | None = None) -> None: ... def use_or_assign_param(self, name: str, value: Any) -> Any: ... def use_or_create_param(self, name: str, factory_func: Callable[_P, Any], *args: _P.args, **kwargs: _P.kwargs) -> Any: ... From b4000402f04bcb8948ab0fd5715d4074fa13f221 Mon Sep 17 00:00:00 2001 From: Hoel Bagard Date: Thu, 12 Mar 2026 15:13:33 +0900 Subject: [PATCH 4/9] stubtest: ignore missing stub --- stubs/behave/METADATA.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stubs/behave/METADATA.toml b/stubs/behave/METADATA.toml index 7b2e7bf0f0b8..5ad943a6ddc2 100644 --- a/stubs/behave/METADATA.toml +++ b/stubs/behave/METADATA.toml @@ -1,3 +1,6 @@ version = "1.3.*" upstream_repository = "https://github.com/behave/behave" partial_stub = true + +[tool.stubtest] +ignore_missing_stub = true From 33ea86a1d42070f43225273bb0fcb9be57405e2d Mon Sep 17 00:00:00 2001 From: Hoel Bagard Date: Fri, 13 Mar 2026 22:20:00 +0900 Subject: [PATCH 5/9] fix: parameter name --- stubs/behave/behave/step_registry.pyi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stubs/behave/behave/step_registry.pyi b/stubs/behave/behave/step_registry.pyi index e9ec4a653313..4f2cf96ce26e 100644 --- a/stubs/behave/behave/step_registry.pyi +++ b/stubs/behave/behave/step_registry.pyi @@ -1,14 +1,14 @@ from collections.abc import Callable from typing import Any, Concatenate, TypeVar -from behave.runner import Context as Context +from behave.runner import Context _F = TypeVar("_F", bound=Callable[Concatenate[Context, ...], None]) -def given(pattern: str, **kwargs: Any) -> Callable[[_F], _F]: ... -def when(pattern: str, **kwargs: Any) -> Callable[[_F], _F]: ... -def then(pattern: str, **kwargs: Any) -> Callable[[_F], _F]: ... -def step(pattern: str, **kwargs: Any) -> Callable[[_F], _F]: ... +def given(step_text: str, **kwargs: Any) -> Callable[[_F], _F]: ... +def when(step_text: str, **kwargs: Any) -> Callable[[_F], _F]: ... +def then(step_text: str, **kwargs: Any) -> Callable[[_F], _F]: ... +def step(step_text: str, **kwargs: Any) -> Callable[[_F], _F]: ... # Title-case aliases Given = given From 7c2b277e5573a139b0d3e5e39551943d56eb36a2 Mon Sep 17 00:00:00 2001 From: Hoel Bagard Date: Mon, 16 Mar 2026 21:32:51 +0900 Subject: [PATCH 6/9] fix: use Incomplete instead of Any --- stubs/behave/behave/runner.pyi | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/stubs/behave/behave/runner.pyi b/stubs/behave/behave/runner.pyi index 38703e64eaeb..e30f9640b03b 100644 --- a/stubs/behave/behave/runner.pyi +++ b/stubs/behave/behave/runner.pyi @@ -1,6 +1,7 @@ +from _typeshed import Incomplete from collections.abc import Callable from contextlib import AbstractContextManager -from typing import Any, ParamSpec +from typing import ParamSpec _P = ParamSpec("_P") @@ -8,27 +9,27 @@ class Context: LAYER_NAMES: list[str] FAIL_ON_CLEANUP_ERRORS: bool - feature: Any - scenario: Any + feature: Incomplete + scenario: Incomplete tags: set[str] aborted: bool failed: bool - table: Any + table: Incomplete text: str | None - config: Any - active_outline: Any + config: Incomplete + active_outline: Incomplete - def __init__(self, runner: Any) -> None: ... - def __getattr__(self, name: str) -> Any: ... - def __setattr__(self, name: str, value: Any) -> None: ... + def __init__(self, runner) -> None: ... + def __getattr__(self, name: str) -> Incomplete: ... + def __setattr__(self, name: str, value) -> None: ... def __delattr__(self, name: str) -> None: ... def __contains__(self, name: str) -> bool: ... def abort(self, reason: str | None = None) -> None: ... - def use_or_assign_param(self, name: str, value: Any) -> Any: ... - def use_or_create_param(self, name: str, factory_func: Callable[_P, Any], *args: _P.args, **kwargs: _P.kwargs) -> Any: ... + def use_or_assign_param(self, name: str, value): ... + def use_or_create_param(self, name: str, factory_func: Callable[_P, Incomplete], *args: _P.args, **kwargs: _P.kwargs): ... def use_with_user_mode(self) -> AbstractContextManager[None]: ... def execute_steps(self, steps_text: str) -> bool: ... - def add_cleanup(self, cleanup_func: Callable[_P, Any], *args: _P.args, **kwargs: _P.kwargs) -> None: ... + def add_cleanup(self, cleanup_func: Callable[_P, Incomplete], *args: _P.args, **kwargs: _P.kwargs) -> None: ... @property - def captured(self) -> Any: ... + def captured(self): ... def attach(self, mime_type: str, data: bytes) -> None: ... From 9994610a7ac79c17b5888bceb2973d4f6dae0b35 Mon Sep 17 00:00:00 2001 From: Hoel Bagard Date: Mon, 16 Mar 2026 22:09:21 +0900 Subject: [PATCH 7/9] add behave to the exclude list in pyrightconfig.stricter.json --- pyrightconfig.stricter.json | 1 + 1 file changed, 1 insertion(+) diff --git a/pyrightconfig.stricter.json b/pyrightconfig.stricter.json index 269b302254eb..cf57f92f0df2 100644 --- a/pyrightconfig.stricter.json +++ b/pyrightconfig.stricter.json @@ -26,6 +26,7 @@ "stubs/auth0-python", "stubs/Authlib", "stubs/aws-xray-sdk", + "stubs/behave", "stubs/boltons", "stubs/braintree", "stubs/cffi", From a31fef087defdf5b04efb98ae208d54570daa2b4 Mon Sep 17 00:00:00 2001 From: Hoel Bagard Date: Mon, 16 Mar 2026 23:02:54 +0900 Subject: [PATCH 8/9] fix: add missing __getattr__ --- stubs/behave/behave/fixture.pyi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stubs/behave/behave/fixture.pyi b/stubs/behave/behave/fixture.pyi index 156f84350a55..b7a257847a1b 100644 --- a/stubs/behave/behave/fixture.pyi +++ b/stubs/behave/behave/fixture.pyi @@ -1,3 +1,4 @@ +from _typeshed import Incomplete from collections.abc import Callable from typing import Any, Concatenate, ParamSpec, TypeVar @@ -11,3 +12,4 @@ def use_fixture( fixture_func: Callable[Concatenate[Context, _P], _T], context: Context, *fixture_args: _P.args, **fixture_kwargs: _P.kwargs ) -> _T: ... def fixture(func: _F | None = None, name: str | None = None, pattern: str | None = None) -> _F: ... +def __getattr__(name: str) -> Incomplete: ... From 886073540f08ef0421a835acb0faa0f1dcfdd632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ho=C3=ABl=20Bagard?= <34478245+hoel-bagard@users.noreply.github.com> Date: Mon, 16 Mar 2026 23:03:53 +0900 Subject: [PATCH 9/9] Apply suggestions from code review (__getattr__, ClassVar) Co-authored-by: Sebastian Rittau fix: use ClassVar Co-authored-by: Sebastian Rittau Apply suggestions from code review Co-authored-by: Sebastian Rittau Apply suggestions from code review Co-authored-by: Sebastian Rittau fix: add missing imports --- stubs/behave/behave/runner.pyi | 13 ++++++++----- stubs/behave/behave/step_registry.pyi | 13 ++++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/stubs/behave/behave/runner.pyi b/stubs/behave/behave/runner.pyi index e30f9640b03b..a3abfa2d0de2 100644 --- a/stubs/behave/behave/runner.pyi +++ b/stubs/behave/behave/runner.pyi @@ -1,23 +1,24 @@ from _typeshed import Incomplete from collections.abc import Callable from contextlib import AbstractContextManager -from typing import ParamSpec +from typing import ClassVar, ParamSpec _P = ParamSpec("_P") class Context: - LAYER_NAMES: list[str] - FAIL_ON_CLEANUP_ERRORS: bool + LAYER_NAMES: ClassVar[list[str]] + FAIL_ON_CLEANUP_ERRORS: ClassVar[bool] - feature: Incomplete + feature: Incomplete | None scenario: Incomplete tags: set[str] aborted: bool failed: bool - table: Incomplete + table: Incomplete | None text: str | None config: Incomplete active_outline: Incomplete + fail_on_cleanup_errors: bool def __init__(self, runner) -> None: ... def __getattr__(self, name: str) -> Incomplete: ... @@ -33,3 +34,5 @@ class Context: @property def captured(self): ... def attach(self, mime_type: str, data: bytes) -> None: ... + +def __getattr__(name: str) -> Incomplete: ... diff --git a/stubs/behave/behave/step_registry.pyi b/stubs/behave/behave/step_registry.pyi index 4f2cf96ce26e..9b0237896c3d 100644 --- a/stubs/behave/behave/step_registry.pyi +++ b/stubs/behave/behave/step_registry.pyi @@ -1,17 +1,20 @@ +from _typeshed import Incomplete from collections.abc import Callable -from typing import Any, Concatenate, TypeVar +from typing import Concatenate, TypeVar from behave.runner import Context _F = TypeVar("_F", bound=Callable[Concatenate[Context, ...], None]) -def given(step_text: str, **kwargs: Any) -> Callable[[_F], _F]: ... -def when(step_text: str, **kwargs: Any) -> Callable[[_F], _F]: ... -def then(step_text: str, **kwargs: Any) -> Callable[[_F], _F]: ... -def step(step_text: str, **kwargs: Any) -> Callable[[_F], _F]: ... +def given(step_text: str, **kwargs) -> Callable[[_F], _F]: ... +def when(step_text: str, **kwargs) -> Callable[[_F], _F]: ... +def then(step_text: str, **kwargs) -> Callable[[_F], _F]: ... +def step(step_text: str, **kwargs) -> Callable[[_F], _F]: ... # Title-case aliases Given = given When = when Then = then Step = step + +def __getattr__(name: str) -> Incomplete: ...