def test_build(self): def basic_implementation(self, a, b, **kwargs): return (a, b, kwargs) m = MethodBuilder("basic_wrapper", basic_implementation) m.with_preamble("Hello World!") m.with_returns("All the arguments.", annotation=Tuple) m.with_notes("This method doesn't do a whole lot.") m.with_arg("a", desc="A value.", annotation=int) with pytest.raises( RuntimeError, match=re.escape( "Proposed method signature `basic_wrapper(self, a: int)` is not compatible with implementation signature `implementation(self, a, b, **kwargs)`" ), ): m.build() m.with_arg("b", desc="Another value.", annotation=str) m.with_arg( "c", desc="Yet another value.", annotation=float, virtual=True, kind="keyword_only", ) c = m.build() assert (c.__doc__ == textwrap.dedent(""" Hello World! Args: a: A value. b: Another value. c: Yet another value. Returns: All the arguments. Notes: This method doesn't do a whole lot. """).strip()) assert str( inspect.signature(c)) == "(self, a: int, b: str, *, c: float)" assert c(None, 1, "two", c=3.0) == (1, "two", {"c": 3.0}) with pytest.raises( TypeError, match=re.escape( "basic_wrapper() got unexpected keyword arguments: {'d'}." ), ): c(None, 1, "two", c=3.0, d=None)
def test_with_arg(self): m = MethodBuilder("basic_wrapper", None) m.with_arg("a", desc="A value.") assert len(m.method_args) == 2 assert m.method_args[0].name == "self" assert m.method_args[1].name == "a" m.with_arg("c", desc="Another value.", kind="keyword_only", virtual=True) assert len(m.method_args) == 3 assert m.method_args[2].name == "kwargs" assert m.method_args[2].kind == Parameter.VAR_KEYWORD assert len(m.method_args_virtual) == 1 assert m.method_args_virtual[0].kind == Parameter.KEYWORD_ONLY m.with_arg("d", desc="Another value.", only_if=False) assert len(m.method_args) == 3 with pytest.raises( RuntimeError, match=re.escape( "Virtual arguments can only be `KEYWORD_ONLY` or `VAR_KEYWORD`, not `POSITIONAL_OR_KEYWORD`." ), ): m.with_arg("d", desc="Another value.", virtual=True) with pytest.raises( RuntimeError, match=re.escape( "Arguments of kind `POSITIONAL_OR_KEYWORD` cannot be added after `VAR_KEYWORD` arguments." ), ): m.with_arg("d", desc="Another value.") with pytest.raises( RuntimeError, match=re.escape( "Arguments of kind `POSITIONAL_ONLY` cannot be added after `VAR_KEYWORD` arguments." ), ): m.with_arg("d", desc="Another value.", kind="positional_only") m.with_arg("e", desc="Collect all.", kind="var_keyword", virtual=True) with pytest.raises( RuntimeError, match=re.escape( "Virtual arguments of kind `KEYWORD_ONLY` cannot be added after `VAR_KEYWORD` arguments." ), ): m.with_arg("f", desc="Another value.", virtual=True, kind="keyword_only")