partyfuse: prefer mfusepy (fuse.py fork);

now supports both fuse2 and fuse3

fallback on fuse.py (fuse2-only) if mfusepy unavailable

fuse3 is 20% faster on large files,
fuse2 == fuse3 on small files

motivated by nixos dropping fuse2 in NixOS/nixpkgs#522340
This commit is contained in:
ed 2026-05-21 23:31:57 +00:00
parent 1f4246c6bb
commit b2401ff15a
10 changed files with 41 additions and 27 deletions

View file

@ -26,12 +26,12 @@ and consider using [../docs/rclone.md](../docs/rclone.md) instead; usually a bit
## to run this on windows: ## to run this on windows:
* install [winfsp](https://github.com/billziss-gh/winfsp/releases/latest) and [python 3](https://www.python.org/downloads/) * install [winfsp](https://github.com/billziss-gh/winfsp/releases/latest) and [python 3](https://www.python.org/downloads/)
* [x] add python 3.x to PATH (it asks during install) * [x] add python 3.x to PATH (it asks during install)
* `python -m pip install --user fusepy` (or grab a copy of `fuse.py` from the `connect` page on your copyparty, and keep it in the same folder) * `python -m pip install --user mfusepy` (or grab a copy of `mfusepy.py` from the `connect` page on your copyparty, and keep it in the same folder)
* `python ./partyfuse.py n: http://192.168.1.69:3923/` * `python ./partyfuse.py n: http://192.168.1.69:3923/`
10% faster in [msys2](https://www.msys2.org/), 700% faster if debug prints are enabled: 10% faster in [msys2](https://www.msys2.org/), 700% faster if debug prints are enabled:
* `pacman -S mingw64/mingw-w64-x86_64-python{,-pip}` * `pacman -S mingw64/mingw-w64-x86_64-python{,-pip}`
* `/mingw64/bin/python3 -m pip install --user fusepy` * `/mingw64/bin/python3 -m pip install --user mfusepy`
* `/mingw64/bin/python3 ./partyfuse.py [...]` * `/mingw64/bin/python3 ./partyfuse.py [...]`
you could replace winfsp with [dokan](https://github.com/dokan-dev/dokany/releases/latest), let me know if you [figure out how](https://github.com/dokan-dev/dokany/wiki/FUSE) you could replace winfsp with [dokan](https://github.com/dokan-dev/dokany/releases/latest), let me know if you [figure out how](https://github.com/dokan-dev/dokany/wiki/FUSE)

View file

@ -21,7 +21,7 @@ usage:
python partyfuse.py http://192.168.1.69:3923/ ./music python partyfuse.py http://192.168.1.69:3923/ ./music
dependencies: dependencies:
python3 -m pip install --user fusepy # or grab it from the connect page python3 -m pip install --user mfusepy # or grab it from the connect page
+ on Linux: sudo apk add fuse + on Linux: sudo apk add fuse
+ on Macos: https://osxfuse.github.io/ + on Macos: https://osxfuse.github.io/
+ on Windows: https://github.com/billziss-gh/winfsp/releases/latest + on Windows: https://github.com/billziss-gh/winfsp/releases/latest
@ -92,8 +92,13 @@ is_dbg = False
try: try:
from fuse import FUSE, FuseOSError, Operations from mfusepy import FUSE, FuseOSError, Operations
except: except:
try:
from fuse import FUSE, FuseOSError, Operations
except:
FUSE = None
if WINDOWS: if WINDOWS:
libfuse = "install https://github.com/billziss-gh/winfsp/releases/latest" libfuse = "install https://github.com/billziss-gh/winfsp/releases/latest"
elif MACOS: elif MACOS:
@ -102,10 +107,11 @@ except:
libfuse = "apt install libfuse2\n modprobe fuse" libfuse = "apt install libfuse2\n modprobe fuse"
m = """\033[33m m = """\033[33m
could not import fuse; these may help: could not import mfusepy; these may help:
{} -m pip install --user fusepy {} -m pip install --user mfusepy
{} {}
\033[0m""" \033[0m"""
if not FUSE:
print(m.format(sys.executable, libfuse)) print(m.format(sys.executable, libfuse))
raise raise
@ -143,10 +149,10 @@ def fancy_log(fmt, *a):
def register_wtf8(): def register_wtf8():
def wtf8_enc(text): def wtf8_enc(text, errors=""):
return str(text).encode("utf-8", "surrogateescape"), len(text) return str(text).encode("utf-8", "surrogateescape"), len(text)
def wtf8_dec(binary): def wtf8_dec(binary, errors=""):
return bytes(binary).decode("utf-8", "surrogateescape"), len(binary) return bytes(binary).decode("utf-8", "surrogateescape"), len(binary)
def wtf8_search(encoding_name): def wtf8_search(encoding_name):

View file

@ -77,7 +77,7 @@ web/deps/busy.mp3
web/deps/easymde.css web/deps/easymde.css
web/deps/easymde.js web/deps/easymde.js
web/deps/marked.js web/deps/marked.js
web/deps/fuse.py web/deps/mfusepy.py
web/deps/mini-fa.css web/deps/mini-fa.css
web/deps/mini-fa.woff web/deps/mini-fa.woff
web/deps/prism.css web/deps/prism.css

View file

@ -233,7 +233,7 @@
<h1>partyfuse</h1> <h1>partyfuse</h1>
<p> <p>
<a href="{{ r }}/.cpr/a/partyfuse.py">partyfuse.py</a> -- fast, read-only, <a href="{{ r }}/.cpr/a/partyfuse.py">partyfuse.py</a> -- fast, read-only,
needs <a href="{{ r }}/.cpr/w/deps/fuse.py">fuse.py</a> in the same folder, needs <a href="{{ r }}/.cpr/w/deps/mfusepy.py">mfusepy.py</a> in the same folder,
<span class="os win">needs <a href="https://winfsp.dev/rel/">winfsp</a></span> <span class="os win">needs <a href="https://winfsp.dev/rel/">winfsp</a></span>
<span class="os lin">doesn't need root</span> <span class="os lin">doesn't need root</span>
</p> </p>

View file

@ -374,7 +374,7 @@ some third-party code has been vendored into the git repo; some for convenience,
* `dnslib` (MIT) may be deleted and replaced with a systemwide install of the original [dnslib](https://github.com/paulc/dnslib/), HOWEVER: * `dnslib` (MIT) may be deleted and replaced with a systemwide install of the original [dnslib](https://github.com/paulc/dnslib/), HOWEVER:
* will cause problems for mDNS in some network environments; 6c1cf68bca7376c6291c3cfe710ebd5bd5ed3e6c + 94d1924fa97e5faaf1ebfd85cae73faebcb89fa1 * will cause problems for mDNS in some network environments; 6c1cf68bca7376c6291c3cfe710ebd5bd5ed3e6c + 94d1924fa97e5faaf1ebfd85cae73faebcb89fa1
* inside the folder `/copyparty/web/deps` (only in distributed archives/builds) is [fuse.py](https://github.com/fusepy/fusepy/blob/master/fuse.py), to make it downloadable from the connect-page on the web-ui * inside the folder `/copyparty/web/deps` (only in distributed archives/builds) is [mfusepy.py](https://github.com/mxmlnkn/mfusepy/blob/master/mfusepy.py) (sizegolfed, no important changes), to make it downloadable from the connect-page on the web-ui
* inside the folder `/copyparty/web` (only in distributed archives/builds) is a collection of javascript libraries (produced by [deps-docker](https://github.com/9001/copyparty/tree/hovudstraum/scripts/deps-docker)) which are used clientside by the web-UI: * inside the folder `/copyparty/web` (only in distributed archives/builds) is a collection of javascript libraries (produced by [deps-docker](https://github.com/9001/copyparty/tree/hovudstraum/scripts/deps-docker)) which are used clientside by the web-UI:
* [marked.js](https://github.com/markedjs/marked/releases) (MIT) powers the markdown editor, and has been [patched](https://github.com/9001/copyparty/blob/hovudstraum/scripts/deps-docker/marked-ln.patch) to include the line-numbers of each input line, to enable scroll-sync between the editor and the preview-pane. This patch is [not strictly necessary anymore](https://github.com/markedjs/marked/issues/2134) but I haven't gotten around to making the change yet * [marked.js](https://github.com/markedjs/marked/releases) (MIT) powers the markdown editor, and has been [patched](https://github.com/9001/copyparty/blob/hovudstraum/scripts/deps-docker/marked-ln.patch) to include the line-numbers of each input line, to enable scroll-sync between the editor and the preview-pane. This patch is [not strictly necessary anymore](https://github.com/markedjs/marked/issues/2134) but I haven't gotten around to making the change yet

View file

@ -36,7 +36,7 @@ https://github.com/ahupp/python-magic/
C: 2001-2014 Adam Hupp C: 2001-2014 Adam Hupp
L: MIT L: MIT
https://github.com/fusepy/fusepy https://github.com/mxmlnkn/mfusepy
C: 2012 Giorgos Verigakis C: 2012 Giorgos Verigakis
L: ISC L: ISC

View file

@ -24,8 +24,9 @@ RUN mkdir -p /z/dist/no-pk \
&& wget https://fonts.gstatic.com/s/sourcecodepro/v11/HI_SiYsKILxRpg3hIP6sJ7fM7PqlPevW.woff2 -O scp.woff2 \ && wget https://fonts.gstatic.com/s/sourcecodepro/v11/HI_SiYsKILxRpg3hIP6sJ7fM7PqlPevW.woff2 -O scp.woff2 \
&& apk add \ && apk add \
bash brotli cmake make g++ git gzip lame npm patch pigz \ bash brotli cmake make g++ git gzip lame npm patch pigz \
python3 python3-dev py3-brotli sox tar unzip wget \ python3 python3-dev py3-pip py3-brotli sox tar unzip wget \
&& rm -f /usr/lib/python3*/EXTERNALLY-MANAGED \ && rm -f /usr/lib/python3*/EXTERNALLY-MANAGED \
&& pip install strip_hints \
&& wget https://github.com/markedjs/marked/archive/v$ver_marked.tar.gz -O marked.tgz \ && wget https://github.com/markedjs/marked/archive/v$ver_marked.tar.gz -O marked.tgz \
&& wget https://github.com/Ionaru/easy-markdown-editor/archive/$ver_mde.tar.gz -O mde.tgz \ && wget https://github.com/Ionaru/easy-markdown-editor/archive/$ver_mde.tar.gz -O mde.tgz \
&& wget https://github.com/codemirror/codemirror5/archive/$ver_codemirror.tar.gz -O codemirror.tgz \ && wget https://github.com/codemirror/codemirror5/archive/$ver_codemirror.tar.gz -O codemirror.tgz \
@ -34,7 +35,7 @@ RUN mkdir -p /z/dist/no-pk \
&& wget https://github.com/google/zopfli/archive/zopfli-$ver_zopfli.tar.gz -O zopfli.tgz \ && wget https://github.com/google/zopfli/archive/zopfli-$ver_zopfli.tar.gz -O zopfli.tgz \
&& wget https://github.com/Daninet/hash-wasm/releases/download/v$ver_hashwasm/hash-wasm@$ver_hashwasm.zip -O hash-wasm.zip \ && wget https://github.com/Daninet/hash-wasm/releases/download/v$ver_hashwasm/hash-wasm@$ver_hashwasm.zip -O hash-wasm.zip \
&& wget https://github.com/PrismJS/prism/archive/refs/tags/v$ver_prism.tar.gz -O prism.tgz \ && wget https://github.com/PrismJS/prism/archive/refs/tags/v$ver_prism.tar.gz -O prism.tgz \
&& wget https://files.pythonhosted.org/packages/04/0b/4506cb2e831cea4b0214d3625430e921faaa05a7fb520458c75a2dbd2152/fusepy-3.0.1.tar.gz -O fusepy.tgz \ && wget https://files.pythonhosted.org/packages/91/47/746287c8962274f73ee25edb3840d80899464bfffbe2c435424c2d60a071/mfusepy-3.1.1.tar.gz -O mfusepy.tgz \
&& (mkdir hash-wasm \ && (mkdir hash-wasm \
&& cd hash-wasm \ && cd hash-wasm \
&& unzip ../hash-wasm.zip) \ && unzip ../hash-wasm.zip) \
@ -51,7 +52,7 @@ RUN mkdir -p /z/dist/no-pk \
&& npm i gulp-cli -g ) \ && npm i gulp-cli -g ) \
&& tar --no-same-owner -xf dompurify.tgz \ && tar --no-same-owner -xf dompurify.tgz \
&& tar --no-same-owner -xf prism.tgz \ && tar --no-same-owner -xf prism.tgz \
&& tar --no-same-owner -xf fusepy.tgz \ && tar --no-same-owner -xf mfusepy.tgz \
&& unzip fontawesome.zip \ && unzip fontawesome.zip \
&& tar --no-same-owner -xf zopfli.tgz && tar --no-same-owner -xf zopfli.tgz
@ -148,16 +149,22 @@ RUN cd /z/dist \
&& rmdir no-pk && rmdir no-pk
# build fusepy # build mfusepy -- just sizegolfing for the sfx, mfusepy.py works fine as-is
COPY uncomment.py /z COPY uncomment.py unhint.py /z
RUN mv /z/fusepy-3.0.1/fuse.py /z/dist/f1 \ RUN mv /z/mfusepy-3.1.1/mfusepy.py /z/dist/ \
&& cd /z/dist \ && cd /z/dist \
&& python3 /z/unhint.py \
&& mv mfusepy.py f1 \
&& python3 /z/uncomment.py f1 \ && python3 /z/uncomment.py f1 \
&& sed -ri '/self.__critical_exception = e/d' f1 \ && sed -ri '/self.__critical_exception/d; /^from (typing|collections.abc) import/d' f1 \
&& awk '/^log =/{s=0} !s; /^from traceback im/{s=1;print"from functools import partial";print"basestring = str"}' <f1 >f2 \ && sed -ri '/^(FieldsEntry|BitFieldsEntry|ReadDirResult) =/d' f1 \
&& awk '/LoggingMixIn:/{exit} --s<0;/self.use_ns = getattr/{s=7}' <f2 >f1 \ && awk "/if TYPE_CHECKING:/{s=1;sub(/TYPE_CHECKING/,"1");print}!s;/else:/{s=0}" <f1 >f2 \
&& awk "/if _machine =/{s=0} /'(mips|ppc|ppc64)'/{s=1} !s" <f1 >f2 \ && awk '/^def _nullable_dummy_function/{print"class Operations:\n pass";exit};1' <f2 >f1 \
&& rm f1 && mv f2 fuse.py && awk '/^# Note that/{s=3} --s<0; /self.use_ns = getattr/{s=16}' <f1 >f2 \
&& awk "/if _machine =/{s=0} /_machine == '(mips|ppc|ppc64)'/{s=1} !s" <f2 >f1 \
&& awk '/else:/{s=0} /elif _system == .NetBSD/{s=1} !s' <f1 >f2 \
&& awk '/^if _system == .NetBSD_False/{s=1;print"if 0:\n pass"} /^elif/{s=0} !s' <f2 >f1 \
&& rm f2 && mv f1 mfusepy.py
# git diff -U2 --no-index marked-1.1.0-orig/ marked-1.1.0-edit/ -U2 | sed -r '/^index /d;s`^(diff --git a/)[^/]+/(.* b/)[^/]+/`\1\2`; s`^(---|\+\+\+) ([ab]/)[^/]+/`\1 \2`' > ../dev/copyparty/scripts/deps-docker/marked-ln.patch # git diff -U2 --no-index marked-1.1.0-orig/ marked-1.1.0-edit/ -U2 | sed -r '/^index /d;s`^(diff --git a/)[^/]+/(.* b/)[^/]+/`\1\2`; s`^(---|\+\+\+) ([ab]/)[^/]+/`\1 \2`' > ../dev/copyparty/scripts/deps-docker/marked-ln.patch

View file

@ -5,6 +5,7 @@ vend := $(self)/../../copyparty/web/deps
all: all:
cp -pv ../uncomment.py . cp -pv ../uncomment.py .
cp -pv ../strip_hints/a.py unhint.py
docker build -t build-copyparty-deps . docker build -t build-copyparty-deps .

View file

@ -41,7 +41,7 @@ hclean:
purge: purge:
-docker kill `docker ps -q` -docker kill `docker ps -q`
-docker rm `docker ps -qa` -docker rm `docker ps -qa`
-docker rmi `docker images -qa` -docker rmi `docker images -qa` -f
sh: sh:
@printf "\n\033[1;31mopening a shell in the most recently created docker image\033[0m\n" @printf "\n\033[1;31mopening a shell in the most recently created docker image\033[0m\n"

View file

@ -80,7 +80,7 @@ copyparty/web/deps/__init__.py,
copyparty/web/deps/busy.mp3, copyparty/web/deps/busy.mp3,
copyparty/web/deps/easymde.css, copyparty/web/deps/easymde.css,
copyparty/web/deps/easymde.js, copyparty/web/deps/easymde.js,
copyparty/web/deps/fuse.py, copyparty/web/deps/mfusepy.py,
copyparty/web/deps/marked.js, copyparty/web/deps/marked.js,
copyparty/web/deps/mini-fa.css, copyparty/web/deps/mini-fa.css,
copyparty/web/deps/mini-fa.woff, copyparty/web/deps/mini-fa.woff,