Question: I have a decorator that "wraps" a function in a new one that has one extra positional argument in the beginning:

```py
import functools

def my_decorator(f):
    @functools.wraps(f)
    def wrapped(message: str, *args, **kwargs):
        print('Decorated:', message)
        return f(*args, **kwargs)
    return wrapped

```

Here is an example on how my decorator is used:

```py
@my_decorator
def foo(a: int, b: str) -> None:
    print('Hello world', [a, b])

foo('test', 2, '3')
# Decorated: test
# Hello world [2, '3']

```

So far so good. However, I'd like my decorator to create a new function with the correct signature. But since I used `@functools.wraps`, I am getting the same signature as the original function:

```py
import inspect

print('Signature:', inspect.signature(foo))
# Signature: (a: int, b: str) -> None

```

But I want to get `(message: str, a: int, b: str) -> None` instead. **How to do this?**

I need the correct signature to get correct type checks and also because I am using a framework that relies on function signatures for its behavior.

Answer: 
Regarding the type annotations, this will be the complete and correct one:

```py
import functools
from typing import Callable, ParamSpec, Protocol, TypeVar

P = ParamSpec("P")
RT = TypeVar("RT")
T_co = TypeVar("T_co", covariant=True)

class WithMessage(Protocol[P, T_co]):
    def __call__(self, message: str, *args: P.args, **kwds: P.kwargs) -> T_co:
        ...

def my_decorator(f: Callable[P, RT]) -> WithMessage[P, RT]:
    @functools.wraps(f)
    def wrapped(message: str, *args: P.args, **kwargs: P.kwargs) -> RT:
        print("Decorated:", message)
        return f(*args, **kwargs)

    return wrapped

@my_decorator
def foo(a: int, b: str) -> None:
    print("Hello world", [a, b])

```

Unfortunately, `inspect.signature` does not seem to respect even the complete and correct type annotations:

```py
# prints: "Signature: (a: int, b: str) -> None"
# instead of "Signature: (message: str, a: int, b: "str) -> None
print("Signature:", inspect.signature(foo))

```

Here's [a playground](https://mypy-play.net/?mypy=latest&python=3.10&gist=2acb141b431a965d7553faf65e7deca3) with this solution.
This isn't the most elegant solution since it's set manually not automatically, but something like this could work. Not sure about automatically adjusting it based on the signature of the wrapped command itself.

```
import functools
from inspect import Parameter, signature

def my_decorator(f):

    @functools.wraps(f)
    def wrapped(message: str, *args, **kwargs):
        print('Decorated:', message)
        return f(*args, **kwargs)

    message_param = Parameter('message', Parameter.POSITIONAL_OR_KEYWORD, annotation=str)
    sig = signature(f)
    parameters = [message_param] + list(sig.parameters.values())
    wrapped.__signature__ = sig.replace(parameters=parameters)

    return wrapped

```