GithubHelp home page GithubHelp logo

libfuse / pyfuse3 Goto Github PK

View Code? Open in Web Editor NEW
166.0 13.0 48.0 1.16 MB

Python 3 bindings for libfuse 3 with asynchronous API (Trio compatible)

Home Page: https://pyfuse3.readthedocs.io/

License: Other

Emacs Lisp 0.10% Python 47.49% HTML 0.05% C 8.02% Shell 0.32% Cython 44.03%

pyfuse3's Introduction

Warning - no longer developed!

pyfuse3 is no longer actively developed and just receiving community-contributed maintenance to keep it alive for some time.

The pyfuse3 Module

pyfuse3 is a set of Python 3 bindings for libfuse 3. It provides an asynchronous API compatible with Trio and asyncio, and enables you to easily write a full-featured Linux filesystem in Python.

pyfuse3 releases can be downloaded from PyPi. The documentation can be read online and is also included in the doc/html directory of the pyfuse3 tarball.

Getting Help

Please report any bugs on the issue tracker. For discussion and questions, please use the general FUSE mailing list. A searchable mailing list archive is kindly provided by Gmane.

Development Status

pyfuse3 is in beta. Bugs are likely.

pyfuse3 uses semantic versioning. This means backwards incompatible changes in the API will be reflected in an increase of the major version number.

Contributing

The pyfuse3 source code is available on GitHub.

pyfuse3's People

Contributors

bgilbert avatar blueyed avatar eli-schwartz avatar geofft avatar grunthos avatar i-ky avatar justanotherarchivist avatar jwilk avatar locutusofborg avatar mayli avatar mgorny avatar mkhon avatar nagexiucai avatar nikratio avatar odgalvin avatar pcgrosen avatar thomaswaldmann avatar touilleman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyfuse3's Issues

readdir hang if have more than 23 entries

Maybe I am using this wrong but when try to do ls on a directory that has more than 23 files readdir stuck in a endless loop.
Below is the function for readdir - the off param does not start at 0 if you have more than 23 entries.
it increment by one as you add more entries. I cannot find where this being pass in -
Can you help?
this same code work using the old llfuse module

    async def readdir(self, dirinode, off, token):
        log.debug('readdir %d starting at %d', dirinode, off)
        log.debug("readdir token: {}".format(token))
        dirnode = self.superblock[dirinode]
        assert dirnode.type == NodeType.Dir
        log.debug("readdir DIR node: {}, enum: {}".format(dirnode, enumerate(dirnode.children[off:])))

        for n, child in enumerate(dirnode.children[off:]):
            log.debug("CHILD: {}, n={}".format(child.name, n))
            pyfuse3.readdir_reply(token, child.name, await self.getattr(child.inode), n+1)

        log.debug("\n\n****readdir END LOOP, dirinode {} offset={}\n".format(dirinode, off))

Error listing virtual files

I am trying to mount a virtual drive from files I have in a cloud. I have based on the example passthroughfs.py.

One of the methods I have adapted is def _getattr:

def _getattr(self, name):
        # Temporarily commented for testing
        # for attr in ('st_ino', 'st_mode', 'st_nlink', 'st_uid', 'st_gid',
        #              'st_rdev', 'st_size', 'st_atime_ns', 'st_mtime_ns',
        #              'st_ctime_ns'):
        for attr in ('st_ino', 'st_mode', 'st_uid', 'st_gid', 'st_size'):
            # Code adapted to obtain the attributes
            if attr == 'st_ino':
                attr_value = int(element['id']) # 10 digits
            if attr == 'st_size':
                attr_value = element['size']
            elif attr == 'st_uid':
                attr_value = os.getuid()
            elif attr == 'st_gid':
                attr_value = os.getgid()
            elif attr == 'st_mode':
                if element['isFolder']:
                    # attr_value = (stat.S_IFDIR | 0o644)
                    attr_value = 16893 # Hardcoded temporary
                else:
                    attr_value = (stat.S_IFREG | 0o664)
            setattr(entry, attr, attr_value)

        entry.generation = 0
        entry.entry_timeout = 0
        entry.attr_timeout = 0
        entry.st_blksize = 512
        entry.st_blocks = ((entry.st_size+entry.st_blksize-1) // entry.st_blksize)

        return entry

When I list ls -l the mounted directory, lookup method is called for each file:

async def lookup(self, inode_p, name, ctx=None):
    name = fsdecode(name)
    log.debug('lookup for %s in %d', name, inode_p)
    path = os.path.join(self._inode_to_path(inode_p), name)
    attr = self._getattr(name)
    if name != '.' and name != '..':
        self._add_path(attr.st_ino, path)
    return attr

And console show:

ls: you can not access 'test/My movie 1.mkv': File or directory does not exist
ls: you can not access 'test/dirTemp': File or directory does not exist
total 0
-????????? ? ? ? ?            ? 'My movie 1.mkv'
d????????? ? ? ? ?            ?  dirTemp

It seems that the attributes assigned in _getattr did not work

issues with py 3.12.0a7 and cy 3.0.0b2

2023-05-14T17:24:47.2404006Z Successfully installed Cython-3.0.0b2
2023-05-14T17:24:47.3118974Z 
2023-05-14T17:24:47.3119815Z [notice] A new release of pip is available: 23.0.1 -> 23.1.2
2023-05-14T17:24:47.3120334Z [notice] To update, run: pip install --upgrade pip
2023-05-14T17:24:47.4072289Z ##[group]Run cython --version
2023-05-14T17:24:47.4072570Z �[36;1mcython --version�[0m
2023-05-14T17:24:47.4072801Z �[36;1mtest/ci-test.sh�[0m
2023-05-14T17:24:47.4124583Z shell: /usr/bin/bash -e {0}
2023-05-14T17:24:47.4124813Z env:
2023-05-14T17:24:47.4124996Z   FORCE_COLOR: 1
2023-05-14T17:24:47.4125499Z   pythonLocation: /opt/hostedtoolcache/Python/3.12.0-alpha.7/x64
2023-05-14T17:24:47.4125864Z   LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.12.0-alpha.7/x64/lib
2023-05-14T17:24:47.4126138Z ##[endgroup]
2023-05-14T17:24:47.4921892Z Cython version 3.0.0b2
2023-05-14T17:24:48.1590810Z running build_cython
2023-05-14T17:24:48.2479890Z /home/runner/work/pyfuse3/pyfuse3/setup.py:231: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
2023-05-14T17:24:48.2480685Z   if not hit or LooseVersion(hit.group(1)) < "0.29":
2023-05-14T17:24:48.4482391Z Compiling /home/runner/work/pyfuse3/pyfuse3/src/pyfuse3.pyx
2023-05-14T17:24:50.6019353Z running build_ext
2023-05-14T17:24:50.6097275Z building 'pyfuse3' extension
2023-05-14T17:24:50.6097900Z creating build
2023-05-14T17:24:50.6099375Z creating build/temp.linux-x86_64-cpython-312
2023-05-14T17:24:50.6100059Z creating build/temp.linux-x86_64-cpython-312/src
2023-05-14T17:24:50.6101765Z gcc -pthread -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O3 -Wall -fPIC -I/opt/hostedtoolcache/Python/3.12.0-alpha.7/x64/include/python3.12 -c src/pyfuse3.c -o build/temp.linux-x86_64-cpython-312/src/pyfuse3.o -I/usr/include/fuse3 -DFUSE_USE_VERSION=32 -Wall -Wextra -Wconversion -Wsign-compare -DPYFUSE3_VERSION=\"3.2.3\" -Wno-unused-function -Wno-implicit-fallthrough -Wno-unused-function -Wno-unused-parameter
2023-05-14T17:24:50.7458439Z src/pyfuse3.c: In function ‘__pyx_gb_7pyfuse3_20generator6’:
2023-05-14T17:24:50.7466112Z src/pyfuse3.c:2305:45: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:50.7466660Z  2305 | #define __Pyx_PyErr_Occurred()  __pyx_tstate->curexc_type
2023-05-14T17:24:50.7466985Z       |                                             ^~
2023-05-14T17:24:50.7467383Z src/pyfuse3.c:11938:30: note: in expansion of macro ‘__Pyx_PyErr_Occurred’
2023-05-14T17:24:50.7467723Z 11938 |         PyObject* exc_type = __Pyx_PyErr_Occurred();
2023-05-14T17:24:50.7468005Z       |                              ^~~~~~~~~~~~~~~~~~~~
2023-05-14T17:24:50.7504473Z src/pyfuse3.c: In function ‘__pyx_gb_7pyfuse3_23generator7’:
2023-05-14T17:24:50.7511571Z src/pyfuse3.c:2305:45: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:50.7512066Z  2305 | #define __Pyx_PyErr_Occurred()  __pyx_tstate->curexc_type
2023-05-14T17:24:50.7512358Z       |                                             ^~
2023-05-14T17:24:50.7512766Z src/pyfuse3.c:12535:30: note: in expansion of macro ‘__Pyx_PyErr_Occurred’
2023-05-14T17:24:50.7513091Z 12535 |         PyObject* exc_type = __Pyx_PyErr_Occurred();
2023-05-14T17:24:50.7513394Z       |                              ^~~~~~~~~~~~~~~~~~~~
2023-05-14T17:24:50.7593596Z src/pyfuse3.c: In function ‘__pyx_gb_7pyfuse3_29generator9’:
2023-05-14T17:24:50.7600777Z src/pyfuse3.c:2305:45: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:50.7601350Z  2305 | #define __Pyx_PyErr_Occurred()  __pyx_tstate->curexc_type
2023-05-14T17:24:50.7601674Z       |                                             ^~
2023-05-14T17:24:50.7602063Z src/pyfuse3.c:13869:30: note: in expansion of macro ‘__Pyx_PyErr_Occurred’
2023-05-14T17:24:50.7602406Z 13869 |         PyObject* exc_type = __Pyx_PyErr_Occurred();
2023-05-14T17:24:50.7602683Z       |                              ^~~~~~~~~~~~~~~~~~~~
2023-05-14T17:24:50.7822690Z src/pyfuse3.c: In function ‘__pyx_gb_7pyfuse3_47generator15’:
2023-05-14T17:24:50.7832405Z src/pyfuse3.c:2305:45: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:50.7832959Z  2305 | #define __Pyx_PyErr_Occurred()  __pyx_tstate->curexc_type
2023-05-14T17:24:50.7833747Z       |                                             ^~
2023-05-14T17:24:50.7834217Z src/pyfuse3.c:17574:30: note: in expansion of macro ‘__Pyx_PyErr_Occurred’
2023-05-14T17:24:50.7834607Z 17574 |         PyObject* exc_type = __Pyx_PyErr_Occurred();
2023-05-14T17:24:50.7834926Z       |                              ^~~~~~~~~~~~~~~~~~~~
2023-05-14T17:24:50.7865221Z src/pyfuse3.c: In function ‘__pyx_gb_7pyfuse3_50generator16’:
2023-05-14T17:24:50.7875338Z src/pyfuse3.c:2305:45: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:50.7875895Z  2305 | #define __Pyx_PyErr_Occurred()  __pyx_tstate->curexc_type
2023-05-14T17:24:50.7876231Z       |                                             ^~
2023-05-14T17:24:50.7876679Z src/pyfuse3.c:18140:30: note: in expansion of macro ‘__Pyx_PyErr_Occurred’
2023-05-14T17:24:50.7877067Z 18140 |         PyObject* exc_type = __Pyx_PyErr_Occurred();
2023-05-14T17:24:50.7877409Z       |                              ^~~~~~~~~~~~~~~~~~~~
2023-05-14T17:24:50.7908759Z src/pyfuse3.c: In function ‘__pyx_gb_7pyfuse3_53generator17’:
2023-05-14T17:24:50.7918766Z src/pyfuse3.c:2305:45: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:50.7919252Z  2305 | #define __Pyx_PyErr_Occurred()  __pyx_tstate->curexc_type
2023-05-14T17:24:50.7919573Z       |                                             ^~
2023-05-14T17:24:50.7919961Z src/pyfuse3.c:18719:30: note: in expansion of macro ‘__Pyx_PyErr_Occurred’
2023-05-14T17:24:50.7920304Z 18719 |         PyObject* exc_type = __Pyx_PyErr_Occurred();
2023-05-14T17:24:50.7920582Z       |                              ^~~~~~~~~~~~~~~~~~~~
2023-05-14T17:24:50.8015013Z src/pyfuse3.c: In function ‘__pyx_gb_7pyfuse3_59generator19’:
2023-05-14T17:24:50.8025392Z src/pyfuse3.c:2305:45: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:50.8025875Z  2305 | #define __Pyx_PyErr_Occurred()  __pyx_tstate->curexc_type
2023-05-14T17:24:50.8026194Z       |                                             ^~
2023-05-14T17:24:50.8026598Z src/pyfuse3.c:20128:32: note: in expansion of macro ‘__Pyx_PyErr_Occurred’
2023-05-14T17:24:50.8026923Z 20128 |           PyObject* exc_type = __Pyx_PyErr_Occurred();
2023-05-14T17:24:50.8027205Z       |                                ^~~~~~~~~~~~~~~~~~~~
2023-05-14T17:24:50.8073708Z src/pyfuse3.c: In function ‘__pyx_gb_7pyfuse3_62generator20’:
2023-05-14T17:24:50.8085081Z src/pyfuse3.c:2305:45: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:50.8085573Z  2305 | #define __Pyx_PyErr_Occurred()  __pyx_tstate->curexc_type
2023-05-14T17:24:50.8085868Z       |                                             ^~
2023-05-14T17:24:50.8086272Z src/pyfuse3.c:20780:30: note: in expansion of macro ‘__Pyx_PyErr_Occurred’
2023-05-14T17:24:50.8086598Z 20780 |         PyObject* exc_type = __Pyx_PyErr_Occurred();
2023-05-14T17:24:50.8086878Z       |                              ^~~~~~~~~~~~~~~~~~~~
2023-05-14T17:24:50.8119802Z src/pyfuse3.c: In function ‘__pyx_gb_7pyfuse3_65generator21’:
2023-05-14T17:24:50.8131110Z src/pyfuse3.c:2305:45: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:50.8131594Z  2305 | #define __Pyx_PyErr_Occurred()  __pyx_tstate->curexc_type
2023-05-14T17:24:50.8132152Z       |                                             ^~
2023-05-14T17:24:50.8132559Z src/pyfuse3.c:21359:30: note: in expansion of macro ‘__Pyx_PyErr_Occurred’
2023-05-14T17:24:50.8132890Z 21359 |         PyObject* exc_type = __Pyx_PyErr_Occurred();
2023-05-14T17:24:50.8133175Z       |                              ^~~~~~~~~~~~~~~~~~~~
2023-05-14T17:24:50.8226227Z src/pyfuse3.c: In function ‘__pyx_gb_7pyfuse3_71generator23’:
2023-05-14T17:24:50.8237868Z src/pyfuse3.c:2305:45: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:50.8238340Z  2305 | #define __Pyx_PyErr_Occurred()  __pyx_tstate->curexc_type
2023-05-14T17:24:50.8238956Z       |                                             ^~
2023-05-14T17:24:50.8239378Z src/pyfuse3.c:22782:36: note: in expansion of macro ‘__Pyx_PyErr_Occurred’
2023-05-14T17:24:50.8239708Z 22782 |               PyObject* exc_type = __Pyx_PyErr_Occurred();
2023-05-14T17:24:50.8240029Z       |                                    ^~~~~~~~~~~~~~~~~~~~
2023-05-14T17:24:50.8261968Z src/pyfuse3.c:2305:45: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:50.8262469Z  2305 | #define __Pyx_PyErr_Occurred()  __pyx_tstate->curexc_type
2023-05-14T17:24:50.8262750Z       |                                             ^~
2023-05-14T17:24:50.8263160Z src/pyfuse3.c:23038:32: note: in expansion of macro ‘__Pyx_PyErr_Occurred’
2023-05-14T17:24:50.8263499Z 23038 |           PyObject* exc_type = __Pyx_PyErr_Occurred();
2023-05-14T17:24:50.8263764Z       |                                ^~~~~~~~~~~~~~~~~~~~
2023-05-14T17:24:50.8276536Z src/pyfuse3.c:2305:45: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:50.8277014Z  2305 | #define __Pyx_PyErr_Occurred()  __pyx_tstate->curexc_type
2023-05-14T17:24:50.8277307Z       |                                             ^~
2023-05-14T17:24:50.8277691Z src/pyfuse3.c:23115:30: note: in expansion of macro ‘__Pyx_PyErr_Occurred’
2023-05-14T17:24:50.8278049Z 23115 |         PyObject* exc_type = __Pyx_PyErr_Occurred();
2023-05-14T17:24:50.8278326Z       |                              ^~~~~~~~~~~~~~~~~~~~
2023-05-14T17:24:50.8394042Z src/pyfuse3.c: In function ‘__pyx_gb_7pyfuse3_80generator26’:
2023-05-14T17:24:50.8407756Z src/pyfuse3.c:2305:45: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:50.8408314Z  2305 | #define __Pyx_PyErr_Occurred()  __pyx_tstate->curexc_type
2023-05-14T17:24:50.8408653Z       |                                             ^~
2023-05-14T17:24:50.8409100Z src/pyfuse3.c:25117:30: note: in expansion of macro ‘__Pyx_PyErr_Occurred’
2023-05-14T17:24:50.8409517Z 25117 |         PyObject* exc_type = __Pyx_PyErr_Occurred();
2023-05-14T17:24:50.8409837Z       |                              ^~~~~~~~~~~~~~~~~~~~
2023-05-14T17:24:50.8709331Z src/pyfuse3.c: In function ‘__pyx_gb_7pyfuse3_91generator29’:
2023-05-14T17:24:50.8725049Z src/pyfuse3.c:2305:45: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:50.8725648Z  2305 | #define __Pyx_PyErr_Occurred()  __pyx_tstate->curexc_type
2023-05-14T17:24:50.8725989Z       |                                             ^~
2023-05-14T17:24:50.8726440Z src/pyfuse3.c:29853:40: note: in expansion of macro ‘__Pyx_PyErr_Occurred’
2023-05-14T17:24:50.8726837Z 29853 |                   PyObject* exc_type = __Pyx_PyErr_Occurred();
2023-05-14T17:24:50.8727171Z       |                                        ^~~~~~~~~~~~~~~~~~~~
2023-05-14T17:24:50.8807958Z src/pyfuse3.c: In function ‘__pyx_gb_7pyfuse3_94generator30’:
2023-05-14T17:24:50.8824610Z src/pyfuse3.c:2305:45: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:50.8825102Z  2305 | #define __Pyx_PyErr_Occurred()  __pyx_tstate->curexc_type
2023-05-14T17:24:50.8825396Z       |                                             ^~
2023-05-14T17:24:50.8825781Z src/pyfuse3.c:31145:30: note: in expansion of macro ‘__Pyx_PyErr_Occurred’
2023-05-14T17:24:50.8826499Z 31145 |         PyObject* exc_type = __Pyx_PyErr_Occurred();
2023-05-14T17:24:50.8826781Z       |                              ^~~~~~~~~~~~~~~~~~~~
2023-05-14T17:24:51.1213683Z src/pyfuse3.c: In function ‘__Pyx_PyErr_ExceptionMatchesInState’:
2023-05-14T17:24:51.1227489Z src/pyfuse3.c:56842:32: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:51.1228024Z 56842 |     PyObject *exc_type = tstate->curexc_type;
2023-05-14T17:24:51.1228331Z       |                                ^~
2023-05-14T17:24:51.1305463Z src/pyfuse3.c: In function ‘__Pyx_ErrRestoreInState’:
2023-05-14T17:24:51.1320230Z src/pyfuse3.c:56855:22: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:51.1320682Z 56855 |     tmp_type = tstate->curexc_type;
2023-05-14T17:24:51.1321060Z       |                      ^~
2023-05-14T17:24:51.1333373Z src/pyfuse3.c:56856:23: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_value’
2023-05-14T17:24:51.1333836Z 56856 |     tmp_value = tstate->curexc_value;
2023-05-14T17:24:51.1334083Z       |                       ^~
2023-05-14T17:24:51.1347043Z src/pyfuse3.c:56857:20: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_traceback’
2023-05-14T17:24:51.1347462Z 56857 |     tmp_tb = tstate->curexc_traceback;
2023-05-14T17:24:51.1347714Z       |                    ^~
2023-05-14T17:24:51.1360644Z src/pyfuse3.c:56858:11: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:51.1361142Z 56858 |     tstate->curexc_type = type;
2023-05-14T17:24:51.1361375Z       |           ^~
2023-05-14T17:24:51.1374099Z src/pyfuse3.c:56859:11: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_value’
2023-05-14T17:24:51.1374508Z 56859 |     tstate->curexc_value = value;
2023-05-14T17:24:51.1374730Z       |           ^~
2023-05-14T17:24:51.1387648Z src/pyfuse3.c:56860:11: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_traceback’
2023-05-14T17:24:51.1388083Z 56860 |     tstate->curexc_traceback = tb;
2023-05-14T17:24:51.1388307Z       |           ^~
2023-05-14T17:24:51.1388644Z src/pyfuse3.c: In function ‘__Pyx_ErrFetchInState’:
2023-05-14T17:24:51.1402080Z src/pyfuse3.c:56866:19: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:51.1402474Z 56866 |     *type = tstate->curexc_type;
2023-05-14T17:24:51.1402904Z       |                   ^~
2023-05-14T17:24:51.1415682Z src/pyfuse3.c:56867:20: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_value’
2023-05-14T17:24:51.1416094Z 56867 |     *value = tstate->curexc_value;
2023-05-14T17:24:51.1416364Z       |                    ^~
2023-05-14T17:24:51.1429485Z src/pyfuse3.c:56868:17: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_traceback’
2023-05-14T17:24:51.1429898Z 56868 |     *tb = tstate->curexc_traceback;
2023-05-14T17:24:51.1430140Z       |                 ^~
2023-05-14T17:24:51.1444162Z src/pyfuse3.c:56869:11: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:51.1444547Z 56869 |     tstate->curexc_type = 0;
2023-05-14T17:24:51.1444775Z       |           ^~
2023-05-14T17:24:51.1457688Z src/pyfuse3.c:56870:11: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_value’
2023-05-14T17:24:51.1458082Z 56870 |     tstate->curexc_value = 0;
2023-05-14T17:24:51.1458297Z       |           ^~
2023-05-14T17:24:51.1471217Z src/pyfuse3.c:56871:11: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_traceback’
2023-05-14T17:24:51.1471629Z 56871 |     tstate->curexc_traceback = 0;
2023-05-14T17:24:51.1471867Z       |           ^~
2023-05-14T17:24:51.2043400Z src/pyfuse3.c: In function ‘__Pyx_Raise’:
2023-05-14T17:24:51.2055311Z src/pyfuse3.c:57354:34: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_traceback’
2023-05-14T17:24:51.2055864Z 57354 |         PyObject* tmp_tb = tstate->curexc_traceback;
2023-05-14T17:24:51.2056592Z       |                                  ^~
2023-05-14T17:24:51.2068851Z src/pyfuse3.c:57357:19: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_traceback’
2023-05-14T17:24:51.2069343Z 57357 |             tstate->curexc_traceback = tb;
2023-05-14T17:24:51.2069625Z       |                   ^~
2023-05-14T17:24:51.2564872Z In file included from /opt/hostedtoolcache/Python/3.12.0-alpha.7/x64/include/python3.12/internal/pycore_frame.h:9,
2023-05-14T17:24:51.2565347Z                  from src/pyfuse3.c:58290:
2023-05-14T17:24:51.2566346Z /opt/hostedtoolcache/Python/3.12.0-alpha.7/x64/include/python3.12/internal/pycore_code.h: In function ‘write_varint’:
2023-05-14T17:24:51.2567283Z /opt/hostedtoolcache/Python/3.12.0-alpha.7/x64/include/python3.12/internal/pycore_code.h:350:18: warning: conversion from ‘unsigned int’ to ‘uint8_t’ {aka ‘unsigned char’} may change value [-Wconversion]
2023-05-14T17:24:51.2567785Z   350 |         *ptr++ = 64 | (val & 63);
2023-05-14T17:24:51.2568069Z       |                  ^~
2023-05-14T17:24:51.2568805Z /opt/hostedtoolcache/Python/3.12.0-alpha.7/x64/include/python3.12/internal/pycore_code.h:354:12: warning: conversion from ‘unsigned int’ to ‘uint8_t’ {aka ‘unsigned char’} may change value [-Wconversion]
2023-05-14T17:24:51.2569286Z   354 |     *ptr = val;
2023-05-14T17:24:51.2569510Z       |            ^~~
2023-05-14T17:24:51.2570081Z /opt/hostedtoolcache/Python/3.12.0-alpha.7/x64/include/python3.12/internal/pycore_code.h: In function ‘write_signed_varint’:
2023-05-14T17:24:51.2570990Z /opt/hostedtoolcache/Python/3.12.0-alpha.7/x64/include/python3.12/internal/pycore_code.h:367:30: warning: conversion to ‘unsigned int’ from ‘int’ may change the sign of the result [-Wsign-conversion]
2023-05-14T17:24:51.2571521Z   367 |     return write_varint(ptr, val);
2023-05-14T17:24:51.2571791Z       |                              ^~~
2023-05-14T17:24:51.2572968Z /opt/hostedtoolcache/Python/3.12.0-alpha.7/x64/include/python3.12/internal/pycore_code.h: In function ‘write_location_entry_start’:
2023-05-14T17:24:51.2573874Z /opt/hostedtoolcache/Python/3.12.0-alpha.7/x64/include/python3.12/internal/pycore_code.h:374:12: warning: conversion from ‘int’ to ‘uint8_t’ {aka ‘unsigned char’} may change value [-Wconversion]
2023-05-14T17:24:51.2574470Z   374 |     *ptr = 128 | (code << 3) | (length - 1);
2023-05-14T17:24:51.2574725Z       |            ^~~
2023-05-14T17:24:51.2575298Z /opt/hostedtoolcache/Python/3.12.0-alpha.7/x64/include/python3.12/internal/pycore_code.h: In function ‘adaptive_counter_bits’:
2023-05-14T17:24:51.2576197Z /opt/hostedtoolcache/Python/3.12.0-alpha.7/x64/include/python3.12/internal/pycore_code.h:415:45: warning: conversion from ‘int’ to ‘uint16_t’ {aka ‘short unsigned int’} may change value [-Wconversion]
2023-05-14T17:24:51.2576729Z   415 |     return (value << ADAPTIVE_BACKOFF_BITS) |
2023-05-14T17:24:51.2577024Z       |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
2023-05-14T17:24:51.2577434Z   416 |         (backoff & ((1<<ADAPTIVE_BACKOFF_BITS)-1));
2023-05-14T17:24:51.2577763Z       |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2023-05-14T17:24:51.2578341Z /opt/hostedtoolcache/Python/3.12.0-alpha.7/x64/include/python3.12/internal/pycore_code.h: In function ‘adaptive_counter_backoff’:
2023-05-14T17:24:51.2579242Z /opt/hostedtoolcache/Python/3.12.0-alpha.7/x64/include/python3.12/internal/pycore_code.h:438:26: warning: conversion to ‘unsigned int’ from ‘int’ may change the sign of the result [-Wsign-conversion]
2023-05-14T17:24:51.2579847Z   438 |     unsigned int value = (1 << backoff) - 1;
2023-05-14T17:24:51.2580137Z       |                          ^
2023-05-14T17:24:51.2580865Z /opt/hostedtoolcache/Python/3.12.0-alpha.7/x64/include/python3.12/internal/pycore_code.h:439:34: warning: conversion to ‘int’ from ‘unsigned int’ may change the sign of the result [-Wsign-conversion]
2023-05-14T17:24:51.2581413Z   439 |     return adaptive_counter_bits(value, backoff);
2023-05-14T17:24:51.2581722Z       |                                  ^~~~~
2023-05-14T17:24:51.2582679Z /opt/hostedtoolcache/Python/3.12.0-alpha.7/x64/include/python3.12/internal/pycore_code.h:439:41: warning: conversion to ‘int’ from ‘unsigned int’ may change the sign of the result [-Wsign-conversion]
2023-05-14T17:24:51.2583206Z   439 |     return adaptive_counter_bits(value, backoff);
2023-05-14T17:24:51.2583518Z       |                                         ^~~~~~~
2023-05-14T17:24:51.2775835Z src/pyfuse3.c: In function ‘__Pyx_Coroutine_MethodReturn’:
2023-05-14T17:24:51.2803559Z src/pyfuse3.c:2305:45: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:51.2804472Z  2305 | #define __Pyx_PyErr_Occurred()  __pyx_tstate->curexc_type
2023-05-14T17:24:51.2804834Z       |                                             ^~
2023-05-14T17:24:51.2805307Z src/pyfuse3.c:58540:14: note: in expansion of macro ‘__Pyx_PyErr_Occurred’
2023-05-14T17:24:51.2805661Z 58540 |         if (!__Pyx_PyErr_Occurred()) {
2023-05-14T17:24:51.2805947Z       |              ^~~~~~~~~~~~~~~~~~~~
2023-05-14T17:24:51.3476239Z src/pyfuse3.c: In function ‘__Pyx__Coroutine_GetAwaitableIter’:
2023-05-14T17:24:51.3489215Z src/pyfuse3.c:59659:53: error: ‘PyGenObject’ {aka ‘struct <anonymous>’} has no member named ‘gi_code’
2023-05-14T17:24:51.3490035Z 59659 |     if (PyGen_CheckExact(obj) && ((PyGenObject*)obj)->gi_code && ((PyCodeObject *)((PyGenObject*)obj)->gi_code)->co_flags & CO_ITERABLE_COROUTINE) {
2023-05-14T17:24:51.3490509Z       |                                                     ^~
2023-05-14T17:24:51.3517683Z src/pyfuse3.c:59659:102: error: ‘PyGenObject’ {aka ‘struct <anonymous>’} has no member named ‘gi_code’
2023-05-14T17:24:51.3518519Z 59659 |     if (PyGen_CheckExact(obj) && ((PyGenObject*)obj)->gi_code && ((PyCodeObject *)((PyGenObject*)obj)->gi_code)->co_flags & CO_ITERABLE_COROUTINE) {
2023-05-14T17:24:51.3519002Z       |                                                                                                      ^~
2023-05-14T17:24:51.3606220Z src/pyfuse3.c: In function ‘__Pyx__GetException’:
2023-05-14T17:24:51.3619379Z src/pyfuse3.c:59785:24: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:51.3619815Z 59785 |     local_type = tstate->curexc_type;
2023-05-14T17:24:51.3620051Z       |                        ^~
2023-05-14T17:24:51.3634771Z src/pyfuse3.c:59786:25: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_value’
2023-05-14T17:24:51.3635233Z 59786 |     local_value = tstate->curexc_value;
2023-05-14T17:24:51.3635474Z       |                         ^~
2023-05-14T17:24:51.3647645Z src/pyfuse3.c:59787:22: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_traceback’
2023-05-14T17:24:51.3648083Z 59787 |     local_tb = tstate->curexc_traceback;
2023-05-14T17:24:51.3648335Z       |                      ^~
2023-05-14T17:24:51.3663195Z src/pyfuse3.c:59788:11: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:51.3663629Z 59788 |     tstate->curexc_type = 0;
2023-05-14T17:24:51.3663900Z       |           ^~
2023-05-14T17:24:51.3675408Z src/pyfuse3.c:59789:11: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_value’
2023-05-14T17:24:51.3675824Z 59789 |     tstate->curexc_value = 0;
2023-05-14T17:24:51.3676056Z       |           ^~
2023-05-14T17:24:51.3690896Z src/pyfuse3.c:59790:11: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_traceback’
2023-05-14T17:24:51.3691337Z 59790 |     tstate->curexc_traceback = 0;
2023-05-14T17:24:51.3691582Z       |           ^~
2023-05-14T17:24:51.3704081Z src/pyfuse3.c:59796:24: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:51.3704500Z 59796 |     if (unlikely(tstate->curexc_type))
2023-05-14T17:24:51.3704752Z       |                        ^~
2023-05-14T17:24:51.3705173Z src/pyfuse3.c:1283:43: note: in definition of macro ‘unlikely’
2023-05-14T17:24:51.3705479Z  1283 |   #define unlikely(x) __builtin_expect(!!(x), 0)
2023-05-14T17:24:51.3706068Z       |                                           ^
2023-05-14T17:24:51.3867288Z src/pyfuse3.c: In function ‘__Pyx_IterFinish’:
2023-05-14T17:24:51.3880125Z src/pyfuse3.c:60007:32: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:51.3880574Z 60007 |     PyObject* exc_type = tstate->curexc_type;
2023-05-14T17:24:51.3880947Z       |                                ^~
2023-05-14T17:24:51.3895905Z src/pyfuse3.c:60011:31: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_value’
2023-05-14T17:24:51.3896374Z 60011 |             exc_value = tstate->curexc_value;
2023-05-14T17:24:51.3896883Z       |                               ^~
2023-05-14T17:24:51.3908929Z src/pyfuse3.c:60012:28: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_traceback’
2023-05-14T17:24:51.3909391Z 60012 |             exc_tb = tstate->curexc_traceback;
2023-05-14T17:24:51.3909641Z       |                            ^~
2023-05-14T17:24:51.3922934Z src/pyfuse3.c:60013:19: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_type’
2023-05-14T17:24:51.3923370Z 60013 |             tstate->curexc_type = 0;
2023-05-14T17:24:51.3923617Z       |                   ^~
2023-05-14T17:24:51.3938553Z src/pyfuse3.c:60014:19: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_value’
2023-05-14T17:24:51.3939020Z 60014 |             tstate->curexc_value = 0;
2023-05-14T17:24:51.3939275Z       |                   ^~
2023-05-14T17:24:51.3951038Z src/pyfuse3.c:60015:19: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘curexc_traceback’
2023-05-14T17:24:51.3951518Z 60015 |             tstate->curexc_traceback = 0;
2023-05-14T17:24:51.3951775Z       |                   ^~
2023-05-14T17:24:51.9006778Z error: command '/usr/bin/gcc' failed with exit code 1
2023-05-14T17:24:51.9834408Z ##[error]Process completed with exit code 1.

Spawning threads in handlers?

I want to have a thread tracking the access of a file: it's spawned when the file is opened, and canceled when the file is closed. I read the trio document and it seems I need to use nursery. It seems that I will need the pyfuse3 framework to pass a nursery object to my handler functions which can then use the nursery to spawn threads? Am I understanding it right?

Alternatively of course I can just use asyncio. But I'm having some issues with it (namely some exceptions are missing) so I'm trying to use trio instead.

macOS compatibility

While macOS lacks support for FUSE 3, there are mentions in the source about OS X compatibility, for example this commit 3686b57 and in setup.py.

Just curious as to whether the author was able to get this project work on OS X, and if so, what steps they took.

Initializing multiple file systems only runs the last one

Hi,

I'm trying to run multiple FUSE mounts from the same process - only the last call to pyfuse3.init() takes effect. Here's an example adapted from hello_asyncio.py:

Code from hello_asyncio.py
'''
hello_asyncio.py - Example file system for pyfuse3 using asyncio.
This program presents a static file system containing a single file.
Copyright © 2015 Nikolaus Rath <Nikolaus.org>
Copyright © 2015 Gerion Entrup.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
'''

import os
import sys

# If we are running from the pyfuse3 source directory, try
# to load the module from there first.
basedir = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '..'))
if (os.path.exists(os.path.join(basedir, 'setup.py')) and
    os.path.exists(os.path.join(basedir, 'src', 'pyfuse3.pyx'))):
    sys.path.insert(0, os.path.join(basedir, 'src'))

from argparse import ArgumentParser
import asyncio
import stat
import logging
import errno
import pyfuse3
import pyfuse3_asyncio

try:
    import faulthandler
except ImportError:
    pass
else:
    faulthandler.enable()

log = logging.getLogger(__name__)
pyfuse3_asyncio.enable()

class TestFs(pyfuse3.Operations):
    def __init__(self):
        super(TestFs, self).__init__()
        self.hello_name = b"message"
        self.hello_inode = pyfuse3.ROOT_INODE+1
        self.hello_data = b"hello world\n"

    async def getattr(self, inode, ctx=None):
        entry = pyfuse3.EntryAttributes()
        if inode == pyfuse3.ROOT_INODE:
            entry.st_mode = (stat.S_IFDIR | 0o755)
            entry.st_size = 0
        elif inode == self.hello_inode:
            entry.st_mode = (stat.S_IFREG | 0o644)
            entry.st_size = len(self.hello_data)
        else:
            raise pyfuse3.FUSEError(errno.ENOENT)

        stamp = int(1438467123.985654 * 1e9)
        entry.st_atime_ns = stamp
        entry.st_ctime_ns = stamp
        entry.st_mtime_ns = stamp
        entry.st_gid = os.getgid()
        entry.st_uid = os.getuid()
        entry.st_ino = inode

        return entry

    async def lookup(self, parent_inode, name, ctx=None):
        if parent_inode != pyfuse3.ROOT_INODE or name != self.hello_name:
            raise pyfuse3.FUSEError(errno.ENOENT)
        return await self.getattr(self.hello_inode)

    async def opendir(self, inode, ctx):
        if inode != pyfuse3.ROOT_INODE:
            raise pyfuse3.FUSEError(errno.ENOENT)
        return inode

    async def readdir(self, fh, start_id, token):
        assert fh == pyfuse3.ROOT_INODE

        # only one entry
        if start_id == 0:
            pyfuse3.readdir_reply(
                token, self.hello_name, await self.getattr(self.hello_inode), 1)
        return

    async def setxattr(self, inode, name, value, ctx):
        if inode != pyfuse3.ROOT_INODE or name != b'command':
            raise pyfuse3.FUSEError(errno.ENOTSUP)

        if value == b'terminate':
            pyfuse3.terminate()
        else:
            raise pyfuse3.FUSEError(errno.EINVAL)

    async def open(self, inode, flags, ctx):
        if inode != self.hello_inode:
            raise pyfuse3.FUSEError(errno.ENOENT)
        if flags & os.O_RDWR or flags & os.O_WRONLY:
            raise pyfuse3.FUSEError(errno.EACCES)
        return pyfuse3.FileInfo(fh=inode)

    async def read(self, fh, off, size):
        assert fh == self.hello_inode
        return self.hello_data[off:off+size]

def init_logging(debug=False):
    formatter = logging.Formatter('%(asctime)s.%(msecs)03d %(threadName)s: '
                                  '[%(name)s] %(message)s', datefmt="%Y-%m-%d %H:%M:%S")
    handler = logging.StreamHandler()
    handler.setFormatter(formatter)
    root_logger = logging.getLogger()
    if debug:
        handler.setLevel(logging.DEBUG)
        root_logger.setLevel(logging.DEBUG)
    else:
        handler.setLevel(logging.INFO)
        root_logger.setLevel(logging.INFO)
    root_logger.addHandler(handler)

def parse_args():
    '''Parse command line'''

    parser = ArgumentParser()

    parser.add_argument('mountpoint', type=str,
                        help='Where to mount the file system')
    parser.add_argument('--debug', action='store_true', default=False,
                        help='Enable debugging output')
    parser.add_argument('--debug-fuse', action='store_true', default=False,
                        help='Enable FUSE debugging output')
    return parser.parse_args()


def main():
    init_logging(True)

    testfs = TestFs()
    testfs2 = TestFs()
    fuse_options = set(pyfuse3.default_options)
    fuse_options.add('fsname=hello_asyncio')
    fuse_options.add('debug')
    pyfuse3.init(testfs, './mnt', fuse_options)
    print('INIT ONE COMPLETE')
    pyfuse3.init(testfs, './mnt2', fuse_options)
    print('INIT TWO COMPLETE')
    loop = asyncio.get_event_loop()
    try:
        print('RUNNING EVENT LOOP')
        loop.run_until_complete(pyfuse3.main())
        # Try `ls ./mnt` and `ls ./mnt2` here
    except:
        pyfuse3.close(unmount=False)
        raise
    finally:
        loop.close()

    pyfuse3.close()

if __name__ == '__main__':
    main()

It seems to me that the globals in pyfuse3.pyx are responsible for this behaviour. A quick-and-dirty fix would be to add to each function using the globals an optional context argument taking a dict of no-longer-global values. The entire init-run-close functionality could also be made part of the Operations class, but I'm not sure whether that is possible in a reasonably backwards compatible way.

I'm not super familiar with FUSE, and definitely unfamiliar with trio - would it nevertheless make sense for me to throw together a pull request, considering the lack of maintainers here?

Make invalidate_entry() easier to use

Currently, this needs to be called outside of any file system operation. The only way to do that is in a separate thread. We should add build-in support for that. We could use a queue, but in that case a single blocking request would block the entire queue. Separate threads would solve that, but might be expensive in general.

We should also make sure that a blocked write from notify does not block processing of other writes.

pyfuse3 module is empty (likely cython issue)

Working on master branch. Python 3.9.1, Cython 0.29.21.
I followed the document on how to build:

root@darkbox /s/d/pyfuse3 (master) [SIGINT]# cat build.sh 
python3 setup.py build_cython
python3 setup.py build_ext --inplace
python3 -m pytest test/
python3 setup.py build_sphinx
python3 setup.py install

and ran the building script:

root@darkbox /s/d/pyfuse3 (master)# sh ./build.sh
found MANIFEST.in, running in developer mode
running build_cython
Compiling /srv/deluge/pyfuse3/src/pyfuse3.pyx
found MANIFEST.in, running in developer mode
running build_ext
building 'pyfuse3' extension
gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -march=x86-64 -mtune=generic -O3 -pipe -fno-plt -fno-semantic-interposition -march=x86-64 -mtune=generic -O3 -pipe -fno-plt -march=x86-64 -mtune=generic -O3 -pipe -fno-plt -fPIC -I/usr/include/python3.9 -c src/pyfuse3.c -o build/temp.linux-x86_64-3.9/src/pyfuse3.o -I/usr/include/fuse3 -DFUSE_USE_VERSION=32 -Wall -Wextra -Wconversion -Wsign-compare -DPYFUSE3_VERSION="3.2.0" -Wno-unused-function -Wno-implicit-fallthrough -Wno-unused-function -Wno-unused-parameter -Werror -Wfatal-errors -Wno-error=unreachable-code -Werror=conversion -Werror=sign-compare
gcc -pthread -shared -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -fno-semantic-interposition -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now build/temp.linux-x86_64-3.9/src/pyfuse3.o -L/usr/lib -o build/lib.linux-x86_64-3.9/pyfuse3.cpython-39-x86_64-linux-gnu.so -lfuse3 -lpthread -lpthread -lrt
/usr/lib/python3.9/site-packages/setuptools/lib2to3_ex.py:10: PendingDeprecationWarning: lib2to3 package is deprecated and may not be able to parse Python 3.10+
  from lib2to3.refactor import RefactoringTool, get_fixers_from_package
copying build/lib.linux-x86_64-3.9/pyfuse3.cpython-39-x86_64-linux-gnu.so -> src
========================================================================== test session starts ===========================================================================
platform linux -- Python 3.9.1, pytest-6.2.1, py-1.10.0, pluggy-0.13.1 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /srv/deluge/pyfuse3/test, configfile: pytest.ini
collected 17 items                                                                                                                                                       

test/test_api.py::test_listdir PASSED                                                                                                                              [  5%]
test/test_api.py::test_sup_groups PASSED                                                                                                                           [ 11%]
test/test_api.py::test_syncfs PASSED                                                                                                                               [ 17%]
test/test_api.py::test_entry_res PASSED                                                                                                                            [ 23%]
test/test_api.py::test_xattr SKIPPED (ACLs not supported for /tmp/tmpve38m2ob)                                                                                     [ 29%]
test/test_api.py::test_copy PASSED                                                                                                                                 [ 35%]
test/test_examples.py::test_hello[hello.py] PASSED                                                                                                                 [ 41%]
test/test_examples.py::test_hello[hello_asyncio.py] PASSED                                                                                                         [ 47%]
test/test_examples.py::test_tmpfs PASSED                                                                                                                           [ 52%]
test/test_examples.py::test_passthroughfs PASSED                                                                                                                   [ 58%]
test/test_fs.py::test_invalidate_entry PASSED                                                                                                                      [ 64%]
test/test_fs.py::test_invalidate_inode PASSED                                                                                                                      [ 70%]
test/test_fs.py::test_notify_store PASSED                                                                                                                          [ 76%]
test/test_fs.py::test_entry_timeout PASSED                                                                                                                         [ 82%]
test/test_fs.py::test_attr_timeout PASSED                                                                                                                          [ 88%]
test/test_fs.py::test_terminate PASSED                                                                                                                             [ 94%]
test/test_rounding.py::test_rounding PASSED                                                                                                                        [100%]

============================================================================ warnings summary ============================================================================
test/test_fs.py:47
  /srv/deluge/pyfuse3/test/test_fs.py:47: PytestDeprecationWarning: @pytest.yield_fixture is deprecated.
  Use @pytest.fixture instead; they are the same.
    @pytest.yield_fixture()

-- Docs: https://docs.pytest.org/en/stable/warnings.html
================================================================ 16 passed, 1 skipped, 1 warning in 5.95s ================================================================
found MANIFEST.in, running in developer mode
running build_sphinx
Running Sphinx v3.4.3

Extension error:
Could not import extension sphinxcontrib.asyncio (exception: No module named 'sphinxcontrib.asyncio')
found MANIFEST.in, running in developer mode
running install
/usr/lib/python3.9/site-packages/packaging/version.py:127: DeprecationWarning: Creating a LegacyVersion has been deprecated and will be removed in the next major release
  warnings.warn(
running bdist_egg
running egg_info
writing src/pyfuse3.egg-info/PKG-INFO
writing dependency_links to src/pyfuse3.egg-info/dependency_links.txt
writing requirements to src/pyfuse3.egg-info/requires.txt
writing top-level names to src/pyfuse3.egg-info/top_level.txt
/usr/lib/python3.9/site-packages/setuptools/lib2to3_ex.py:10: PendingDeprecationWarning: lib2to3 package is deprecated and may not be able to parse Python 3.10+
  from lib2to3.refactor import RefactoringTool, get_fixers_from_package
reading manifest file 'src/pyfuse3.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
warning: no directories found matching 'doc/html'
no previously-included directories found matching 'test/.cache'
writing manifest file 'src/pyfuse3.egg-info/SOURCES.txt'
installing library code to build/bdist.linux-x86_64/egg
running install_lib
running build_py
running build_ext
creating build/bdist.linux-x86_64/egg
copying build/lib.linux-x86_64-3.9/_pyfuse3.py -> build/bdist.linux-x86_64/egg
copying build/lib.linux-x86_64-3.9/pyfuse3_twisted.py -> build/bdist.linux-x86_64/egg
copying build/lib.linux-x86_64-3.9/pyfuse3_asyncio.py -> build/bdist.linux-x86_64/egg
copying build/lib.linux-x86_64-3.9/pyfuse3.cpython-39-x86_64-linux-gnu.so -> build/bdist.linux-x86_64/egg
byte-compiling build/bdist.linux-x86_64/egg/_pyfuse3.py to _pyfuse3.cpython-39.pyc
byte-compiling build/bdist.linux-x86_64/egg/pyfuse3_twisted.py to pyfuse3_twisted.cpython-39.pyc
byte-compiling build/bdist.linux-x86_64/egg/pyfuse3_asyncio.py to pyfuse3_asyncio.cpython-39.pyc
creating stub loader for pyfuse3.cpython-39-x86_64-linux-gnu.so
byte-compiling build/bdist.linux-x86_64/egg/pyfuse3.py to pyfuse3.cpython-39.pyc
creating build/bdist.linux-x86_64/egg/EGG-INFO
copying src/pyfuse3.egg-info/PKG-INFO -> build/bdist.linux-x86_64/egg/EGG-INFO
copying src/pyfuse3.egg-info/SOURCES.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
copying src/pyfuse3.egg-info/dependency_links.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
copying src/pyfuse3.egg-info/requires.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
copying src/pyfuse3.egg-info/top_level.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
copying src/pyfuse3.egg-info/zip-safe -> build/bdist.linux-x86_64/egg/EGG-INFO
writing build/bdist.linux-x86_64/egg/EGG-INFO/native_libs.txt
creating 'dist/pyfuse3-3.2.0-py3.9-linux-x86_64.egg' and adding 'build/bdist.linux-x86_64/egg' to it
removing 'build/bdist.linux-x86_64/egg' (and everything under it)
Processing pyfuse3-3.2.0-py3.9-linux-x86_64.egg
Removing /usr/lib/python3.9/site-packages/pyfuse3-3.2.0-py3.9-linux-x86_64.egg
Copying pyfuse3-3.2.0-py3.9-linux-x86_64.egg to /usr/lib/python3.9/site-packages
pyfuse3 3.2.0 is already the active version in easy-install.pth

Installed /usr/lib/python3.9/site-packages/pyfuse3-3.2.0-py3.9-linux-x86_64.egg
Processing dependencies for pyfuse3==3.2.0
Searching for trio==0.17.0
Best match: trio 0.17.0
Adding trio 0.17.0 to easy-install.pth file

Using /usr/lib/python3.9/site-packages
Searching for async-generator==1.10
Best match: async-generator 1.10
Adding async-generator 1.10 to easy-install.pth file

Using /usr/lib/python3.9/site-packages
Searching for attrs==20.3.0
Best match: attrs 20.3.0
Adding attrs 20.3.0 to easy-install.pth file

Using /usr/lib/python3.9/site-packages
Searching for sortedcontainers==2.3.0
Best match: sortedcontainers 2.3.0
Adding sortedcontainers 2.3.0 to easy-install.pth file

Using /usr/lib/python3.9/site-packages
Searching for idna==2.10
Best match: idna 2.10
Adding idna 2.10 to easy-install.pth file

Using /usr/lib/python3.9/site-packages
Searching for outcome==1.1.0
Best match: outcome 1.1.0
Adding outcome 1.1.0 to easy-install.pth file

Using /usr/lib/python3.9/site-packages
Searching for sniffio==1.2.0
Best match: sniffio 1.2.0
Adding sniffio 1.2.0 to easy-install.pth file

Using /usr/lib/python3.9/site-packages
Finished processing dependencies for pyfuse3==3.2.0

everything look ok. But when I try to use the module:

root@darkbox /s/d/pyfuse3 (master)# python
Python 3.9.1 (default, Dec 13 2020, 11:55:53) 
[GCC 10.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyfuse3
>>> dir(pyfuse3)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']

undefined symbol: _PyGen_Send

docker python:3.10

docker run --mount type=bind,source=$PWD,target=/app,bind-propagation=rshared -w /app --cap-add SYS
_ADMIN --device /dev/fuse -it python:3.10 bash
$ apt update && apt install libfuse3-dev && pip install pyfuse3
$ python
Python 3.10.2
>>> import pyfuse3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: /usr/local/lib/python3.10/site-packages/pyfuse3.cpython-310-x86_64-linux-gnu.so: undefined symbol: _PyGen_Send

docker python:3.9

docker run --mount type=bind,source=$PWD,target=/app,bind-propagation=rshared -w /app --cap-add SYS
_ADMIN --device /dev/fuse -it python:3.9 bash
$ apt update && apt install libfuse3-dev && pip install pyfuse3
$ python
Python 3.9.10
>>> import pyfuse3
>>>

Attribute Caching Question

Hi:

I have been using the passthroughfs.py example, and I am seeing something weird happen with attributes. Specifically, if I create a file in the underlying file system, I get the correct attributes the first time I stat the file or list the directory contents in the FUSE mount. Some of the attributes are not updating when files are modified in the underlying file system, then I look at them in the FUSE mount. entry_timeout and attr_timeout are set to 0 in the returned entry in _getattr, so I don't think any caching should happen.

I've added a debug statement to print st_size from the EntryAttributes variable that is created in _getattr, and it is correctly set in the entry (and st_blocks is set based on it, which does change). However, the size is not correct when I stat the file in the FUSE mount. I have also noticed timestamps not updating, but hard links and mode updates come through.

This is what I see when running the following commands (a is source directory, b is FUSE mount):

> echo a > a/a
> stat b/a
  File: b/a
  Size: 2         	Blocks: 1          IO Block: 512    regular file
Device: 36h/54d	Inode: 1814195     Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/  ubuntu)   Gid: ( 1000/  ubuntu)
Access: 2020-03-26 22:26:32.322392232 +0000
Modify: 2020-03-26 22:24:29.742113292 +0000
Change: 2020-03-26 22:24:29.742113292 +0000
 Birth: -
> yes a | head -c 10000 >> a/a
> stat b/a
  File: b/a
  Size: 2         	Blocks: 20         IO Block: 512    regular file
Device: 36h/54d	Inode: 1814195     Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/  ubuntu)   Gid: ( 1000/  ubuntu)
Access: 2020-03-26 22:26:32.322392232 +0000
Modify: 2020-03-26 22:24:29.742113292 +0000
Change: 2020-03-26 22:24:29.742113292 +0000
 Birth: -
> ln a/a a/a2
> stat b/a
  File: b/a
  Size: 2         	Blocks: 20         IO Block: 512    regular file
Device: 36h/54d	Inode: 1814195     Links: 2
Access: (0644/-rw-r--r--)  Uid: ( 1000/  ubuntu)   Gid: ( 1000/  ubuntu)
Access: 2020-03-26 22:26:32.322392232 +0000
Modify: 2020-03-26 22:24:29.742113292 +0000
Change: 2020-03-26 22:24:29.742113292 +0000
 Birth: -
> chmod 600 a/a
> stat b/a
  File: b/a
  Size: 2         	Blocks: 20         IO Block: 512    regular file
Device: 36h/54d	Inode: 1814195     Links: 2
Access: (0600/-rw-------)  Uid: ( 1000/  ubuntu)   Gid: ( 1000/  ubuntu)
Access: 2020-03-26 22:26:32.322392232 +0000
Modify: 2020-03-26 22:24:29.742113292 +0000
Change: 2020-03-26 22:24:29.742113292 +0000
 Birth: -
> stat a/a
  File: a/a
  Size: 10002     	Blocks: 24         IO Block: 4096   regular file
Device: 801h/2049d	Inode: 1814195     Links: 2
Access: (0600/-rw-------)  Uid: ( 1000/  ubuntu)   Gid: ( 1000/  ubuntu)
Access: 2020-03-26 22:26:32.322392232 +0000
Modify: 2020-03-26 22:27:48.690696428 +0000
Change: 2020-03-26 22:29:16.171019526 +0000
 Birth: -

No package 'fuse3' found when doing pip install on MacOS

Is pyfuse3 meant to be able to work with non-standard implementations of FUSE for MacOS? I'm using @bfleischer's osxfuse (https://github.com/osxfuse/osxfuse).

When trying to install pyfuse3, pip blows up pretty quickly (output below)

└─[$] <> pip install pyfuse3
Collecting pyfuse3
  Using cached pyfuse3-3.1.1.tar.gz (460 kB)
    ERROR: Command errored out with exit status 2:
     command: /Users/myuser/.pyenv/versions/3.9.0/bin/python3.9 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/jm/ljdgg7f537l7wyzzqrf1yzwr0000gn/T/pip-install-e7whjmro/pyfuse3/setup.py'"'"'; __file__='"'"'/private/var/folders/jm/ljdgg7f537l7wyzzqrf1yzwr0000gn/T/pip-install-e7whjmro/pyfuse3/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /private/var/folders/jm/ljdgg7f537l7wyzzqrf1yzwr0000gn/T/pip-pip-egg-info-mketchj9
         cwd: /private/var/folders/jm/ljdgg7f537l7wyzzqrf1yzwr0000gn/T/pip-install-e7whjmro/pyfuse3/
    Complete output (4 lines):
    Package fuse3 was not found in the pkg-config search path.
    Perhaps you should add the directory containing `fuse3.pc'
    to the PKG_CONFIG_PATH environment variable
    No package 'fuse3' found
    ----------------------------------------
ERROR: Command errored out with exit status 2: python setup.py egg_info Check the logs for full command output.

st_{m,a,c,...}time_ns methods lose accuracy

Python real values have 15 (or so) digits of accuracy. Seconds-since-1970 (eg. 1,576,800,000), use 10 of those digits (roughly). This means that representing any FS time as a real value will lose several decimal places.

Specifically, it will not have sufficient precision to represent seconds with nano-second accuracy.

This affects (I think) all of the uses of the st_{m,a,c,...}time_ns methods.

Worse, it affects the getters (eg. st_mtime_ns), causing them to return values that are exactly 1 second greater than they should be.

Install Error in Ubuntu 20.04

$ pip3 install pyfuse3
Collecting pyfuse3
  Using cached pyfuse3-2.0.0.tar.gz (546 kB)
    ERROR: Command errored out with exit status 2:
     command: /usr/bin/python3 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-6yl12cvl/pyfuse3/setup.py'"'"'; __file__='"'"'/tmp/pip-install-6yl12cvl/pyfuse3/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-install-6yl12cvl/pyfuse3/pip-egg-info
         cwd: /tmp/pip-install-6yl12cvl/pyfuse3/
    Complete output (4 lines):
    Package fuse3 was not found in the pkg-config search path.
    Perhaps you should add the directory containing `fuse3.pc'
    to the PKG_CONFIG_PATH environment variable
    No package 'fuse3' found
    ----------------------------------------
ERROR: Command errored out with exit status 2: python setup.py egg_info Check the logs for full command output.

test_passthroughfs sometimes fails due to timestamp difference

Seen on github actions CI:

Traceback (most recent call last):
  File "/home/runner/work/pyfuse3/pyfuse3/test/test_examples.py", line 124, in test_passthroughfs
    tst_passthrough(src_dir, mnt_dir)
  File "/home/runner/work/pyfuse3/pyfuse3/test/test_examples.py", line 412, in tst_passthrough
    assert_same_stats(src_name, mnt_name)
  File "/home/runner/work/pyfuse3/pyfuse3/test/test_examples.py", line 438, in assert_same_stats
    assert  v1 == v2, 'Attribute {} differs by {} ({} vs {})'.format(
AssertionError: Attribute st_mtime_ns differs by 4000074 (1654852943987067641 vs 1654852943983067567)
assert 1654852943987067641 == 1654852943983067567

Bug in setup.py (with fix): some pkg-config failures are ignored.

setup.py has some bugs in the way it calls pkg-config.

When pkg-config fails, setup.py raises SystemExit() but doesn't supply a nonzero status code.

The error exists on lines 167 and 183 of setup.py. The offending lines look like this:
raise SystemExit() # pkg-config generates error message already

Fix:
raise SystemExit(1) # pkg-config generates error message already

python 3.9, cython 0.29.21 FTBFS: error: ‘_PyUnicode_get_wstr_length’ is deprecated

a more complete protocol of struggle
(git)lena:~/proj/misc/pyfuse3[master]git
$> py=3.9; d=venvs/dev$py; virtualenv --python=python$py --system-site-packages $d && source $d/bin/activate && pip3 install -e .
created virtual environment CPython3.9.1.final.0-64 in 128ms
  creator CPython3Posix(dest=/home/yoh/proj/misc/pyfuse3/venvs/dev3.9, clear=False, no_vcs_ignore=False, global=True)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/home/yoh/.local/share/virtualenv)
    added seed packages: pip==20.1.1, pkg_resources==0.0.0, setuptools==44.0.0, wheel==0.34.2
  activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator
Obtaining file:///home/yoh/proj/misc/pyfuse3
Collecting trio>=0.15
  Using cached trio-0.18.0-py3-none-any.whl (354 kB)
Requirement already satisfied: attrs>=19.2.0 in /usr/lib/python3/dist-packages (from trio>=0.15->pyfuse3==3.2.0) (20.3.0)
Collecting outcome
  Using cached outcome-1.1.0-py2.py3-none-any.whl (9.7 kB)
Requirement already satisfied: sortedcontainers in /usr/lib/python3/dist-packages (from trio>=0.15->pyfuse3==3.2.0) (2.1.0)
Collecting async-generator>=1.9
  Using cached async_generator-1.10-py3-none-any.whl (18 kB)
Collecting sniffio
  Using cached sniffio-1.2.0-py3-none-any.whl (10 kB)
Requirement already satisfied: idna in /usr/lib/python3/dist-packages (from trio>=0.15->pyfuse3==3.2.0) (2.10)
Installing collected packages: outcome, async-generator, sniffio, trio, pyfuse3
  Running setup.py develop for pyfuse3
    ERROR: Command errored out with exit status 1:
     command: /home/yoh/proj/misc/pyfuse3/venvs/dev3.9/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/home/yoh/proj/misc/pyfuse3/setup.py'"'"'; __file__='"'"'/home/yoh/proj/misc/pyfuse3/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' develop --no-deps
         cwd: /home/yoh/proj/misc/pyfuse3/
    Complete output (26 lines):
    found MANIFEST.in, running in developer mode
    running develop
    running egg_info
    writing src/pyfuse3.egg-info/PKG-INFO
    writing dependency_links to src/pyfuse3.egg-info/dependency_links.txt
    writing requirements to src/pyfuse3.egg-info/requires.txt
    writing top-level names to src/pyfuse3.egg-info/top_level.txt
    /home/yoh/proj/misc/pyfuse3/venvs/dev3.9/lib/python3.9/site-packages/setuptools/lib2to3_ex.py:12: PendingDeprecationWarning: lib2to3 package is deprecated and may not be able to parse Python 3.10+
      from lib2to3.refactor import RefactoringTool, get_fixers_from_package
    reading manifest template 'MANIFEST.in'
    warning: no directories found matching 'doc/html'
    no previously-included directories found matching 'test/.cache'
    warning: no previously-included files matching '*.pyc' found anywhere in distribution
    writing manifest file 'src/pyfuse3.egg-info/SOURCES.txt'
    running build_ext
    building 'pyfuse3' extension
    creating build/temp.linux-x86_64-3.9
    creating build/temp.linux-x86_64-3.9/src
    x86_64-linux-gnu-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/home/yoh/proj/misc/pyfuse3/venvs/dev3.9/include -I/usr/include/python3.9 -c src/pyfuse3.c -o build/temp.linux-x86_64-3.9/src/pyfuse3.o -I/usr/include/fuse3 -DFUSE_USE_VERSION=32 -Wall -Wextra -Wconversion -Wsign-compare -DPYFUSE3_VERSION="3.2.0" -Wno-unused-function -Wno-implicit-fallthrough -Wno-unused-function -Wno-unused-parameter -Werror -Wfatal-errors -Wno-error=unreachable-code -Werror=conversion -Werror=sign-compare
    src/pyfuse3.c: In function ‘__Pyx_ParseOptionalKeywords’:
    src/pyfuse3.c:50650:21: error: ‘_PyUnicode_get_wstr_length’ is deprecated [-Werror=deprecated-declarations]
    50650 |                     (PyUnicode_GET_SIZE(**name) != PyUnicode_GET_SIZE(key)) ? 1 :
          |                     ^
    compilation terminated due to -Wfatal-errors.
    cc1: all warnings being treated as errors
    error: command '/usr/bin/x86_64-linux-gnu-gcc' failed with exit code 1
    ----------------------------------------
ERROR: Command errored out with exit status 1: /home/yoh/proj/misc/pyfuse3/venvs/dev3.9/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/home/yoh/proj/misc/pyfuse3/setup.py'"'"'; __file__='"'"'/home/yoh/proj/misc/pyfuse3/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' develop --no-deps Check the logs for full command output.
pip3 install -e .  4.88s user 0.56s system 94% cpu 5.730 total

and here is manual piece meal

$> python3 setup.py build_cython
found MANIFEST.in, running in developer mode
running build_cython
Compiling /home/yoh/proj/misc/pyfuse3/src/pyfuse3.pyx
$> python3 setup.py build_ext --inplace
found MANIFEST.in, running in developer mode
running build_ext
building 'pyfuse3' extension
x86_64-linux-gnu-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/home/yoh/proj/misc/pyfuse3/venvs/dev3.9/include -I/usr/include/python3.9 -c src/pyfuse3.c -o build/temp.linux-x86_64-3.9/src/pyfuse3.o -I/usr/include/fuse3 -DFUSE_USE_VERSION=32 -Wall -Wextra -Wconversion -Wsign-compare -DPYFUSE3_VERSION="3.2.0" -Wno-unused-function -Wno-implicit-fallthrough -Wno-unused-function -Wno-unused-parameter -Werror -Wfatal-errors -Wno-error=unreachable-code -Werror=conversion -Werror=sign-compare
src/pyfuse3.c: In function ‘__Pyx_ParseOptionalKeywords’:
src/pyfuse3.c:50650:21: error: ‘_PyUnicode_get_wstr_length’ is deprecated [-Werror=deprecated-declarations]
50650 |                     (PyUnicode_GET_SIZE(**name) != PyUnicode_GET_SIZE(key)) ? 1 :
      |                     ^
compilation terminated due to -Wfatal-errors.
cc1: all warnings being treated as errors
error: command '/usr/bin/x86_64-linux-gnu-gcc' failed with exit code 1

TypeError in examples/tmpfs.py

I'm not sure whether this or libfuse is the more appropriate repo for this, or whether it falls under the exemptions listed here, or whether it's even an issue at all and not user error. But debugging it myself has been difficult as trio seems to make it difficult to find the source of the failing task.

Steps to (hopefully re)produce:

  • From one console
    -- Build HEAD versions of libfuse, pyfuse3
    -- cd pyfuse/examples
    -- python3.6 tmpfs.py /home/username/foo
  • From a second, after this is done
    -- cd ~/foo
    -- touch file
    --mv file file2

Console 1: (below)
Console 2: mv: cannot move 'file' to 'file2': Software caused connection abort

Traceback (most recent call last):
  File "tmpfs.py", line 495, in <module>
    trio.run(pyfuse3.main)
  File "/usr/local/lib/python3.6/dist-packages/trio/_core/_run.py", line 1337, in run
    raise runner.main_task_outcome.error
  File "/home/username/workspaces/vscode/fuse-test/pyfuse3/src/_pyfuse3.py", line 26, in wrapper
    await fn(*args, **kwargs)
  File "src/pyfuse3.pyx", line 743, in main
  File "/usr/local/lib/python3.6/dist-packages/trio/_core/_run.py", line 397, in __aexit__
    raise combined_error_from_nursery
  File "/home/username/workspaces/vscode/fuse-test/pyfuse3/src/_pyfuse3.py", line 26, in wrapper
    await fn(*args, **kwargs)
  File "src/internal.pxi", line 247, in _session_loop
  File "src/handlers.pxi", line 339, in fuse_rename_async
TypeError: rename() takes 6 positional arguments but 7 were given

How to use pyfuse3 without Trio/with asyncio?

Asynchronous I/O is obviously a perfect match for FUSE, so first of all, thanks a lot for working on this!

It's mentioned in several places that pyfuse3 is "Trio-compatible", and Trio is not listed as a dependency in setup.py, so I assume that that Trio is not required to run pyfuse3. I'd like to use pyfuse3 together with an asyncio-based library. I could of course hack something together using two threads, one running an asyncio event loop and the other using Trio, but there has to be a better way than that. Based on a cursory look at the pyfuse3 source code, it appears that Trio is only used in very few places at a high level (i.e. not deeply inside the internals), and it seems that only two methods would have to be reimplemented using another asynchronous I/O implementation, main and _session_loop. Is that correct? Do you happen to have any example code for asyncio + pyfuse3? Also, would having asyncio support in pyfuse3 be desirable?

be compatible with macOS?

python 3.7
pip install pyfuse3

Lots of error and install failed.
Search and google , it seems that pyfuse3 does not support Mac OS. Is that true? Do we have plan to support Mac OS?

compatibility layer for twisted?

I'm using pyfuse3 in a project that already uses twisted as async IO framework. I wonder if it's possible to have a compabitility layer for it, similar to the one for asyncio? I don't mind writing it myself, but just want some opinion from the author that it's actually possible. Thank you.

Test case test_rounding fails on i686

Looks like an integer size problem:

============================= test session starts ==============================
platform linux -- Python 3.9.6, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /build/pyfuse3-3.2.0
plugins: trio-0.7.0
collected 17 items / 1 deselected / 16 selected                                

test/test_api.py ...s.                                                   [ 31%]
test/test_examples.py ssss                                               [ 56%]
test/test_fs.py ssssss                                                   [ 93%]
test/test_rounding.py F                                                  [100%]

=================================== FAILURES ===================================
________________________________ test_rounding _________________________________

    def test_rounding():
        # Incorrect division previously resulted in rounding errors for
        # all dates.
        entry = pyfuse3.EntryAttributes()
    
        # Approximately 100 years, ending in 999
        secs = 100 * 365 * 24 * 3600 + 999
        nanos = _NANOS_PER_SEC - 1
    
        total = secs * _NANOS_PER_SEC + nanos
    
>       entry.st_atime_ns = total

test/test_rounding.py:31: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   self.attr.st_atime = val // _NANOS_PER_SEC
E   OverflowError: Python int too large to convert to C long

src/pyfuse3.pyx:295: OverflowError
=============================== warnings summary ===============================
test/test_fs.py:47
  /build/pyfuse3-3.2.0/test/test_fs.py:47: PytestDeprecationWarning: @pytest.yield_fixture is deprecated.
  Use @pytest.fixture instead; they are the same.
    @pytest.yield_fixture()

-- Docs: https://docs.pytest.org/en/stable/warnings.html
=========================== short test summary info ============================
FAILED test/test_rounding.py::test_rounding - OverflowError: Python int too l...
====== 1 failed, 4 passed, 11 skipped, 1 deselected, 1 warning in 27.32s =======

Python3.9 : Regenerate pyfuse3.c by cython

The PyTypeObject structure has changed. There is no tp_print slot any more.
I couldn't regenerate it myself, since cython bails out with "GIL" errors.
Thanks,
Helmut

master branch is failing to compile

Hi, thanks for this great work. I was just trying to install it and I got

Processing /home/carlopires/ca/pyfuse3
Requirement already satisfied: trio>=0.15 in ./.venv/lib/python3.8/site-packages (from pyfuse3==3.2.0) (0.18.0)
Requirement already satisfied: sniffio in ./.venv/lib/python3.8/site-packages (from trio>=0.15->pyfuse3==3.2.0) (1.2.0)
Requirement already satisfied: sortedcontainers in ./.venv/lib/python3.8/site-packages (from trio>=0.15->pyfuse3==3.2.0) (2.3.0)
Requirement already satisfied: idna in ./.venv/lib/python3.8/site-packages (from trio>=0.15->pyfuse3==3.2.0) (3.1)
Requirement already satisfied: outcome in ./.venv/lib/python3.8/site-packages (from trio>=0.15->pyfuse3==3.2.0) (1.1.0)
Requirement already satisfied: async-generator>=1.9 in ./.venv/lib/python3.8/site-packages (from trio>=0.15->pyfuse3==3.2.0) (1.10)
Requirement already satisfied: attrs>=19.2.0 in ./.venv/lib/python3.8/site-packages (from trio>=0.15->pyfuse3==3.2.0) (20.3.0)
Building wheels for collected packages: pyfuse3
  Building wheel for pyfuse3 (setup.py) ... error
  ERROR: Command errored out with exit status 1:
   command: /home/carlopires/ca/pyfuse3/.venv/bin/python3 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-req-build-g3d3mwl4/setup.py'"'"'; __file__='"'"'/tmp/pip-req-build-g3d3mwl4/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /tmp/pip-wheel-az56lkro
       cwd: /tmp/pip-req-build-g3d3mwl4/
  Complete output (17 lines):
  found MANIFEST.in, running in developer mode
  running bdist_wheel
  running build
  running build_py
  creating build
  creating build/lib.linux-x86_64-3.8
  copying src/_pyfuse3.py -> build/lib.linux-x86_64-3.8
  copying src/pyfuse3_asyncio.py -> build/lib.linux-x86_64-3.8
  running build_ext
  building 'pyfuse3' extension
  creating build/temp.linux-x86_64-3.8
  creating build/temp.linux-x86_64-3.8/src
  gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/home/carlopires/ca/pyfuse3/.venv/include -I/opt/python/cpython/3/include/python3.8 -c src/pyfuse3.c -o build/temp.linux-x86_64-3.8/src/pyfuse3.o -I/usr/include/fuse3 -DFUSE_USE_VERSION=32 -Wall -Wextra -Wconversion -Wsign-compare -DPYFUSE3_VERSION="3.2.0" -Wno-unused-function -Wno-implicit-fallthrough -Wno-unused-function -Wno-unused-parameter -Werror -Wfatal-errors -Wno-error=unreachable-code -Werror=conversion -Werror=sign-compare
  gcc: error: src/pyfuse3.c: Arquivo ou diretório inexistente
  gcc: fatal error: no input files
  compilation terminated.
  error: command 'gcc' failed with exit status 1
  ----------------------------------------
  ERROR: Failed building wheel for pyfuse3
  Running setup.py clean for pyfuse3
Failed to build pyfuse3

It seems pyfuse3.c is not used anymore, is Ok to just remove it from c_sources in setup.py?

EPERM should be EACCES in a few places

In src/handlers.pxi, if the access handler returns a false boolean value, then FUSEError(EPERM) is raised ... shouldn't that be EACCES?

The examples examples/hello.py and examples/hello_asyncio.py raise FUSEError(EPERM) if write access is denied for open ... I think that should also be EACCES.

The tests test/test_examples.py and test/test_fs.py have the same problem for open.

Test cases fail under Valgrind

With at least Python 3.7.1 and today's cpython Git master, we get:

test/test_examples.py::test_hello[hello.py] FAILED                                     [ 46%]
[...]
------------------------------------ Captured stderr call ------------------------------------
==31074== Memcheck, a memory error detector
==31074== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==31074== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==31074== Command: /home/nikratio/clones/cpython/python /home/nikratio/in-progress/pyfuse3/test/../examples/hello.py /tmp/pytest-of-nikratio/pytest-11/test_hello_hello_py_0
==31074== 
==31074== Syscall param epoll_ctl(event) points to uninitialised byte(s)
==31074==    at 0x584906A: epoll_ctl (syscall-template.S:84)
==31074==    by 0xBDAA493: pyepoll_internal_ctl (selectmodule.c:1392)
==31074==    by 0xBDAA59F: select_epoll_register_impl (selectmodule.c:1438)
==31074==    by 0xBDAA5F8: select_epoll_register (selectmodule.c.h:599)
==31074==    by 0x174E15: _PyMethodDef_RawFastCallKeywords (call.c:658)
==31074==    by 0x300BCA: _PyMethodDescr_FastCallKeywords (descrobject.c:290)
==31074==    by 0x21FC05: call_function (ceval.c:4611)
==31074==    by 0x22B5E7: _PyEval_EvalFrameDefault (ceval.c:3183)
==31074==    by 0x2206FF: PyEval_EvalFrameEx (ceval.c:533)
==31074==    by 0x173B61: function_code_fastcall (call.c:285)
==31074==    by 0x174737: _PyFunction_FastCallKeywords (call.c:410)
==31074==    by 0x21FDF4: call_function (ceval.c:4634)
==31074==  Address 0xffeffeb4c is on thread 1's stack
==31074==  in frame #1, created by pyepoll_internal_ctl (selectmodule.c:1379)

Reported upstream as https://bugs.python.org/issue35561

Gracefully stopping pyfuse3 from within an application

Is there any way to cleanly stop a mount from within a module using pyfuse3? E.g.

import pyfuse3

class MyOperations(pyfuse3.Operations):
    # ...

async def dosomework():
    await trio.sleep(3)
    pyfuse3.close() # <<< What to put here to stop the mount?

await main():
    async with trio.open_nursery() as nursery:
        nursery.start_soon(pyfuse3.main)
        nursery.start_soon(dosomework)

# set up operations, pyfuse3.init
trio.run(main)

I would expect this to stop the mount after ~3 seconds, but it definitely doesn't work. During my tests with #8, I even managed to get a segfault, but that might've been related to my changes instead.
I guess it should be possible to execute fusermount -u, but that seems very awkward.

Errors on PyPy3

Should the library run on PyPy? Trying pyfuse3 v3.1.1 on PyPy 7.3.2, pyfuse3 compiles, but when I tried to run/mount the hello.py example:

# python hello.py /mnt/fuse
Traceback (most recent call last):
  File "hello.py", line 157, in <module>
    main()
  File "hello.py", line 148, in main
    trio.run(pyfuse3.main)
  File "/root/test/pypyvenv/site-packages/trio/_core/_run.py", line 1928, in run
    raise runner.main_task_outcome.error
  File "/root/test/pypyvenv/site-packages/_pyfuse3.py", line 30, in wrapper
    await fn(*args, **kwargs)
  File "src/pyfuse3.pyx", line 767, in main
  File "src/pyfuse3.pyx", line 770, in pyfuse3.main
AttributeError: 'NoneType' object has no attribute 'start_soon'

Same thing with hello_async.py:

# python hello_asyncio.py /mnt/fuse
Traceback (most recent call last):
  File "hello_asyncio.py", line 162, in <module>
    main()
  File "hello_asyncio.py", line 151, in main
    loop.run_until_complete(pyfuse3.main())
  File "/usr/lib/pypy3/lib-python/3/asyncio/base_events.py", line 488, in run_until_complete
    return future.result()
  File "/usr/lib/pypy3/lib-python/3/asyncio/futures.py", line 243, in result
    raise self._exception
  File "/usr/lib/pypy3/lib-python/3/asyncio/tasks.py", line 180, in _step
    result = coro.send(None)
  File "/root/test/pypyvenv/site-packages/_pyfuse3.py", line 30, in wrapper
    await fn(*args, **kwargs)
  File "src/pyfuse3.pyx", line 767, in main
  File "src/pyfuse3.pyx", line 770, in pyfuse3.main
AttributeError: 'NoneType' object has no attribute 'start_soon'

Package versions:

# pip freeze
async-generator==1.10
attrs==20.3.0
cffi==1.14.2
contextvars==2.4
greenlet==0.4.13
idna==2.10
immutables==0.14
outcome==1.1.0
Pillow==8.0.1
pyfuse3==3.1.1
readline==6.2.4.1
sniffio==1.2.0
sortedcontainers==2.3.0
trio==0.17.0

Trio claims to work on PyPy, so I'm wondering what's going on here. It also seems that even the asyncio example (hello_async.py) initializes through Trio somehow.

AUR deps

==> Запускается build()...
found MANIFEST.in, running in developer mode
running build_cython
Traceback (most recent call last):
  File "/home/nikto_b/.cache/yay/python-pyfuse3/src/pyfuse3-pyfuse-3.2.0/setup.py", line 275, in <module>
    main()
  File "/home/nikto_b/.cache/yay/python-pyfuse3/src/pyfuse3-pyfuse-3.2.0/setup.py", line 117, in main
    setuptools.setup(
  File "/home/nikto_b/.local/lib/python3.9/site-packages/setuptools/__init__.py", line 153, in setup
    return distutils.core.setup(**attrs)
  File "/usr/lib/python3.9/distutils/core.py", line 148, in setup
    dist.run_commands()
  File "/usr/lib/python3.9/distutils/dist.py", line 966, in run_commands
    self.run_command(cmd)
  File "/usr/lib/python3.9/distutils/dist.py", line 985, in run_command
    cmd_obj.run()
  File "/home/nikto_b/.cache/yay/python-pyfuse3/src/pyfuse3-pyfuse-3.2.0/setup.py", line 218, in run
    version = subprocess.check_output([c, '--version'],
  File "/usr/lib/python3.9/subprocess.py", line 420, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "/usr/lib/python3.9/subprocess.py", line 524, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['cython', '--version']' returned non-zero exit status 1.
==> ОШИБКА: Произошел сбой в build().
    Прерывание...
ошибка сборки: python-pyfuse3

Error caused because of cython not installed

$ cython     
Traceback (most recent call last):
  File "/usr/bin/cython", line 5, in <module>
    from Cython.Compiler.Main import setuptools_main
ModuleNotFoundError: No module named 'Cython'

Fixed with

pip install cython

can You fix AUR package to provide this dependency?

Various FreeBSD issues

There are a number of issues with pyfuse3 on FreeBSD right now.

Buildtime issues:

  1. In src/pyfuse.pyx, there's def syncfs(path) function that calls libc_extra.syncfs(), which is expected to be available in unistd.h. However, there's no such function available on FreeBSD, and, in general, it appears to be Linux-only.
  2. In src/pyfuse3.pyx, it's expected that linux/fs.h contains RENAME_EXCHANGE and RENAME_NOREPLACE which's not the case on FreeBSD (there's no such header at all).

Runtime issues:

$ sudo python3 examples/tmpfs.py ~/fuse
Traceback (most recent call last):
  File "examples/tmpfs.py", line 451, in <module>
    trio.run(pyfuse3.main)
  File "/usr/local/lib/python3.6/site-packages/trio-0.11.0-py3.6.egg/trio/_core/_run.py", line 1444, in run
    raise runner.main_task_outcome.error
  File "/usr/home/novel/code/pyfuse3/src/_pyfuse3.py", line 30, in wrapper
    await fn(*args, **kwargs)
  File "src/pyfuse3.pyx", line 732, in main
    async with trio.open_nursery() as nursery:
  File "/usr/local/lib/python3.6/site-packages/trio-0.11.0-py3.6.egg/trio/_core/_run.py", line 506, in __aexit__
    raise combined_error_from_nursery
  File "/usr/home/novel/code/pyfuse3/src/_pyfuse3.py", line 30, in wrapper
    await fn(*args, **kwargs)
  File "src/internal.pxi", line 229, in _session_loop
    await _wait_fuse_readable()
  File "src/internal.pxi", line 205, in _wait_fuse_readable
    async with worker_data.read_lock:
  File "src/internal.pxi", line 207, in pyfuse3._wait_fuse_readable
    await trio.hazmat.wait_readable(session_fd)
  File "/usr/local/lib/python3.6/site-packages/trio-0.11.0-py3.6.egg/trio/_core/_io_kqueue.py", line 131, in wait_readable
    await self._wait_common(fd, select.KQ_FILTER_READ)
  File "/usr/local/lib/python3.6/site-packages/trio-0.11.0-py3.6.egg/trio/_core/_io_kqueue.py", line 120, in _wait_common
    self._kqueue.control([event], 0)
OSError: [Errno 19] Operation not supported by device
$

I'm yet to debug this traceback further.

Setup is failing if it doesn't have access to one directory in $PATH

Hi, I struggled a bit on Gentoo's bugzilla because I couldn't install pyfuse3 on one of my machine.

After some investigation, it appears the culprit was one personal directory in the $PATH that couldn't be reached by the package manager (portage).

I'm not a python developper, so I can't really offer a PR.
However, I'd like to point out my findings and why I think this is a bug.

Consider this snippet in setup.py

        cython = None
        for c in ('cython3', 'cython'):
            try:
                version = subprocess.check_output([c, '--version'],
                                              universal_newlines=True, stderr=subprocess.STDOUT)
                cython = c
            except FileNotFoundError:
                pass
        if cython is None:
            raise SystemExit('Cython needs to be installed for this command') from None

As you can see, the try/except is testing for a file to exists, but if one directory in the path isn't accessible, then the exception isn't handled and this result as a general failure.

In my environment, I didn't have a 'cython3' binary, but I had a 'cython' one.
The issue here is since the script aborted while testing for 'cython3', it did not even try to look for 'cython' and just failed and exited the setup script with a:

Permission denied: 'cython3'

Which is a confusing message since this binary doesn't even exist on the system, obviously it's feels wrong to display a permission error on it.

I think adding another except line would make this process more robust.

pyfuse crash if go to the fused directory directly

Another issue in this new version is that it crashed if you try to go to the directory directly.
This works in the old llfuse module.

2018-10-16 16:52:03.801 MainThread: [__main__] lookup for b'vivint' in 385
2018-10-16 16:52:03.803 MainThread: [pyfuse3] Calling fuse_session_unmount
2018-10-16 16:52:03.838 MainThread: [pyfuse3] Calling fuse_session_destroy
Traceback (most recent call last):
  File "jscfs.py", line 410, in <module>
    main()
  File "jscfs.py", line 398, in main
    trio.run(pyfuse3.main)
  File "/usr/local/lib/python3.6/dist-packages/trio/_core/_run.py", line 1328, in run
    raise runner.main_task_outcome.error
  File "/usr/local/lib/python3.6/dist-packages/pyfuse3-0.9-py3.6-linux-x86_64.egg/_pyfuse3.py", line 26, in wrapper
  File "src/pyfuse3.pyx", line 743, in main
  File "/usr/local/lib/python3.6/dist-packages/trio/_core/_run.py", line 395, in __aexit__
    raise combined_error_from_nursery
  File "/usr/local/lib/python3.6/dist-packages/pyfuse3-0.9-py3.6-linux-x86_64.egg/_pyfuse3.py", line 26, in wrapper
  File "src/internal.pxi", line 247, in _session_loop
  File "src/handlers.pxi", line 65, in pyfuse3.fuse_lookup_async
TypeError: Cannot convert coroutine to pyfuse3.EntryAttributes

Python 3.10 compatibility?

pyfuse 3.2.1 fails to build on python 3.10

$ cd pyfuse3-release-3.2.1 

$ python setup.py build_cython       
found MANIFEST.in, running in developer mode
running build_cython
Compiling /mnt/ssd/Scratch/makepkg/python-pyfuse3/src/pyfuse3-release-3.2.1/src/pyfuse3.pyx

$ python setup.py build_ext --inplace
found MANIFEST.in, running in developer mode
running build_ext
building 'pyfuse3' extension
creating build
creating build/temp.linux-x86_64-3.10
creating build/temp.linux-x86_64-3.10/src
gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -march=x86-64 -mtune=generic -O3 -pipe -fno-plt -march=x86-64 -mtune=generic -O3 -pipe -fno-plt -march=x86-64 -mtune=generic -O3 -pipe -fno-plt -fPIC -I/usr/include/python3.10 -c src/pyfuse3.c -o build/temp.linux-x86_64-3.10/src/pyfuse3.o -I/usr/include/fuse3 -DFUSE_USE_VERSION=32 -Wall -Wextra -Wconversion -Wsign-compare -DPYFUSE3_VERSION="3.2.1" -Wno-unused-function -Wno-implicit-fallthrough -Wno-unused-function -Wno-unused-parameter -Werror -Wfatal-errors -Wno-error=unreachable-code -Werror=conversion -Werror=sign-compare
src/pyfuse3.c:53221:1: error: missing initializer for field 'am_send' of 'PyAsyncMethods' [-Werror=missing-field-initializers]
53221 | };
      | ^
compilation terminated due to -Wfatal-errors.
cc1: all warnings being treated as errors
error: command '/usr/bin/gcc' failed with exit code 1

I can see that the error is in generated code, but I've really no idea what to do with it. Python 3.10.0, Cython 0.29.25. Doesn't happen with python 3.9.9.

Error when install pyfuse3 on EC2 Amazon linux

in EC2 Amazon linux install
pip3 install pyfuse3

ERRORs
Defaulting to user installation because normal site-packages is not writeable
Collecting pyfuse3
Using cached pyfuse3-3.2.1.tar.gz (509 kB)
ERROR: Command errored out with exit status 2:
command: /usr/bin/python3 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-6b0b20_w/pyfuse3/setup.py'"'"'; file='"'"'/tmp/pip-install-6b0b20_w/pyfuse3/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(file);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, file, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-vvfst1nw
cwd: /tmp/pip-install-6b0b20_w/pyfuse3/
Complete output (4 lines):
Package fuse3 was not found in the pkg-config search path.
Perhaps you should add the directory containing `fuse3.pc'
to the PKG_CONFIG_PATH environment variable
No package 'fuse3' found
----------------------------------------
ERROR: Command errored out with exit status 2: python setup.py egg_info Check the logs for full command output.

Cannot install fuse3 in ec2 linux

pip3 install fuse3
Defaulting to user installation because normal site-packages is not writeable
ERROR: Could not find a version that satisfies the requirement fuse3 (from versions: none)
ERROR: No matching distribution found for fuse3

or
wget https://github.com/libfuse/libfuse/archive/refs/tags/fuse-3.11.0.tar.gz
pip3 install fuse-3.11.0.tar.gz

Defaulting to user installation because normal site-packages is not writeable
Processing ./fuse-3.11.0.tar.gz
ERROR: Command errored out with exit status 1:
command: /usr/bin/python3 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-req-build-jvi0dibk/setup.py'"'"'; file='"'"'/tmp/pip-req-build-jvi0dibk/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(file);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, file, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-cn4_8du6
cwd: /tmp/pip-req-build-jvi0dibk/
Complete output (5 lines):
Traceback (most recent call last):
File "", line 1, in
File "/usr/lib64/python3.7/tokenize.py", line 447, in open
buffer = _builtin_open(filename, 'rb')
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/pip-req-build-jvi0dibk/setup.py'
----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

Any suggestions?

tmpfs crashes on access to deleted file

Hi,

Apologies for the slightly vague report, but on the current version of ubuntu test_tmpfs fails, and the failure seems to boil down to this:

In one terminal:

ubuntu@autopkgtest:~/pyfuse3$ mkdir /tmp/foo
ubuntu@autopkgtest:~/pyfuse3$ python3 examples/tmpfs.py  /tmp/foo

In another

ubuntu@autopkgtest:/tmp/autopkgtest.llp16Q/build.xqX/real-tree$ touch /tmp/foo/file
ubuntu@autopkgtest:/tmp/autopkgtest.llp16Q/build.xqX/real-tree$ rm /tmp/foo/file
ubuntu@autopkgtest:/tmp/autopkgtest.llp16Q/build.xqX/real-tree$ ls /tmp/foo/file
ls: cannot access '/tmp/foo/file': Transport endpoint is not connected

and going back to the first we see:

Traceback (most recent call last):
  File "/home/ubuntu/pyfuse3/examples/tmpfs.py", line 121, in get_row
    row = next(self.cursor)
StopIteration

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/ubuntu/pyfuse3/examples/tmpfs.py", line 451, in <module>
    trio.run(pyfuse3.main)
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 1932, in run
    raise runner.main_task_outcome.error
  File "/home/ubuntu/pyfuse3/src/_pyfuse3.py", line 43, in wrapper
    await fn(*args, **kwargs)
  File "src/pyfuse3.pyx", line 781, in main
    async with trio.open_nursery() as nursery:
  File "/usr/lib/python3/dist-packages/trio/_core/_run.py", line 815, in __aexit__
    raise combined_error_from_nursery
  File "/home/ubuntu/pyfuse3/src/_pyfuse3.py", line 43, in wrapper
    await fn(*args, **kwargs)
  File "src/internal.pxi", line 272, in _session_loop
    await py_retval
  File "src/handlers.pxi", line 168, in fuse_setattr_async
    entry = <EntryAttributes?> await operations.setattr(c.ino, entry, fields, fh, ctx)
  File "/home/ubuntu/pyfuse3/examples/tmpfs.py", line 315, in setattr
    return await self.getattr(inode)
  File "/home/ubuntu/pyfuse3/examples/tmpfs.py", line 150, in getattr
    row = self.get_row('SELECT * FROM inodes WHERE id=?', (inode,))
  File "/home/ubuntu/pyfuse3/examples/tmpfs.py", line 123, in get_row
    raise NoSuchRowError()
NoSuchRowError: Query produced 0 result rows

This worked a few months ago in Ubuntu so we've probably upgraded some dependency that caused this to break -- any idea which one? :)

Two questions about the method 'readdir' and server crash

i'm writing a fs it's base on a netdisc, now i have two problems, I hope you can take some time to answer:
the first is when call readdir method, i ll request netdisc to read file list, but always lose some file in display, around 23, the total is 37. i printed filename before call method 'pyfuse3.readdir_reply' , the file list is complete, but in terminal is always lose some files, i don't know what happend, maybe i usage is wrong, there is my code snippet:

async def readdir(self, fh, start_id, token):
        if start_id == -1:
            return
        else:
            f = FileMgr.get_from_fs_id(fh)
        files = self.fs.dir_cache('/' if not f else f.path, pyfuse3.ROOT_INODE if not f else f.fs_id)
        for file in files:
            pyfuse3.readdir_reply(token, file.filename_bytes, await self.getattr(file.fs_id, None), -1)

another question is when i mounted fs for nearly ten minutes , the server was always crash,this is error log

"Cannot convert coroutine to pyfuse3.EntryAttributes
2020-04-16 17:08:46.687 MainThread: [pyfuse3] Calling fuse_session_destroy
2020-04-16 17:08:46.687 MainThread: [pyfuse3] Calling fuse_session_unmount"

don't have enough error info , i can't tace back to the point of error.

last, the pyfuse is a very useful lib, thankyou.

Allow users to modify connection properties in `init`

Hi,

I'd like to limit maximum size of read requests incoming to my FS. I tried using max_read=N option (with N = 4096), but then I get an error from libfuse:

fuse: error: init() and fuse_session_new() requested different maximum read size (0 vs 4096)

To illustrate the problem I modified test case - SupraSummus@ce20b49

As far as I understand I need to pass max_read option to libfuse's init(). How do I do that?

Thanks and have a nice day!
Jan Rydzewski

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.