Skip to content

Commit d5c9c8e

Browse files
committed
make it 5% faster
1 parent 7462298 commit d5c9c8e

File tree

8 files changed

+55
-43
lines changed

8 files changed

+55
-43
lines changed

copyparty/authsrv.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ def bubble_flags(self) -> None:
441441

442442
def _find(self, vpath: str) -> tuple["VFS", str]:
443443
"""return [vfs,remainder]"""
444-
if vpath == "":
444+
if not vpath:
445445
return self, ""
446446

447447
if "/" in vpath:
@@ -451,7 +451,7 @@ def _find(self, vpath: str) -> tuple["VFS", str]:
451451
rem = ""
452452

453453
if name in self.nodes:
454-
return self.nodes[name]._find(undot(rem))
454+
return self.nodes[name]._find(rem)
455455

456456
return self, vpath
457457

copyparty/fsutil.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
if True: # pylint: disable=using-constant-test
1515
from typing import Optional, Union
1616

17-
from .util import RootLogger
17+
from .util import RootLogger, undot
1818

1919

2020
class Fstab(object):
@@ -52,7 +52,7 @@ def get(self, path: str) -> str:
5252
self.log(msg.format(path, fs, min_ex()), 3)
5353
return fs
5454

55-
path = path.lstrip("/")
55+
path = undot(path)
5656
try:
5757
return self.cache[path]
5858
except:
@@ -124,7 +124,7 @@ def relabel(self, path: str, nval: str) -> None:
124124
if ANYWIN:
125125
path = self._winpath(path)
126126

127-
path = path.lstrip("/")
127+
path = undot(path)
128128
ptn = re.compile(r"^[^\\/]*")
129129
vn, rem = self.tab._find(path)
130130
if not self.trusted:

copyparty/httpcli.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import time
2020
import uuid
2121
from datetime import datetime
22-
from email.utils import formatdate, parsedate
22+
from email.utils import parsedate
2323
from operator import itemgetter
2424

2525
import jinja2 # typechk
@@ -54,6 +54,7 @@
5454
alltrace,
5555
atomic_move,
5656
exclude_dotfiles,
57+
formatdate,
5758
fsenc,
5859
gen_filekey,
5960
gen_filekey_dbg,
@@ -787,7 +788,7 @@ def send_headers(
787788

788789
# close if unknown length, otherwise take client's preference
789790
response.append("Connection: " + ("Keep-Alive" if self.keepalive else "Close"))
790-
response.append("Date: " + formatdate(usegmt=True))
791+
response.append("Date: " + formatdate())
791792

792793
# headers{} overrides anything set previously
793794
if headers:
@@ -811,9 +812,9 @@ def send_headers(
811812
self.cbonk(self.conn.hsrv.gmal, zs, "cc_hdr", "Cc in out-hdr")
812813
raise Pebkac(999)
813814

815+
response.append("\r\n")
814816
try:
815-
# best practice to separate headers and body into different packets
816-
self.s.sendall("\r\n".join(response).encode("utf-8") + b"\r\n\r\n")
817+
self.s.sendall("\r\n".join(response).encode("utf-8"))
817818
except:
818819
raise Pebkac(400, "client d/c while replying headers")
819820

@@ -1146,7 +1147,7 @@ def handle_get(self) -> bool:
11461147
return self.tx_mounts()
11471148

11481149
# conditional redirect to single volumes
1149-
if self.vpath == "" and not self.ouparam:
1150+
if not self.vpath and not self.ouparam:
11501151
nread = len(self.rvol)
11511152
nwrite = len(self.wvol)
11521153
if nread + nwrite == 1 or (self.rvol == self.wvol and nread == 1):
@@ -1305,7 +1306,7 @@ def handle_propfind(self) -> bool:
13051306

13061307
pvs: dict[str, str] = {
13071308
"displayname": html_escape(rp.split("/")[-1]),
1308-
"getlastmodified": formatdate(mtime, usegmt=True),
1309+
"getlastmodified": formatdate(mtime),
13091310
"resourcetype": '<D:collection xmlns:D="DAV:"/>' if isdir else "",
13101311
"supportedlock": '<D:lockentry xmlns:D="DAV:"><D:lockscope><D:exclusive/></D:lockscope><D:locktype><D:write/></D:locktype></D:lockentry>',
13111312
}
@@ -2952,7 +2953,7 @@ def handle_text_upload(self) -> bool:
29522953
return True
29532954

29542955
def _chk_lastmod(self, file_ts: int) -> tuple[str, bool]:
2955-
file_lastmod = formatdate(file_ts, usegmt=True)
2956+
file_lastmod = formatdate(file_ts)
29562957
cli_lastmod = self.headers.get("if-modified-since")
29572958
if cli_lastmod:
29582959
try:
@@ -3034,8 +3035,8 @@ def _add_logues(
30343035
for n, fn in enumerate([".prologue.html", ".epilogue.html"]):
30353036
if lnames is not None and fn not in lnames:
30363037
continue
3037-
fn = os.path.join(abspath, fn)
3038-
if bos.path.exists(fn):
3038+
fn = "%s/%s" % (abspath, fn)
3039+
if bos.path.isfile(fn):
30393040
with open(fsenc(fn), "rb") as f:
30403041
logues[n] = f.read().decode("utf-8")
30413042
if "exp" in vn.flags:
@@ -3053,7 +3054,7 @@ def _add_logues(
30533054
fns = []
30543055

30553056
for fn in fns:
3056-
fn = os.path.join(abspath, fn)
3057+
fn = "%s/%s" % (abspath, fn)
30573058
if bos.path.isfile(fn):
30583059
with open(fsenc(fn), "rb") as f:
30593060
readme = f.read().decode("utf-8")
@@ -3588,7 +3589,7 @@ def tx_svg(self, txt: str, small: bool = False) -> bool:
35883589
# (useragent-sniffing kinshi due to caching proxies)
35893590
mime, ico = self.ico.get(txt, not small, "raster" in self.uparam)
35903591

3591-
lm = formatdate(self.E.t0, usegmt=True)
3592+
lm = formatdate(self.E.t0)
35923593
self.reply(ico, mime=mime, headers={"Last-Modified": lm})
35933594
return True
35943595

copyparty/ssdp.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
import re
66
import select
77
import socket
8-
from email.utils import formatdate
8+
import time
99

1010
from .__init__ import TYPE_CHECKING
1111
from .multicast import MC_Sck, MCast
12-
from .util import CachedSet, html_escape, min_ex
12+
from .util import CachedSet, formatdate, html_escape, min_ex
1313

1414
if TYPE_CHECKING:
1515
from .broker_util import BrokerCli
@@ -229,7 +229,7 @@ def eat(self, buf: bytes, addr: tuple[str, int]) -> None:
229229
230230
"""
231231
v4 = srv.ip.replace("::ffff:", "")
232-
zs = zs.format(formatdate(usegmt=True), v4, srv.hport, self.args.zsid)
232+
zs = zs.format(formatdate(), v4, srv.hport, self.args.zsid)
233233
zb = zs[1:].replace("\n", "\r\n").encode("utf-8", "replace")
234234
srv.sck.sendto(zb, addr[:2])
235235

copyparty/szip.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,7 @@ def dostime2unix(buf: bytes) -> int:
3737

3838

3939
def unixtime2dos(ts: int) -> bytes:
40-
tt = time.gmtime(ts + 1)
41-
dy, dm, dd, th, tm, ts = list(tt)[:6]
42-
40+
dy, dm, dd, th, tm, ts, _, _, _ = time.gmtime(ts + 1)
4341
bd = ((dy - 1980) << 9) + (dm << 5) + dd
4442
bt = (th << 11) + (tm << 5) + ts // 2
4543
try:

copyparty/tftpd.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def __init__(self, **attr):
3636
from .__init__ import EXE, PY2, TYPE_CHECKING
3737
from .authsrv import VFS
3838
from .bos import bos
39-
from .util import BytesIO, Daemon, ODict, exclude_dotfiles, min_ex, runhook, undot
39+
from .util import UTC, BytesIO, Daemon, ODict, exclude_dotfiles, min_ex, runhook, undot
4040

4141
if True: # pylint: disable=using-constant-test
4242
from typing import Any, Union
@@ -262,7 +262,7 @@ def _ls(self, vpath: str, raddress: str, rport: int, force=False) -> Any:
262262
dirs1 = [(v.st_mtime, v.st_size, k + "/") for k, v in vfs_ls if k in dnames]
263263
fils1 = [(v.st_mtime, v.st_size, k) for k, v in vfs_ls if k not in dnames]
264264
real1 = dirs1 + fils1
265-
realt = [(datetime.fromtimestamp(mt), sz, fn) for mt, sz, fn in real1]
265+
realt = [(datetime.fromtimestamp(mt, UTC), sz, fn) for mt, sz, fn in real1]
266266
reals = [
267267
(
268268
"%04d-%02d-%02d %02d:%02d:%02d"

copyparty/util.py

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import time
2727
import traceback
2828
from collections import Counter
29-
from email.utils import formatdate
3029

3130
from ipaddress import IPv4Address, IPv4Network, IPv6Address, IPv6Network
3231
from queue import Queue
@@ -1821,10 +1820,21 @@ def gen_filekey_dbg(
18211820
return ret
18221821

18231822

1823+
WKDAYS = "Mon Tue Wed Thu Fri Sat Sun".split()
1824+
MONTHS = "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split()
1825+
RFC2822 = "%s, %02d %s %04d %02d:%02d:%02d GMT"
1826+
1827+
1828+
def formatdate(ts: Optional[int] = None) -> str:
1829+
# gmtime ~= datetime.fromtimestamp(ts, UTC).timetuple()
1830+
y, mo, d, h, mi, s, wd, _, _ = time.gmtime(ts)
1831+
return RFC2822 % (WKDAYS[wd], d, MONTHS[mo - 1], y, h, mi, s)
1832+
1833+
18241834
def gencookie(k: str, v: str, r: str, tls: bool, dur: int = 0, txt: str = "") -> str:
18251835
v = v.replace("%", "%25").replace(";", "%3B")
18261836
if dur:
1827-
exp = formatdate(time.time() + dur, usegmt=True)
1837+
exp = formatdate(time.time() + dur)
18281838
else:
18291839
exp = "Fri, 15 Aug 1997 01:00:00 GMT"
18301840

@@ -1839,12 +1849,10 @@ def humansize(sz: float, terse: bool = False) -> str:
18391849

18401850
sz /= 1024.0
18411851

1842-
ret = " ".join([str(sz)[:4].rstrip("."), unit])
1843-
1844-
if not terse:
1845-
return ret
1846-
1847-
return ret.replace("iB", "").replace(" ", "")
1852+
if terse:
1853+
return "%s%s" % (str(sz)[:4].rstrip("."), unit[:1])
1854+
else:
1855+
return "%s %s" % (str(sz)[:4].rstrip("."), unit)
18481856

18491857

18501858
def unhumanize(sz: str) -> int:
@@ -1896,7 +1904,7 @@ def uncyg(path: str) -> str:
18961904
def undot(path: str) -> str:
18971905
ret: list[str] = []
18981906
for node in path.split("/"):
1899-
if node in ["", "."]:
1907+
if node == "." or not node:
19001908
continue
19011909

19021910
if node == "..":
@@ -2709,30 +2717,30 @@ def rmdirs_up(top: str, stop: str) -> tuple[list[str], list[str]]:
27092717

27102718
def unescape_cookie(orig: str) -> str:
27112719
# mw=idk; doot=qwe%2Crty%3Basd+fgh%2Bjkl%25zxc%26vbn # qwe,rty;asd fgh+jkl%zxc&vbn
2712-
ret = ""
2720+
ret = []
27132721
esc = ""
27142722
for ch in orig:
27152723
if ch == "%":
2716-
if len(esc) > 0:
2717-
ret += esc
2724+
if esc:
2725+
ret.append(esc)
27182726
esc = ch
27192727

2720-
elif len(esc) > 0:
2728+
elif esc:
27212729
esc += ch
27222730
if len(esc) == 3:
27232731
try:
2724-
ret += chr(int(esc[1:], 16))
2732+
ret.append(chr(int(esc[1:], 16)))
27252733
except:
2726-
ret += esc
2734+
ret.append(esc)
27272735
esc = ""
27282736

27292737
else:
2730-
ret += ch
2738+
ret.append(ch)
27312739

2732-
if len(esc) > 0:
2733-
ret += esc
2740+
if esc:
2741+
ret.append(esc)
27342742

2735-
return ret
2743+
return "".join(ret)
27362744

27372745

27382746
def guess_mime(url: str, fallback: str = "application/octet-stream") -> str:

tests/test_httpcli.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,11 @@ def test(self):
168168
h, ret = self.put(url)
169169
res = h.startswith("HTTP/1.1 201 ")
170170
self.assertEqual(res, wok)
171+
if wok:
172+
vp = h.split("\nLocation: http://a:1/")[1].split("\r")[0]
173+
vn, rem = self.asrv.vfs.get(vp, "*", False, False)
174+
ap = os.path.join(vn.realpath, rem)
175+
os.unlink(ap)
171176

172177
def can_rw(self, fp):
173178
# lowest non-neutral folder declares permissions

0 commit comments

Comments
 (0)