Repository: smarie/python-makefun

Issue:
Can't wrap function with StrEnum as argument with default
This issue is similar to #63 

```python
from enum import StrEnum
from makefun import wraps

class A(StrEnum):
    a = 'a'

def foo(a=A.a):
    pass

@wraps(foo)
def test(*args, **kwargs):
    return foo(*args, **kwargs)
```

When this runs it throws:
```
Error in generated code:
def foo(a=<A.a: 'a'>):
    return _func_impl_(a=a)

Traceback (most recent call last):
  File "/home/alexeyd/a.py", line 10, in <module>
    @wraps(foo)
     ^^^^^^^^^^
  File "/usr/python3.11/lib/python3.11/site-packages/makefun/main.py", line 1062, in replace_f
    return create_function(func_signature=func_signature,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/python3.11/lib/python3.11/site-packages/makefun/main.py", line 323, in create_function
    f = _make(co_name, params_names, body, evaldict)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/python3.11/lib/python3.11/site-packages/makefun/main.py", line 714, in _make
    code = compile(body, filename, 'single')
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<makefun-gen-0>", line 1
    def foo(a=<A.a: 'a'>):
              ^
SyntaxError: invalid syntax
```

The problem is StrEnum is also an str (that's a point of the class), so [here](https://github.com/smarie/python-makefun/blob/525ce1fa6239899d3cd6c83aba54504c091767d7/src/makefun/main.py#L469) it is assumed to have safe repr.


I propose to change the check from checking isinstance to checking ```type(symbol) in TYPES_WITH_SAFE_REPR```

Discussion:

Patch:
diff --git a/src/makefun/main.py b/src/makefun/main.py
index 22cd52e..e682155 100644
--- a/src/makefun/main.py
+++ b/src/makefun/main.py
@@ -466,7 +466,7 @@ def _signature_symbol_needs_protection(symbol, evaldict):
     :param symbol:
     :return:
     """
-    if symbol is not None and symbol is not Parameter.empty and not isinstance(symbol, TYPES_WITH_SAFE_REPR):
+    if symbol is not None and symbol is not Parameter.empty and type(symbol) not in TYPES_WITH_SAFE_REPR:
         try:
             # check if the repr() of the default value is equal to itself.
             return eval(repr(symbol), evaldict) != symbol  # noqa  # we cannot use ast.literal_eval, too restrictive


Test patch:
diff --git a/tests/test_issues.py b/tests/test_issues.py
index d314d6e..ed32a9b 100644
--- a/tests/test_issues.py
+++ b/tests/test_issues.py
@@ -280,3 +280,19 @@ def test_issue_91():
     """This test should work also in python 2 ! """
     assert is_identifier("_results_bag")
     assert is_identifier("hello__bag")
+
+
+def test_issue_98():
+    class A(str):
+        def __str__(self):
+            return 'custom str'
+
+        def __repr__(self):
+            return 'custom repr'
+
+    def foo(a=A()):
+        pass
+
+    @wraps(foo)
+    def test(*args, **kwargs):
+        return foo(*args, **kwargs)