easy +10 pts

Log Calls Decorator

Build a decorator that logs each function call with arguments and return value.

Write a decorator `log_calls` that wraps a function so that every call prints a line to stdout in the exact format: `Called: <function_name>(<args>...) -> <return_value>` - `<function_name>` is the original function's `__name__`. - `<args>` is the comma-separated list of positional arguments and keyword arguments as they appear in the call. For each positional argument, use `repr(arg)`. For each keyword argument, format as `key=repr(value)`. If there are no arguments, print `()` (i.e., no spaces after the name). - After the arrow, print the returned value using `repr()`. The decorator must preserve the original function's metadata (name, docstring, etc.) using `functools.wraps`. The decorated function should return exactly what the original function returns. Implement the decorator so it can be used with `@log_calls` directly (no arguments). Example: If a function `add(a, b)` returns `a + b`, then `add(2, 3)` should print `Called: add(2, 3) -> 5`. Your code will be tested by calling a decorated function and capturing stdout. Your implementation must print exactly one line per call, with no extra spaces or newlines beyond the line ending.

Constraints

- The function may take any number of positional and keyword arguments. - The return value may be any Python object; use `repr()` for display. - Do not modify the original function's behavior. - The decorator must be defined in the same module and be named `log_calls`. - The provided test functions `add`, `greet`, `noop`, and `mul` are already decorated with `@log_calls` in the starter code.

Example

```python
@log_calls
def add(a, b):
    return a + b

add(2, 3)
# Called: add(2, 3) -> 5

@log_calls
def greet(name, greeting='Hello'):
    return f'{greeting}, {name}!'

greet('Alice')
# Called: greet('Alice', greeting='Hello') -> 'Hello, Alice!'
```
10 points ~15 min

Recent Submissions

No submissions yet — hit Run Tests to try!

Hints

Use functools.wraps to preserve metadata.
Build the argument string using repr() for each value.
Remember to call func(*args, **kwargs) and print before returning the result.
Python 3
All tests passed!
Test Results
Press Ctrl+Enter or click Run Tests to execute your code.