Repository: Parsl/parsl

Issue:
walltime app function parameter modifies task_record func_name
**Describe the bug**
When the walltime special parameter is passed to a Parsl app the `task_record['func_name']` parameter is set to "wrapper" instead of to the function's name. 

**To Reproduce**
Launch the code below using parsl version 1.2.0:
```
import parsl
print(parsl.__version__, flush = True)
from parsl.app.app import python_app, bash_app
from parsl.config import Config
from parsl.executors import HighThroughputExecutor


@python_app
def test(stdout='std.out', stderr = 'std.err', walltime = 5):
    from time import sleep
    sleep(1)
    Fail = 1/0
    return 'Hello'

def retry_handler(exception, task_record):
    print(task_record['func_name'], flush = True)
    return 1

if __name__ == '__main__':

    config = Config(
        executors = [HighThroughputExecutor()],
        retries = 2,
        retry_handler = retry_handler
    )
    print('Loading Parsl Config', flush = True)
    parsl.load(config)

    fut = test()

    print(fut.result())

```

It will print "wrapper" if the walltime parameter is present and test otherwise. 

**Expected behavior**
The code should print the function's name (test).

**Environment**
- OS: Linux
- Python version: 3.10.4
- Parsl version: 1.2.0


**Distributed Environment**
- Where are you running the Parsl script from ? Local
- Where do you need the workers to run ? Local



Discussion:
This bug is also present in more recent parsl `master` at 50044b7f67cbe34ec0c612a9f16507b1383e53a4

This behaviour also shows up in log messages:

```
parsl.dataflow.dflow:929 submit INFO: Task 0 submitted for App wrapper
```

should show the app name, but instead shows `wrapper`.


Resolving patch:
diff --git a/parsl/app/python.py b/parsl/app/python.py
--- a/parsl/app/python.py
+++ b/parsl/app/python.py
@@ -3,6 +3,8 @@
 import tblib.pickling_support
 tblib.pickling_support.install()
 
+from functools import wraps
+
 from parsl.app.app import AppBase
 from parsl.app.errors import wrap_error
 from parsl.dataflow.dflow import DataFlowKernelLoader
@@ -12,6 +14,7 @@
 
 
 def timeout(f, seconds):
+    @wraps(f)
     def wrapper(*args, **kwargs):
         import threading
         import ctypes


Test patch:
diff --git a/parsl/tests/test_error_handling/test_python_walltime.py b/parsl/tests/test_error_handling/test_python_walltime.py
--- a/parsl/tests/test_error_handling/test_python_walltime.py
+++ b/parsl/tests/test_error_handling/test_python_walltime.py
@@ -5,21 +5,28 @@
 
 
 @parsl.python_app
-def my_app(walltime=1):
+def my_app(t, walltime=1):
     import time
-    time.sleep(1.2)
-    return True
+    time.sleep(t)
+    return 7
 
 
 def test_python_walltime():
-    f = my_app()
+    f = my_app(2)
     with pytest.raises(AppTimeout):
         f.result()
 
 
 def test_python_longer_walltime_at_invocation():
-    f = my_app(walltime=6)
-    f.result()
+    f = my_app(1, walltime=6)
+    assert f.result() == 7
+
+
+def test_python_walltime_wrapped_names():
+    f = my_app(1, walltime=6)
+    assert f.result() == 7
+    assert f.task_def['func'].__name__ == "my_app"
+    assert f.task_def['func_name'] == "my_app"
 
 
 def test_python_bad_decorator_args():