Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dill/_dill.py
Original file line number Diff line number Diff line change
Expand Up @@ -2031,7 +2031,7 @@ def save_function(pickler, obj):
fattr = getattr(obj, fattrname, None)
if fattr is not None:
state_dict[fattrname] = fattr
if obj.__qualname__ != obj.__name__:
if obj.__qualname__ != getattr(obj.__code__, "co_qualname", obj.__code__.co_name):
state_dict['__qualname__'] = obj.__qualname__
if '__name__' not in globs or obj.__module__ != globs['__name__']:
state_dict['__module__'] = obj.__module__
Expand Down
40 changes: 40 additions & 0 deletions dill/tests/test_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,45 @@ def f2(self):
assert f1.f2() is f1


@functools.wraps(function_a)
def function_wrapped(a):
return function_a(a)

def test_issue_602():
# Check that __qualname__ is set correctly when functools.wraps is used.
# Different code paths are used for module-level and local functions, so
# we test the various combinations.

# Global wrapping global

copied_global = dill.copy(function_wrapped)
assert copied_global.__name__ == function_a.__name__
assert copied_global.__qualname__ == function_a.__qualname__

# Local wrapping global

@functools.wraps(function_a)
def function_wrapped_local(a):
return function_a(a)

copied_local = dill.copy(function_wrapped_local)
assert copied_local.__name__ == function_a.__name__
assert copied_local.__qualname__ == function_a.__qualname__

# Local wrapping local

def local():
pass

@functools.wraps(local)
def wrapped_local():
local()

copied_local = dill.copy(wrapped_local)
assert copied_local.__name__ == local.__name__
assert copied_local.__qualname__ == local.__qualname__


def test_functions():
dumped_func_a = dill.dumps(function_a)
assert dill.loads(dumped_func_a)(0) == 0
Expand Down Expand Up @@ -138,4 +177,5 @@ def test_code_object():
if __name__ == '__main__':
test_functions()
test_issue_510()
test_issue_602()
test_code_object()