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

Pickled FakeFilesystem causes RecursionError when unpickling #445

Closed
ttsalo opened this issue Oct 24, 2018 · 3 comments
Closed

Pickled FakeFilesystem causes RecursionError when unpickling #445

ttsalo opened this issue Oct 24, 2018 · 3 comments
Labels

Comments

@ttsalo
Copy link

ttsalo commented Oct 24, 2018

When unpickling a pickled FakeFilesystem object, the getattr method of FakeFile loops forever.

import pickle
from pyfakefs import fake_filesystem
filesystem = fake_filesystem.FakeFilesystem()
filesystem.open_files = []
p = pickle.dumps(filesystem)
pickle.loads(p)

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File ".local/lib/python3.6/site-packages/pyfakefs/fake_filesystem.py", line 477, in __getattr__
    return getattr(self.stat_result, item)
  File ".local/lib/python3.6/site-packages/pyfakefs/fake_filesystem.py", line 477, in __getattr__
    return getattr(self.stat_result, item)
  File ".local/lib/python3.6/site-packages/pyfakefs/fake_filesystem.py", line 477, in __getattr__
    return getattr(self.stat_result, item)
  [Previous line repeated 323 more times]
RecursionError: maximum recursion depth exceeded

The fix is fairly simple, use the same conditional as setattr already does :

--- fake_filesystem.py.orig	2018-10-24 14:05:28.497666345 +0300
+++ fake_filesystem.py	2018-10-15 14:32:20.872485946 +0300
@@ -471,13 +471,15 @@
           st_ctime: The desired creation time.
         """
         self.st_ctime = st_ctime
 
     def __getattr__(self, item):
         """Forward some properties to stat_result."""
-        return getattr(self.stat_result, item)
+        if item in self.stat_types:
+            return getattr(self.stat_result, item)
+        return super(FakeFile, self).__getattr__(item)
 
     def __setattr__(self, key, value):
         """Forward some properties to stat_result."""
         if key in self.stat_types:
             return setattr(self.stat_result, key, value)
         return super(FakeFile, self).__setattr__(key, value)

I can make a pull request if needed

@mrbean-bremen
Copy link
Member

Thanks - could have sworn I already fixed that some time ago... ah well.
I can fix this in the evening, or you can make a PR - as you said, the fix is trivial.

@mrbean-bremen
Copy link
Member

Hm, this works nice in Python 3, but not in Python 2.
Pickling doesn't work there because FakeStatResult uses a class method as a member variable , which cannot be pickled out of the box in Python 2. This can be solved, but the other problem is that the current implementation replaces that with a lambda function on copy to simulate the real behavior. This can also not be pickled in Python 2, and seems to be a little more complicated to handle.
I will think a bit more about this - maybe have another go tomorrow...

@mrbean-bremen
Copy link
Member

Thanks again for the report - you seem to use pyfakefs in ways no one tried before...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants