Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

instrumented functions aren't pickleable #356

Closed
apotterri opened this issue Jul 27, 2024 · 2 comments
Closed

instrumented functions aren't pickleable #356

apotterri opened this issue Jul 27, 2024 · 2 comments
Assignees
Labels
bug Something isn't working

Comments

@apotterri
Copy link
Collaborator

apotterri commented Jul 27, 2024

Trying to pickle a function that has been instrumented will raise an exception. This is almost certainly the cause of these failures:
#318 (comment)
#336 (comment)
and is probably the cause of the failures that show the message

NotImplementedError: object proxy must define __reduce_ex__()

as seen in in #319 (comment)

@apotterri apotterri added the bug Something isn't working label Jul 27, 2024
@apotterri apotterri self-assigned this Jul 27, 2024
@dustinbyrne dustinbyrne assigned apotterri and unassigned apotterri Jul 30, 2024
@apotterri
Copy link
Collaborator Author

Title: Update FunctionWrapper to Support Pickling of Instances
Problem
The FunctionWrapper class currently does not support pickling of instances, resulting in a NotImplementedError when attempting to pickle objects that use this wrapper.

Analysis
Pickling in Python requires objects to implement the reduce_ex method or the reduce method. These methods help the pickle module understand how to serialize the object. For wrapped functions or objects, we need to ensure that any wrapper classes also support this serialization process.

When we look at the implementation of FunctionWrapper, we can see that the core issue is the absence of methods that aid the pickling process. Specifically, the wrapper must define reduce_ex (and possibly reduce) methods to allow the pickle module to properly serialize the wrapped object along with its wrapping.

Proposed Changes
To solve this problem, we need to add the reduce_ex method to the FunctionWrapper class. This method will ensure that both the wrapper and the wrapped object are properly serialized.

Step-by-Step Changes:
Define reduce_ex method in FunctionWrapper:

Implement the method to return a callable and the arguments needed to recreate the FunctionWrapper instance.
Ensure the wrapped function or object is correctly included in the serialization.
Adjust unit tests to validate the new pickling support:

Add a test case to check if an instance of FunctionWrapper can be pickled and unpickled without errors.
Verify that the unwrapped function or object retains its original functionality after unpickling.
Specific Changes:
In the FunctionWrapper class (assumed to be in wrapt module), add:

python
Copy
class FunctionWrapper:
# Existing methods and properties...

def __reduce_ex__(self, proto):
    return (self.__class__, (self.__wrapped__,), self.__dict__)

Update the test suite to include checks for pickling support:

In tests/test_pickle.py test case:
python
Copy
class TestFunctionWrapperPickle(unittest.TestCase):

def test_function_wrapper_pickle(self):
    @wrapt.function_wrapper
    def wrapper(wrapped, instance, args, kwargs):
        return wrapped(*args, **kwargs)

    def sample_function(x, y):
        return x + y

    wrapped_function = wrapper(sample_function)
    pickled_function = pickle.dumps(wrapped_function)
    unpickled_function = pickle.loads(pickled_function)

    self.assertEqual(unpickled_function(2, 3), 5)
    self.assertTrue(isinstance(unpickled_function, type(wrapped_function)))

These changes will ensure that the FunctionWrapper class provides full support for pickling, thereby resolving the NotImplementedError and allowing wrapped objects to be serialized and deserialized seamlessly.

@apotterri
Copy link
Collaborator Author

Fixed by #367

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant