Skip to content

Hacking through WrapFS #207

@xandfury

Description

@xandfury

Disclaimer: This might be long for something stupid or simple. Please be patient :-)


As discussed in #204 - I am trying to write a custom FS that caches files and directories. For the same I needed a custom file wrapper that does setup and teardown stuff. This is how it looks like:

class _custom_file_wrapper(object):
    """This is a custom file class that does some setup and teardown stuff.."""

    def __init__(self,
                 file_system,
                 parent_fs,
                 path,
                 mode,
                 buffering=-1,
                 encoding=None,
                 newline='',
                 line_buffering=False):
        print('We should see this message when a new file is created!!')
        self._file = parent_fs.openbin(path=path,
                                       mode=mode,
                                       buffering=buffering,
                                       encoding=encoding)

        # do some setUp stuff with _file.
        print('Filesystem: {}, Parent File system: {}'.format(file_system, parent_fs))

    def __enter__(self):
        return self._file

    def __exit__(self, exc_type, exc_value, traceback):
        self.close()
        return False

    def close(self):
        # do some tearDown stuff for the _file object.
        print('Closing File ....')
        self._file.close()

    def __getattr__(self, item):
        return getattr(self._file, item)

My WrapFS wraps an OSFS instance and overwrites functionality such as open and openbin to use the above _custom_file_wrapper object. This works fine when the essential methods are called but when non-essential methods such as move or copy are called, my _custom_file_wrapper is ignored. Below is how my custom WrapFS instance looks like:

class TestFileSystem(WrapFS):
    def __init__(self, path):
        super(TestFileSystem, self).__init__(open_fs(path))   # wrap osfs at path
        self._wrap_fs._meta['supports_rename'] = False
        # ^^^ not sure if this is required as a custom getmeta() is defined below.
        # But still - to be safe.

    def getmeta(self, namespace="standard"):
        """Defined so that os.rename is never used."""
        self.check()
        meta = self.delegate_fs().getmeta(namespace=namespace)
        meta['supports_rename'] = False
        return meta


    def openbin(self, path, mode="r", buffering=-1, **options):
        print('Inside openbin of TestFileSystem. This is a test!')
        return _custom_file_wrapper(parent_fs=self.delegate_fs(),
                                    file_system=self,
                                    path=path,
                                    mode=Mode(mode).to_platform_bin(),
                                    buffering=buffering)

    # NOTE: open() is similar. I omitted it's definition since  `move()`  uses move.move_file which would
    # neither use open() or openbin()

When run together, the following result is obtained (Link to gist)

Starting FS test
Listing files/directories in cwd: ['another.py', 'test.py']
Rename is False. os.rename should not be used
Inside openbin of TestFileSystem. This is a test!
We should see this message when a new file is created!!
Filesystem: <osfs '/home/abhinav/demo'>, Parent File system: <osfs '/home/abhinav/demo'>
Closing File ....
------------- Start Move --------------
------------- Stop Move --------------
Stopping FS test

As seen from above output, my custom defined essesntial methods were not invoked during the call of move().

Problem:
The reason for this is that all methods defined in WrapFS call the underlying OSFS methods.
I was hoping that in it's implementation, only essential methods would be allowed to do so.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions