copyparty 1.15.0__py3-none-any.whl → 1.15.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- copyparty/__init__.py +1 -0
- copyparty/__main__.py +21 -12
- copyparty/__version__.py +2 -2
- copyparty/authsrv.py +84 -8
- copyparty/broker_mp.py +6 -2
- copyparty/broker_mpw.py +6 -2
- copyparty/broker_thr.py +5 -9
- copyparty/broker_util.py +13 -1
- copyparty/cfg.py +1 -0
- copyparty/fsutil.py +0 -3
- copyparty/httpcli.py +145 -70
- copyparty/httpconn.py +0 -1
- copyparty/httpsrv.py +3 -5
- copyparty/svchub.py +67 -5
- copyparty/th_srv.py +15 -7
- copyparty/u2idx.py +0 -3
- copyparty/up2k.py +223 -100
- copyparty/util.py +116 -63
- copyparty/web/browser.css.gz +0 -0
- copyparty/web/browser.js.gz +0 -0
- copyparty/web/splash.css.gz +0 -0
- copyparty/web/splash.html +12 -0
- copyparty/web/splash.js.gz +0 -0
- {copyparty-1.15.0.dist-info → copyparty-1.15.2.dist-info}/METADATA +15 -3
- {copyparty-1.15.0.dist-info → copyparty-1.15.2.dist-info}/RECORD +29 -29
- {copyparty-1.15.0.dist-info → copyparty-1.15.2.dist-info}/WHEEL +1 -1
- {copyparty-1.15.0.dist-info → copyparty-1.15.2.dist-info}/LICENSE +0 -0
- {copyparty-1.15.0.dist-info → copyparty-1.15.2.dist-info}/entry_points.txt +0 -0
- {copyparty-1.15.0.dist-info → copyparty-1.15.2.dist-info}/top_level.txt +0 -0
copyparty/__init__.py
CHANGED
copyparty/__main__.py
CHANGED
@@ -27,6 +27,7 @@ from .__init__ import (
|
|
27
27
|
EXE,
|
28
28
|
MACOS,
|
29
29
|
PY2,
|
30
|
+
PY36,
|
30
31
|
VT100,
|
31
32
|
WINDOWS,
|
32
33
|
E,
|
@@ -54,6 +55,7 @@ from .util import (
|
|
54
55
|
Daemon,
|
55
56
|
align_tab,
|
56
57
|
ansi_re,
|
58
|
+
b64enc,
|
57
59
|
dedent,
|
58
60
|
min_ex,
|
59
61
|
pybin,
|
@@ -198,7 +200,7 @@ def init_E(EE ) :
|
|
198
200
|
errs.append("Using [%s] instead" % (p,))
|
199
201
|
|
200
202
|
if errs:
|
201
|
-
|
203
|
+
warn(". ".join(errs))
|
202
204
|
|
203
205
|
return p # type: ignore
|
204
206
|
except Exception as ex:
|
@@ -228,7 +230,7 @@ def init_E(EE ) :
|
|
228
230
|
raise
|
229
231
|
|
230
232
|
|
231
|
-
def get_srvname() :
|
233
|
+
def get_srvname(verbose) :
|
232
234
|
try:
|
233
235
|
ret = unicode(socket.gethostname()).split(".")[0]
|
234
236
|
except:
|
@@ -238,7 +240,8 @@ def get_srvname() :
|
|
238
240
|
return ret
|
239
241
|
|
240
242
|
fp = os.path.join(E.cfg, "name.txt")
|
241
|
-
|
243
|
+
if verbose:
|
244
|
+
lprint("using hostname from {}\n".format(fp))
|
242
245
|
try:
|
243
246
|
with open(fp, "rb") as f:
|
244
247
|
ret = f.read().decode("utf-8", "replace").strip()
|
@@ -260,7 +263,7 @@ def get_fk_salt() :
|
|
260
263
|
with open(fp, "rb") as f:
|
261
264
|
ret = f.read().strip()
|
262
265
|
except:
|
263
|
-
ret =
|
266
|
+
ret = b64enc(os.urandom(18))
|
264
267
|
with open(fp, "wb") as f:
|
265
268
|
f.write(ret + b"\n")
|
266
269
|
|
@@ -273,7 +276,7 @@ def get_dk_salt() :
|
|
273
276
|
with open(fp, "rb") as f:
|
274
277
|
ret = f.read().strip()
|
275
278
|
except:
|
276
|
-
ret =
|
279
|
+
ret = b64enc(os.urandom(30))
|
277
280
|
with open(fp, "wb") as f:
|
278
281
|
f.write(ret + b"\n")
|
279
282
|
|
@@ -286,7 +289,7 @@ def get_ah_salt() :
|
|
286
289
|
with open(fp, "rb") as f:
|
287
290
|
ret = f.read().strip()
|
288
291
|
except:
|
289
|
-
ret =
|
292
|
+
ret = b64enc(os.urandom(18))
|
290
293
|
with open(fp, "wb") as f:
|
291
294
|
f.write(ret + b"\n")
|
292
295
|
|
@@ -344,7 +347,6 @@ def configure_ssl_ver(al ) :
|
|
344
347
|
# oh man i love openssl
|
345
348
|
# check this out
|
346
349
|
# hold my beer
|
347
|
-
assert ssl # type: ignore
|
348
350
|
ptn = re.compile(r"^OP_NO_(TLS|SSL)v")
|
349
351
|
sslver = terse_sslver(al.ssl_ver).split(",")
|
350
352
|
flags = [k for k in ssl.__dict__ if ptn.match(k)]
|
@@ -378,7 +380,6 @@ def configure_ssl_ver(al ) :
|
|
378
380
|
|
379
381
|
|
380
382
|
def configure_ssl_ciphers(al ) :
|
381
|
-
assert ssl # type: ignore
|
382
383
|
ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
383
384
|
if al.ssl_ver:
|
384
385
|
ctx.options &= ~al.ssl_flags_en
|
@@ -1061,6 +1062,7 @@ def add_cert(ap, cert_path):
|
|
1061
1062
|
|
1062
1063
|
|
1063
1064
|
def add_auth(ap):
|
1065
|
+
ses_db = os.path.join(E.cfg, "sessions.db")
|
1064
1066
|
ap2 = ap.add_argument_group('IdP / identity provider / user authentication options')
|
1065
1067
|
ap2.add_argument("--idp-h-usr", metavar="HN", type=u, default="", help="bypass the copyparty authentication checks and assume the request-header \033[33mHN\033[0m contains the username of the requesting user (for use with authentik/oauth/...)\n\033[1;31mWARNING:\033[0m if you enable this, make sure clients are unable to specify this header themselves; must be washed away and replaced by a reverse-proxy")
|
1066
1068
|
ap2.add_argument("--idp-h-grp", metavar="HN", type=u, default="", help="assume the request-header \033[33mHN\033[0m contains the groupname of the requesting user; can be referenced in config files for group-based access control")
|
@@ -1068,6 +1070,9 @@ def add_auth(ap):
|
|
1068
1070
|
ap2.add_argument("--idp-gsep", metavar="RE", type=u, default="|:;+,", help="if there are multiple groups in \033[33m--idp-h-grp\033[0m, they are separated by one of the characters in \033[33mRE\033[0m")
|
1069
1071
|
ap2.add_argument("--no-bauth", action="store_true", help="disable basic-authentication support; do not accept passwords from the 'Authenticate' header at all. NOTE: This breaks support for the android app")
|
1070
1072
|
ap2.add_argument("--bauth-last", action="store_true", help="keeps basic-authentication enabled, but only as a last-resort; if a cookie is also provided then the cookie wins")
|
1073
|
+
ap2.add_argument("--ses-db", metavar="PATH", type=u, default=ses_db, help="where to store the sessions database (if you run multiple copyparty instances, make sure they use different DBs)")
|
1074
|
+
ap2.add_argument("--ses-len", metavar="CHARS", type=int, default=20, help="session key length; default is 120 bits ((20//4)*4*6)")
|
1075
|
+
ap2.add_argument("--no-ses", action="store_true", help="disable sessions; use plaintext passwords in cookies")
|
1071
1076
|
|
1072
1077
|
|
1073
1078
|
def add_chpw(ap):
|
@@ -1220,6 +1225,7 @@ def add_optouts(ap):
|
|
1220
1225
|
ap2.add_argument("--no-zip", action="store_true", help="disable download as zip/tar")
|
1221
1226
|
ap2.add_argument("--no-tarcmp", action="store_true", help="disable download as compressed tar (?tar=gz, ?tar=bz2, ?tar=xz, ?tar=gz:9, ...)")
|
1222
1227
|
ap2.add_argument("--no-lifetime", action="store_true", help="do not allow clients (or server config) to schedule an upload to be deleted after a given time")
|
1228
|
+
ap2.add_argument("--no-up-list", action="store_true", help="don't show list of incoming files in controlpanel")
|
1223
1229
|
ap2.add_argument("--no-pipe", action="store_true", help="disable race-the-beam (lockstep download of files which are currently being uploaded) (volflag=nopipe)")
|
1224
1230
|
ap2.add_argument("--no-db-ip", action="store_true", help="do not write uploader IPs into the database")
|
1225
1231
|
|
@@ -1348,6 +1354,8 @@ def add_db_general(ap, hcores):
|
|
1348
1354
|
ap2.add_argument("--hist", metavar="PATH", type=u, default="", help="where to store volume data (db, thumbs); default is a folder named \".hist\" inside each volume (volflag=hist)")
|
1349
1355
|
ap2.add_argument("--no-hash", metavar="PTN", type=u, default="", help="regex: disable hashing of matching absolute-filesystem-paths during e2ds folder scans (volflag=nohash)")
|
1350
1356
|
ap2.add_argument("--no-idx", metavar="PTN", type=u, default=noidx, help="regex: disable indexing of matching absolute-filesystem-paths during e2ds folder scans (volflag=noidx)")
|
1357
|
+
ap2.add_argument("--no-dirsz", action="store_true", help="do not show total recursive size of folders in listings, show inode size instead; slightly faster (volflag=nodirsz)")
|
1358
|
+
ap2.add_argument("--re-dirsz", action="store_true", help="if the directory-sizes in the UI are bonkers, use this along with \033[33m-e2dsa\033[0m to rebuild the index from scratch")
|
1351
1359
|
ap2.add_argument("--no-dhash", action="store_true", help="disable rescan acceleration; do full database integrity check -- makes the db ~5%% smaller and bootup/rescans 3~10x slower")
|
1352
1360
|
ap2.add_argument("--re-dhash", action="store_true", help="force a cache rebuild on startup; enable this once if it gets out of sync (should never be necessary)")
|
1353
1361
|
ap2.add_argument("--no-forget", action="store_true", help="never forget indexed files, even when deleted from disk -- makes it impossible to ever upload the same file twice -- only useful for offloading uploads to a cloud service or something (volflag=noforget)")
|
@@ -1461,10 +1469,11 @@ def add_debug(ap):
|
|
1461
1469
|
|
1462
1470
|
|
1463
1471
|
def run_argparse(
|
1464
|
-
argv , formatter , retry , nc
|
1472
|
+
argv , formatter , retry , nc , verbose=True
|
1465
1473
|
) :
|
1466
1474
|
ap = argparse.ArgumentParser(
|
1467
1475
|
formatter_class=formatter,
|
1476
|
+
usage=argparse.SUPPRESS,
|
1468
1477
|
prog="copyparty",
|
1469
1478
|
description="http file sharing hub v{} ({})".format(S_VERSION, S_BUILD_DT),
|
1470
1479
|
)
|
@@ -1482,7 +1491,7 @@ def run_argparse(
|
|
1482
1491
|
|
1483
1492
|
tty = os.environ.get("TERM", "").lower() == "linux"
|
1484
1493
|
|
1485
|
-
srvname = get_srvname()
|
1494
|
+
srvname = get_srvname(verbose)
|
1486
1495
|
|
1487
1496
|
add_general(ap, nc, srvname)
|
1488
1497
|
add_network(ap)
|
@@ -1662,7 +1671,7 @@ def main(argv = None, rsrc = None) :
|
|
1662
1671
|
for fmtr in [RiceFormatter, RiceFormatter, Dodge11874, BasicDodge11874]:
|
1663
1672
|
try:
|
1664
1673
|
al = run_argparse(argv, fmtr, retry, nc)
|
1665
|
-
dal = run_argparse([], fmtr, retry, nc)
|
1674
|
+
dal = run_argparse([], fmtr, retry, nc, False)
|
1666
1675
|
break
|
1667
1676
|
except SystemExit:
|
1668
1677
|
raise
|
@@ -1746,7 +1755,7 @@ def main(argv = None, rsrc = None) :
|
|
1746
1755
|
print("error: python2 cannot --smb")
|
1747
1756
|
return
|
1748
1757
|
|
1749
|
-
if
|
1758
|
+
if not PY36:
|
1750
1759
|
al.no_scandir = True
|
1751
1760
|
|
1752
1761
|
if not hasattr(os, "sendfile"):
|
copyparty/__version__.py
CHANGED
copyparty/authsrv.py
CHANGED
@@ -833,8 +833,10 @@ class AuthSrv(object):
|
|
833
833
|
|
834
834
|
# fwd-decl
|
835
835
|
self.vfs = VFS(log_func, "", "", AXS(), {})
|
836
|
-
self.acct = {}
|
837
|
-
self.iacct = {}
|
836
|
+
self.acct = {} # uname->pw
|
837
|
+
self.iacct = {} # pw->uname
|
838
|
+
self.ases = {} # uname->session
|
839
|
+
self.sesa = {} # session->uname
|
838
840
|
self.defpw = {}
|
839
841
|
self.grps = {}
|
840
842
|
self.re_pwd = None
|
@@ -846,6 +848,7 @@ class AuthSrv(object):
|
|
846
848
|
self.idp_accs = {} # username->groupnames
|
847
849
|
self.idp_usr_gh = {} # username->group-header-value (cache)
|
848
850
|
|
851
|
+
self.hid_cache = {}
|
849
852
|
self.mutex = threading.Lock()
|
850
853
|
self.reload()
|
851
854
|
|
@@ -1522,7 +1525,7 @@ class AuthSrv(object):
|
|
1522
1525
|
if enshare:
|
1523
1526
|
import sqlite3
|
1524
1527
|
|
1525
|
-
shv = VFS(self.log_func, "", shr, AXS(), {
|
1528
|
+
shv = VFS(self.log_func, "", shr, AXS(), {})
|
1526
1529
|
|
1527
1530
|
db_path = self.args.shr_db
|
1528
1531
|
db = sqlite3.connect(db_path)
|
@@ -1541,8 +1544,8 @@ class AuthSrv(object):
|
|
1541
1544
|
if s_pw:
|
1542
1545
|
# gotta reuse the "account" for all shares with this pw,
|
1543
1546
|
# so do a light scramble as this appears in the web-ui
|
1544
|
-
|
1545
|
-
sun = "s_%s" % (
|
1547
|
+
zb = hashlib.sha512(s_pw.encode("utf-8")).digest()
|
1548
|
+
sun = "s_%s" % (ub64enc(zb)[4:16].decode("ascii"),)
|
1546
1549
|
acct[sun] = s_pw
|
1547
1550
|
else:
|
1548
1551
|
sun = "*"
|
@@ -1647,8 +1650,12 @@ class AuthSrv(object):
|
|
1647
1650
|
promote = []
|
1648
1651
|
demote = []
|
1649
1652
|
for vol in vfs.all_vols.values():
|
1650
|
-
|
1651
|
-
|
1653
|
+
hid = self.hid_cache.get(vol.realpath)
|
1654
|
+
if not hid:
|
1655
|
+
zb = hashlib.sha512(afsenc(vol.realpath)).digest()
|
1656
|
+
hid = base64.b32encode(zb).decode("ascii").lower()
|
1657
|
+
self.hid_cache[vol.realpath] = hid
|
1658
|
+
|
1652
1659
|
vflag = vol.flags.get("hist")
|
1653
1660
|
if vflag == "-":
|
1654
1661
|
pass
|
@@ -2174,8 +2181,11 @@ class AuthSrv(object):
|
|
2174
2181
|
self.grps = grps
|
2175
2182
|
self.iacct = {v: k for k, v in acct.items()}
|
2176
2183
|
|
2184
|
+
self.load_sessions()
|
2185
|
+
|
2177
2186
|
self.re_pwd = None
|
2178
2187
|
pwds = [re.escape(x) for x in self.iacct.keys()]
|
2188
|
+
pwds.extend(list(self.sesa))
|
2179
2189
|
if pwds:
|
2180
2190
|
if self.ah.on:
|
2181
2191
|
zs = r"(\[H\] pw:.*|[?&]pw=)([^&]+)"
|
@@ -2250,6 +2260,72 @@ class AuthSrv(object):
|
|
2250
2260
|
cur.close()
|
2251
2261
|
db.close()
|
2252
2262
|
|
2263
|
+
def load_sessions(self, quiet=False) :
|
2264
|
+
# mutex me
|
2265
|
+
if self.args.no_ses:
|
2266
|
+
self.ases = {}
|
2267
|
+
self.sesa = {}
|
2268
|
+
return
|
2269
|
+
|
2270
|
+
import sqlite3
|
2271
|
+
|
2272
|
+
ases = {}
|
2273
|
+
blen = (self.args.ses_len // 4) * 4 # 3 bytes in 4 chars
|
2274
|
+
blen = (blen * 3) // 4 # bytes needed for ses_len chars
|
2275
|
+
|
2276
|
+
db = sqlite3.connect(self.args.ses_db)
|
2277
|
+
cur = db.cursor()
|
2278
|
+
|
2279
|
+
for uname, sid in cur.execute("select un, si from us"):
|
2280
|
+
if uname in self.acct:
|
2281
|
+
ases[uname] = sid
|
2282
|
+
|
2283
|
+
n = []
|
2284
|
+
q = "insert into us values (?,?,?)"
|
2285
|
+
for uname in self.acct:
|
2286
|
+
if uname not in ases:
|
2287
|
+
sid = ub64enc(os.urandom(blen)).decode("ascii")
|
2288
|
+
cur.execute(q, (uname, sid, int(time.time())))
|
2289
|
+
ases[uname] = sid
|
2290
|
+
n.append(uname)
|
2291
|
+
|
2292
|
+
if n:
|
2293
|
+
db.commit()
|
2294
|
+
|
2295
|
+
cur.close()
|
2296
|
+
db.close()
|
2297
|
+
|
2298
|
+
self.ases = ases
|
2299
|
+
self.sesa = {v: k for k, v in ases.items()}
|
2300
|
+
if n and not quiet:
|
2301
|
+
t = ", ".join(n[:3])
|
2302
|
+
if len(n) > 3:
|
2303
|
+
t += "..."
|
2304
|
+
self.log("added %d new sessions (%s)" % (len(n), t))
|
2305
|
+
|
2306
|
+
def forget_session(self, broker , uname ) :
|
2307
|
+
with self.mutex:
|
2308
|
+
self._forget_session(uname)
|
2309
|
+
|
2310
|
+
if broker:
|
2311
|
+
broker.ask("_reload_sessions").get()
|
2312
|
+
|
2313
|
+
def _forget_session(self, uname ) :
|
2314
|
+
if self.args.no_ses:
|
2315
|
+
return
|
2316
|
+
|
2317
|
+
import sqlite3
|
2318
|
+
|
2319
|
+
db = sqlite3.connect(self.args.ses_db)
|
2320
|
+
cur = db.cursor()
|
2321
|
+
cur.execute("delete from us where un = ?", (uname,))
|
2322
|
+
db.commit()
|
2323
|
+
cur.close()
|
2324
|
+
db.close()
|
2325
|
+
|
2326
|
+
self.sesa.pop(self.ases.get(uname, ""), "")
|
2327
|
+
self.ases.pop(uname, "")
|
2328
|
+
|
2253
2329
|
def chpw(self, broker , uname, pw) :
|
2254
2330
|
if not self.args.chpw:
|
2255
2331
|
return False, "feature disabled in server config"
|
@@ -2269,7 +2345,7 @@ class AuthSrv(object):
|
|
2269
2345
|
if hpw == self.acct[uname]:
|
2270
2346
|
return False, "that's already your password my dude"
|
2271
2347
|
|
2272
|
-
if hpw in self.iacct:
|
2348
|
+
if hpw in self.iacct or hpw in self.sesa:
|
2273
2349
|
return False, "password is taken"
|
2274
2350
|
|
2275
2351
|
with self.mutex:
|
copyparty/broker_mp.py
CHANGED
@@ -9,7 +9,7 @@ import queue
|
|
9
9
|
|
10
10
|
from .__init__ import CORES, TYPE_CHECKING
|
11
11
|
from .broker_mpw import MpWorker
|
12
|
-
from .broker_util import ExceptionalQueue, try_exec
|
12
|
+
from .broker_util import ExceptionalQueue, NotExQueue, try_exec
|
13
13
|
from .util import Daemon, mp
|
14
14
|
|
15
15
|
if TYPE_CHECKING:
|
@@ -72,6 +72,10 @@ class BrokerMp(object):
|
|
72
72
|
for _, proc in enumerate(self.procs):
|
73
73
|
proc.q_pend.put((0, "reload", []))
|
74
74
|
|
75
|
+
def reload_sessions(self) :
|
76
|
+
for _, proc in enumerate(self.procs):
|
77
|
+
proc.q_pend.put((0, "reload_sessions", []))
|
78
|
+
|
75
79
|
def collector(self, proc ) :
|
76
80
|
"""receive message from hub in other process"""
|
77
81
|
while True:
|
@@ -100,7 +104,7 @@ class BrokerMp(object):
|
|
100
104
|
if retq_id:
|
101
105
|
proc.q_pend.put((retq_id, "retq", rv))
|
102
106
|
|
103
|
-
def ask(self, dest , *args )
|
107
|
+
def ask(self, dest , *args ) :
|
104
108
|
|
105
109
|
# new non-ipc invoking managed service in hub
|
106
110
|
obj = self.hub
|
copyparty/broker_mpw.py
CHANGED
@@ -11,7 +11,7 @@ import queue
|
|
11
11
|
|
12
12
|
from .__init__ import ANYWIN
|
13
13
|
from .authsrv import AuthSrv
|
14
|
-
from .broker_util import BrokerCli, ExceptionalQueue
|
14
|
+
from .broker_util import BrokerCli, ExceptionalQueue, NotExQueue
|
15
15
|
from .httpsrv import HttpSrv
|
16
16
|
from .util import FAKE_MP, Daemon, HMaccas
|
17
17
|
|
@@ -88,6 +88,10 @@ class MpWorker(BrokerCli):
|
|
88
88
|
self.asrv.reload()
|
89
89
|
self.logw("mpw.asrv reloaded")
|
90
90
|
|
91
|
+
elif dest == "reload_sessions":
|
92
|
+
with self.asrv.mutex:
|
93
|
+
self.asrv.load_sessions()
|
94
|
+
|
91
95
|
elif dest == "listen":
|
92
96
|
self.httpsrv.listen(args[0], args[1])
|
93
97
|
|
@@ -104,7 +108,7 @@ class MpWorker(BrokerCli):
|
|
104
108
|
else:
|
105
109
|
raise Exception("what is " + str(dest))
|
106
110
|
|
107
|
-
def ask(self, dest , *args )
|
111
|
+
def ask(self, dest , *args ) :
|
108
112
|
retq = ExceptionalQueue(1)
|
109
113
|
retq_id = id(retq)
|
110
114
|
with self.retpend_mutex:
|
copyparty/broker_thr.py
CHANGED
@@ -5,7 +5,7 @@ import os
|
|
5
5
|
import threading
|
6
6
|
|
7
7
|
from .__init__ import TYPE_CHECKING
|
8
|
-
from .broker_util import BrokerCli, ExceptionalQueue,
|
8
|
+
from .broker_util import BrokerCli, ExceptionalQueue, NotExQueue
|
9
9
|
from .httpsrv import HttpSrv
|
10
10
|
from .util import HMaccas
|
11
11
|
|
@@ -30,6 +30,7 @@ class BrokerThr(BrokerCli):
|
|
30
30
|
self.iphash = HMaccas(os.path.join(self.args.E.cfg, "iphash"), 8)
|
31
31
|
self.httpsrv = HttpSrv(self, None)
|
32
32
|
self.reload = self.noop
|
33
|
+
self.reload_sessions = self.noop
|
33
34
|
|
34
35
|
def shutdown(self) :
|
35
36
|
# self.log("broker", "shutting down")
|
@@ -38,19 +39,14 @@ class BrokerThr(BrokerCli):
|
|
38
39
|
def noop(self) :
|
39
40
|
pass
|
40
41
|
|
41
|
-
def ask(self, dest , *args )
|
42
|
+
def ask(self, dest , *args ) :
|
42
43
|
|
43
44
|
# new ipc invoking managed service in hub
|
44
45
|
obj = self.hub
|
45
46
|
for node in dest.split("."):
|
46
47
|
obj = getattr(obj, node)
|
47
48
|
|
48
|
-
|
49
|
-
|
50
|
-
# pretend we're broker_mp
|
51
|
-
retq = ExceptionalQueue(1)
|
52
|
-
retq.put(rv)
|
53
|
-
return retq
|
49
|
+
return NotExQueue(obj(*args)) # type: ignore
|
54
50
|
|
55
51
|
def say(self, dest , *args ) :
|
56
52
|
if dest == "listen":
|
@@ -66,4 +62,4 @@ class BrokerThr(BrokerCli):
|
|
66
62
|
for node in dest.split("."):
|
67
63
|
obj = getattr(obj, node)
|
68
64
|
|
69
|
-
|
65
|
+
obj(*args) # type: ignore
|
copyparty/broker_util.py
CHANGED
@@ -28,6 +28,18 @@ class ExceptionalQueue(Queue, object):
|
|
28
28
|
return rv
|
29
29
|
|
30
30
|
|
31
|
+
class NotExQueue(object):
|
32
|
+
"""
|
33
|
+
BrokerThr uses this instead of ExceptionalQueue; 7x faster
|
34
|
+
"""
|
35
|
+
|
36
|
+
def __init__(self, rv ) :
|
37
|
+
self.rv = rv
|
38
|
+
|
39
|
+
def get(self) :
|
40
|
+
return self.rv
|
41
|
+
|
42
|
+
|
31
43
|
class BrokerCli(object):
|
32
44
|
"""
|
33
45
|
helps mypy understand httpsrv.broker but still fails a few levels deeper,
|
@@ -43,7 +55,7 @@ class BrokerCli(object):
|
|
43
55
|
def __init__(self) :
|
44
56
|
pass
|
45
57
|
|
46
|
-
def ask(self, dest , *args )
|
58
|
+
def ask(self, dest , *args ) :
|
47
59
|
return ExceptionalQueue(1)
|
48
60
|
|
49
61
|
def say(self, dest , *args ) :
|
copyparty/cfg.py
CHANGED
copyparty/fsutil.py
CHANGED
@@ -113,7 +113,6 @@ class Fstab(object):
|
|
113
113
|
self.srctab = srctab
|
114
114
|
|
115
115
|
def relabel(self, path , nval ) :
|
116
|
-
assert self.tab
|
117
116
|
self.cache = {}
|
118
117
|
if ANYWIN:
|
119
118
|
path = self._winpath(path)
|
@@ -150,7 +149,6 @@ class Fstab(object):
|
|
150
149
|
self.log("failed to build tab:\n{}".format(min_ex()), 3)
|
151
150
|
self.build_fallback()
|
152
151
|
|
153
|
-
assert self.tab
|
154
152
|
ret = self.tab._find(path)[0]
|
155
153
|
if self.trusted or path == ret.vpath:
|
156
154
|
return ret.realpath.split("/")[0]
|
@@ -161,6 +159,5 @@ class Fstab(object):
|
|
161
159
|
if not self.tab:
|
162
160
|
self.build_fallback()
|
163
161
|
|
164
|
-
assert self.tab
|
165
162
|
ret = self.tab._find(path)[0]
|
166
163
|
return ret.realpath
|