def test_with_preamble(self):
        m = MethodBuilder("basic_wrapper", None)

        m.with_preamble("A value")
        assert m.doc_preamble == "A value"

        m.with_preamble("A different value", only_if=False)
        assert m.doc_preamble == "A value"
    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)