make linters happier

This commit is contained in:
ed 2023-11-30 17:33:07 +00:00
parent c9fd26255b
commit 8c52b88767
22 changed files with 116 additions and 100 deletions

View file

@ -207,7 +207,7 @@ def examples():
def main():
global NC, BY_PATH
global NC, BY_PATH # pylint: disable=global-statement
os.system("")
print()
@ -282,7 +282,8 @@ def main():
if ver == "corrupt":
die("{} database appears to be corrupt, sorry")
if ver < DB_VER1 or ver > DB_VER2:
iver = int(ver)
if iver < DB_VER1 or iver > DB_VER2:
m = f"{n} db is version {ver}, this tool only supports versions between {DB_VER1} and {DB_VER2}, please upgrade it with copyparty first"
die(m)

View file

@ -53,7 +53,13 @@ from urllib.parse import unquote_to_bytes as unquote
WINDOWS = sys.platform == "win32"
MACOS = platform.system() == "Darwin"
UTC = timezone.utc
info = log = dbg = None
def print(*args, **kwargs):
try:
builtins.print(*list(args), **kwargs)
except:
builtins.print(termsafe(" ".join(str(x) for x in args)), **kwargs)
print(
@ -65,6 +71,13 @@ print(
)
def null_log(msg):
pass
info = log = dbg = null_log
try:
from fuse import FUSE, FuseOSError, Operations
except:
@ -84,13 +97,6 @@ except:
raise
def print(*args, **kwargs):
try:
builtins.print(*list(args), **kwargs)
except:
builtins.print(termsafe(" ".join(str(x) for x in args)), **kwargs)
def termsafe(txt):
try:
return txt.encode(sys.stdout.encoding, "backslashreplace").decode(
@ -119,10 +125,6 @@ def fancy_log(msg):
print("{:10.6f} {} {}\n".format(time.time() % 900, rice_tid(), msg), end="")
def null_log(msg):
pass
def hexler(binary):
return binary.replace("\r", "\\r").replace("\n", "\\n")
return " ".join(["{}\033[36m{:02x}\033[0m".format(b, ord(b)) for b in binary])

View file

@ -105,8 +105,8 @@ class File(object):
# set by handshake
self.recheck = False # duplicate; redo handshake after all files done
self.ucids = [] # type: list[str] # chunks which need to be uploaded
self.wark = None # type: str
self.url = None # type: str
self.wark = "" # type: str
self.url = "" # type: str
self.nhs = 0
# set by upload
@ -223,6 +223,7 @@ class MTHash(object):
def hash_at(self, nch):
f = self.f
assert f
ofs = ofs0 = nch * self.csz
hashobj = hashlib.sha512()
chunk_sz = chunk_rem = min(self.csz, self.sz - ofs)
@ -463,7 +464,7 @@ def quotep(btxt):
if not PY2:
quot1 = quot1.encode("ascii")
return quot1.replace(b" ", b"+")
return quot1.replace(b" ", b"+") # type: ignore
# from copyparty/util.py
@ -500,7 +501,7 @@ def up2k_chunksize(filesize):
# mostly from copyparty/up2k.py
def get_hashlist(file, pcb, mth):
# type: (File, any, any) -> None
# type: (File, Any, Any) -> None
"""generates the up2k hashlist from file contents, inserts it into `file`"""
chunk_sz = up2k_chunksize(file.size)
@ -1116,7 +1117,7 @@ source file/folder selection uses rsync syntax, meaning that:
ap.add_argument("-v", action="store_true", help="verbose")
ap.add_argument("-a", metavar="PASSWORD", help="password or $filepath")
ap.add_argument("-s", action="store_true", help="file-search (disables upload)")
ap.add_argument("-x", type=unicode, metavar="REGEX", default="", help="skip file if filesystem-abspath matches REGEX, example: '.*/\.hist/.*'")
ap.add_argument("-x", type=unicode, metavar="REGEX", default="", help="skip file if filesystem-abspath matches REGEX, example: '.*/\\.hist/.*'")
ap.add_argument("--ok", action="store_true", help="continue even if some local files are inaccessible")
ap.add_argument("--version", action="store_true", help="show version and exit")

View file

@ -66,7 +66,7 @@ def main():
ofs = ln.find("{")
j = json.loads(ln[ofs:])
except:
pass
continue
w = j["wark"]
if db.execute("select w from up where w = ?", (w,)).fetchone():

View file

@ -23,7 +23,7 @@ if not PY2:
unicode: Callable[[Any], str] = str
else:
sys.dont_write_bytecode = True
unicode = unicode # noqa: F821 # pylint: disable=undefined-variable,self-assigning-variable
unicode = unicode # type: ignore
WINDOWS: Any = (
[int(x) for x in platform.version().split(".")]

View file

@ -143,9 +143,11 @@ def warn(msg: str) -> None:
lprint("\033[1mwarning:\033[0;33m {}\033[0m\n".format(msg))
def init_E(E: EnvParams) -> None:
def init_E(EE: EnvParams) -> None:
# __init__ runs 18 times when oxidized; do expensive stuff here
E = EE # pylint: disable=redefined-outer-name
def get_unixdir() -> str:
paths: list[tuple[Callable[..., Any], str]] = [
(os.environ.get, "XDG_CONFIG_HOME"),
@ -246,7 +248,7 @@ def get_srvname() -> str:
return ret
def get_fk_salt(cert_path) -> str:
def get_fk_salt() -> str:
fp = os.path.join(E.cfg, "fk-salt.txt")
try:
with open(fp, "rb") as f:
@ -320,6 +322,7 @@ def configure_ssl_ver(al: argparse.Namespace) -> None:
# oh man i love openssl
# check this out
# hold my beer
assert ssl
ptn = re.compile(r"^OP_NO_(TLS|SSL)v")
sslver = terse_sslver(al.ssl_ver).split(",")
flags = [k for k in ssl.__dict__ if ptn.match(k)]
@ -353,6 +356,7 @@ def configure_ssl_ver(al: argparse.Namespace) -> None:
def configure_ssl_ciphers(al: argparse.Namespace) -> None:
assert ssl
ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
if al.ssl_ver:
ctx.options &= ~al.ssl_flags_en
@ -432,9 +436,9 @@ def disable_quickedit() -> None:
if PY2:
wintypes.LPDWORD = ctypes.POINTER(wintypes.DWORD)
k32.GetStdHandle.errcheck = ecb
k32.GetConsoleMode.errcheck = ecb
k32.SetConsoleMode.errcheck = ecb
k32.GetStdHandle.errcheck = ecb # type: ignore
k32.GetConsoleMode.errcheck = ecb # type: ignore
k32.SetConsoleMode.errcheck = ecb # type: ignore
k32.GetConsoleMode.argtypes = (wintypes.HANDLE, wintypes.LPDWORD)
k32.SetConsoleMode.argtypes = (wintypes.HANDLE, wintypes.DWORD)
@ -1253,7 +1257,7 @@ def run_argparse(
cert_path = os.path.join(E.cfg, "cert.pem")
fk_salt = get_fk_salt(cert_path)
fk_salt = get_fk_salt()
ah_salt = get_ah_salt()
# alpine peaks at 5 threads for some reason,
@ -1269,6 +1273,7 @@ def run_argparse(
add_network(ap)
add_tls(ap, cert_path)
add_cert(ap, cert_path)
add_auth(ap)
add_qr(ap, tty)
add_zeroconf(ap)
add_zc_mdns(ap)

View file

@ -957,6 +957,7 @@ class AuthSrv(object):
err = ""
try:
self._l(ln, 5, "volume access config:")
assert vp
sk, sv = ln.split(":")
if re.sub("[rwmdgGha]", "", sk) or not sk:
err = "invalid accs permissions list; "
@ -974,6 +975,7 @@ class AuthSrv(object):
err = ""
try:
self._l(ln, 6, "volume-specific config:")
assert vp
zd = split_cfg_ln(ln)
fstr = ""
for sk, sv in zd.items():
@ -1184,12 +1186,13 @@ class AuthSrv(object):
vfs = VFS(self.log_func, mount[dst], dst, daxs[dst], mflags[dst])
continue
assert vfs # type: ignore
zv = vfs.add(mount[dst], dst)
zv.axs = daxs[dst]
zv.flags = mflags[dst]
zv.dbv = None
assert vfs
assert vfs # type: ignore
vfs.all_vols = {}
vfs.all_aps = []
vfs.all_vps = []

View file

@ -46,8 +46,8 @@ class BrokerMp(object):
self.num_workers = self.args.j or CORES
self.log("broker", "booting {} subprocesses".format(self.num_workers))
for n in range(1, self.num_workers + 1):
q_pend: queue.Queue[tuple[int, str, list[Any]]] = mp.Queue(1)
q_yield: queue.Queue[tuple[int, str, list[Any]]] = mp.Queue(64)
q_pend: queue.Queue[tuple[int, str, list[Any]]] = mp.Queue(1) # type: ignore
q_yield: queue.Queue[tuple[int, str, list[Any]]] = mp.Queue(64) # type: ignore
proc = MProcess(q_pend, q_yield, MpWorker, (q_pend, q_yield, self.args, n))
Daemon(self.collector, "mp-sink-{}".format(n), (proc,))

View file

@ -15,7 +15,7 @@ from pyftpdlib.handlers import FTPHandler
from pyftpdlib.ioloop import IOLoop
from pyftpdlib.servers import FTPServer
from .__init__ import ANYWIN, PY2, TYPE_CHECKING, E
from .__init__ import PY2, TYPE_CHECKING
from .authsrv import VFS
from .bos import bos
from .util import (
@ -88,8 +88,8 @@ class FtpAuth(DummyAuthorizer):
bans[ip] = bonk
try:
# only possible if multiprocessing disabled
self.hub.broker.httpsrv.bans[ip] = bonk
self.hub.broker.httpsrv.nban += 1
self.hub.broker.httpsrv.bans[ip] = bonk # type: ignore
self.hub.broker.httpsrv.nban += 1 # type: ignore
except:
pass

View file

@ -81,7 +81,7 @@ from .util import (
sendfile_py,
undot,
unescape_cookie,
unquote,
unquote, # type: ignore
unquotep,
vjoin,
vol_san,
@ -888,7 +888,11 @@ class HttpCli(object):
return self.tx_ico(self.vpath.split("/")[-1], exact=True)
if self.vpath.startswith(".cpr/ssdp"):
return self.conn.hsrv.ssdp.reply(self)
if self.conn.hsrv.ssdp:
return self.conn.hsrv.ssdp.reply(self)
else:
self.reply(b"ssdp is disabled in server config", 404)
return False
if self.vpath.startswith(".cpr/dd/") and self.args.mpmc:
if self.args.mpmc == ".":
@ -3309,7 +3313,7 @@ class HttpCli(object):
def setck(self) -> bool:
k, v = self.uparam["setck"].split("=", 1)
t = None if v == "" else 86400 * 299
t = 0 if v == "" else 86400 * 299
ck = gencookie(k, v, self.args.R, False, t)
self.out_headerlist.append(("Set-Cookie", ck))
self.reply(b"o7\n")

View file

@ -8,7 +8,7 @@ import re
from .__init__ import PY2
from .th_srv import HAVE_PIL, HAVE_PILF
from .util import BytesIO
from .util import BytesIO # type: ignore
class Ico(object):
@ -22,7 +22,7 @@ class Ico(object):
ext = bext.decode("utf-8")
zb = hashlib.sha1(bext).digest()[2:4]
if PY2:
zb = [ord(x) for x in zb]
zb = [ord(x) for x in zb] # type: ignore
c1 = colorsys.hsv_to_rgb(zb[0] / 256.0, 1, 0.3)
c2 = colorsys.hsv_to_rgb(zb[0] / 256.0, 0.8 if HAVE_PILF else 1, 1)
@ -91,20 +91,6 @@ class Ico(object):
img.save(buf, format="PNG", compress_level=1)
return "image/png", buf.getvalue()
elif False:
# 48s, too slow
import pyvips
h = int(192 * h / w)
w = 192
img = pyvips.Image.text(
ext, width=w, height=h, dpi=192, align=pyvips.Align.CENTRE
)
img = img.ifthenelse(ci[3:], ci[:3], blend=True)
# i = i.resize(3, kernel=pyvips.Kernel.NEAREST)
buf = img.write_to_buffer(".png[compression=1]")
return "image/png", buf
svg = """\
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" viewBox="0 0 100 {}" xmlns="http://www.w3.org/2000/svg"><g>

View file

@ -261,7 +261,8 @@ def parse_ffprobe(txt: str) -> tuple[dict[str, tuple[int, Any]], dict[str, list[
if ".resw" in ret and ".resh" in ret:
ret["res"] = "{}x{}".format(ret[".resw"], ret[".resh"])
zd = {k: (0, v) for k, v in ret.items()}
zero = int("0")
zd = {k: (zero, v) for k, v in ret.items()}
return zd, md

View file

@ -18,7 +18,7 @@ from .bos import bos
from .mtag import HAVE_FFMPEG, HAVE_FFPROBE, ffprobe
from .util import (
FFMPEG_URL,
BytesIO,
BytesIO, # type: ignore
Cooldown,
Daemon,
Pebkac,
@ -411,6 +411,7 @@ class ThumbSrv(object):
if c == crops[-1]:
raise
assert img # type: ignore
img.write_to_file(tpath, Q=40)
def conv_ffmpeg(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:

View file

@ -1285,8 +1285,8 @@ class Up2k(object):
db.t = time.time()
if not self.args.no_dhash:
db.c.execute("delete from dh where d = ?", (drd,))
db.c.execute("insert into dh values (?,?)", (drd, dhash))
db.c.execute("delete from dh where d = ?", (drd,)) # type: ignore
db.c.execute("insert into dh values (?,?)", (drd, dhash)) # type: ignore
if self.stop:
return -1
@ -1305,7 +1305,7 @@ class Up2k(object):
if n:
t = "forgetting {} shadowed autoindexed files in [{}] > [{}]"
self.log(t.format(n, top, sh_rd))
assert sh_erd
assert sh_erd # type: ignore
q = "delete from dh where (d = ? or d like ?||'%')"
db.c.execute(q, (sh_erd, sh_erd + "/"))
@ -2204,7 +2204,7 @@ class Up2k(object):
t = "native sqlite3 backup failed; using fallback method:\n"
self.log(t + min_ex())
finally:
c2.close()
c2.close() # type: ignore
db = cur.connection
cur.close()

View file

@ -115,6 +115,11 @@ if True: # pylint: disable=using-constant-test
import typing
from typing import Any, Generator, Optional, Pattern, Protocol, Union
try:
from typing import LiteralString
except:
pass
class RootLogger(Protocol):
def __call__(self, src: str, msg: str, c: Union[int, str] = 0) -> None:
return None
@ -144,15 +149,15 @@ if not PY2:
from urllib.parse import quote_from_bytes as quote
from urllib.parse import unquote_to_bytes as unquote
else:
from StringIO import StringIO as BytesIO
from urllib import quote # pylint: disable=no-name-in-module
from urllib import unquote # pylint: disable=no-name-in-module
from StringIO import StringIO as BytesIO # type: ignore
from urllib import quote # type: ignore # pylint: disable=no-name-in-module
from urllib import unquote # type: ignore # pylint: disable=no-name-in-module
try:
struct.unpack(b">i", b"idgi")
spack = struct.pack
sunpack = struct.unpack
spack = struct.pack # type: ignore
sunpack = struct.unpack # type: ignore
except:
def spack(fmt: bytes, *a: Any) -> bytes:
@ -378,6 +383,7 @@ def py_desc() -> str:
def _sqlite_ver() -> str:
assert sqlite3 # type: ignore
try:
co = sqlite3.connect(":memory:")
cur = co.cursor()
@ -1817,7 +1823,7 @@ def exclude_dotfiles(filepaths: list[str]) -> list[str]:
return [x for x in filepaths if not x.split("/")[-1].startswith(".")]
def odfusion(base: ODict[str, bool], oth: str) -> ODict[str, bool]:
def odfusion(base: Union[ODict[str, bool], ODict["LiteralString", bool]], oth: str) -> ODict[str, bool]:
# merge an "ordered set" (just a dict really) with another list of keys
words0 = [x for x in oth.split(",") if x]
words1 = [x for x in oth[1:].split(",") if x]
@ -1987,10 +1993,10 @@ else:
# moonrunes become \x3f with bytestrings,
# losing mojibake support is worth
def _not_actually_mbcs_enc(txt: str) -> bytes:
return txt
return txt # type: ignore
def _not_actually_mbcs_dec(txt: bytes) -> str:
return txt
return txt # type: ignore
fsenc = afsenc = sfsenc = _not_actually_mbcs_enc
fsdec = _not_actually_mbcs_dec
@ -2049,6 +2055,7 @@ def atomic_move(usrc: str, udst: str) -> None:
def get_df(abspath: str) -> tuple[Optional[int], Optional[int]]:
try:
# some fuses misbehave
assert ctypes
if ANYWIN:
bfree = ctypes.c_ulonglong(0)
ctypes.windll.kernel32.GetDiskFreeSpaceExW( # type: ignore
@ -2451,6 +2458,7 @@ def getalive(pids: list[int], pgid: int) -> list[int]:
alive.append(pid)
else:
# windows doesn't have pgroups; assume
assert psutil
psutil.Process(pid)
alive.append(pid)
except:
@ -2468,6 +2476,7 @@ def killtree(root: int) -> None:
pgid = 0
if HAVE_PSUTIL:
assert psutil
pids = [root]
parent = psutil.Process(root)
for child in parent.children(recursive=True):
@ -2864,7 +2873,7 @@ def loadpy(ap: str, hot: bool) -> Any:
if PY2:
mod = __import__(mname)
if hot:
reload(mod)
reload(mod) # type: ignore
else:
import importlib
@ -3007,6 +3016,7 @@ def termsize() -> tuple[int, int]:
def hidedir(dp) -> None:
if ANYWIN:
try:
assert ctypes
k32 = ctypes.WinDLL("kernel32")
attrs = k32.GetFileAttributesW(dp)
if attrs >= 0:

View file

@ -100,6 +100,10 @@ include_trailing_comma = true
[tool.bandit]
skips = ["B104", "B110", "B112"]
[tool.ruff]
line-length = 120
ignore = ["E402", "E722"]
# =====================================================================
[tool.pylint.MAIN]

View file

@ -1,16 +1,16 @@
#!/usr/bin/env python3
import itertools
import re
import sys
import time
import itertools
from . import util as tu
from .util import Cfg
from copyparty.authsrv import AuthSrv
from copyparty.httpcli import HttpCli
from . import util as tu
from .util import Cfg
atlas = ["%", "25", "2e", "2f", ".", "/"]

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import sys
import runpy
import sys
host = sys.argv[1]
sys.argv = sys.argv[:1] + sys.argv[2:]

View file

@ -4,9 +4,9 @@ from __future__ import print_function, unicode_literals
import re
import unittest
from xml.etree import ElementTree as ET
from copyparty.dxml import parse_xml, BadXML, mkenod, mktnod
from copyparty.dxml import BadXML, mkenod, mktnod, parse_xml
ET.register_namespace("D", "DAV:")

View file

@ -4,18 +4,17 @@ from __future__ import print_function, unicode_literals
import io
import os
import time
import shutil
import pprint
import shutil
import tarfile
import tempfile
import time
import unittest
from tests import util as tu
from tests.util import Cfg, eprint
from copyparty.authsrv import AuthSrv
from copyparty.httpcli import HttpCli
from tests import util as tu
from tests.util import Cfg, eprint
def hdr(query):

View file

@ -2,19 +2,18 @@
# coding: utf-8
from __future__ import print_function, unicode_literals
import os
import json
import os
import shutil
import tempfile
import unittest
from textwrap import dedent
from copyparty import util
from copyparty.authsrv import VFS, AuthSrv
from tests import util as tu
from tests.util import Cfg
from copyparty.authsrv import AuthSrv, VFS
from copyparty import util
class TestVFS(unittest.TestCase):
def setUp(self):

View file

@ -3,23 +3,23 @@
from __future__ import print_function, unicode_literals
import os
import re
import sys
import time
import shutil
import jinja2
import threading
import tempfile
import platform
import re
import shutil
import subprocess as sp
import sys
import tempfile
import threading
import time
from argparse import Namespace
import jinja2
WINDOWS = platform.system() == "Windows"
ANYWIN = WINDOWS or sys.platform in ["msys"]
MACOS = platform.system() == "Darwin"
J2_ENV = jinja2.Environment(loader=jinja2.BaseLoader)
J2_ENV = jinja2.Environment(loader=jinja2.BaseLoader) # type: ignore
J2_FILES = J2_ENV.from_string("{{ files|join('\n') }}\nJ2EOT")
@ -43,7 +43,7 @@ if MACOS:
from copyparty.__init__ import E
from copyparty.__main__ import init_E
from copyparty.util import Unrecv, FHC, Garda
from copyparty.util import FHC, Garda, Unrecv
init_E(E)
@ -83,8 +83,8 @@ def get_ramdisk():
for _ in range(10):
try:
_, _ = chkcmd(["diskutil", "eraseVolume", "HFS+", "cptd", devname])
with open("/Volumes/cptd/.metadata_never_index", "w") as f:
f.write("orz")
with open("/Volumes/cptd/.metadata_never_index", "wb") as f:
f.write(b"orz")
try:
shutil.rmtree("/Volumes/cptd/.fseventsd")
@ -99,10 +99,10 @@ def get_ramdisk():
raise Exception("ramdisk creation failed")
ret = os.path.join(tempfile.gettempdir(), "copyparty-test")
try:
if not os.path.isdir(ret):
os.mkdir(ret)
finally:
return subdir(ret)
return subdir(ret)
class Cfg(Namespace):
@ -156,10 +156,10 @@ class Cfg(Namespace):
class NullBroker(object):
def say(*args):
def say(self, *args):
pass
def ask(*args):
def ask(self, *args):
pass
@ -209,7 +209,7 @@ class VHttpSrv(object):
class VHttpConn(object):
def __init__(self, args, asrv, log, buf):
self.s = VSock(buf)
self.sr = Unrecv(self.s, None)
self.sr = Unrecv(self.s, None) # type: ignore
self.addr = ("127.0.0.1", "42069")
self.args = args
self.asrv = asrv