diff --git a/README.md b/README.md index 662c7d94..379758bb 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,9 @@ summary: it works! you can use it! (but technically not even close to beta) # bugs -* probably, pls let me know +* Windows: python 3.7 and older cannot read tags with ffprobe, so use mutagen or upgrade +* Windows: python 2.7 cannot index non-ascii filenames with `-e2d` +* probably more, pls let me know # searching diff --git a/copyparty/__main__.py b/copyparty/__main__.py index cbb08822..ff5bc9d4 100644 --- a/copyparty/__main__.py +++ b/copyparty/__main__.py @@ -18,7 +18,7 @@ import locale import argparse from textwrap import dedent -from .__init__ import E, WINDOWS, VT100 +from .__init__ import E, WINDOWS, VT100, PY2 from .__version__ import S_VERSION, S_BUILD_DT, CODENAME from .svchub import SvcHub from .util import py_desc, align_tab @@ -53,6 +53,10 @@ class RiceFormatter(argparse.HelpFormatter): return "".join(indent + line + "\n" for line in text.splitlines()) +def warn(msg): + print("\033[1mwarning:\033[0;33m {}\033[0m\n".format(msg)) + + def ensure_locale(): for x in [ "en_US.UTF-8", @@ -300,7 +304,13 @@ def main(): if al.ciphers: configure_ssl_ciphers(al) else: - print("\033[33m ssl module does not exist; cannot enable https\033[0m\n") + warn("ssl module does not exist; cannot enable https") + + if PY2 and WINDOWS and al.e2d: + warn( + "windows py2 cannot do unicode filenames with -e2d\n" + + " (if you crash with codec errors then that is why)" + ) SvcHub(al).run() diff --git a/copyparty/mtag.py b/copyparty/mtag.py index abaa9583..1d668230 100644 --- a/copyparty/mtag.py +++ b/copyparty/mtag.py @@ -10,6 +10,9 @@ import subprocess as sp from .__init__ import PY2, WINDOWS from .util import fsenc, fsdec +if not PY2: + unicode = str + class MTag(object): def __init__(self, log_func, args): @@ -18,6 +21,7 @@ class MTag(object): self.prefer_mt = False mappings = args.mtm self.backend = "ffprobe" if args.no_mutagen else "mutagen" + or_ffprobe = " or ffprobe" if self.backend == "mutagen": self.get = self.get_mutagen @@ -32,7 +36,7 @@ class MTag(object): self.prefer_mt = True # about 20x slower if PY2: - cmd = ["ffprobe", "-version"] + cmd = [b"ffprobe", b"-version"] try: sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE) except: @@ -41,9 +45,15 @@ class MTag(object): if not shutil.which("ffprobe"): self.usable = False + if self.usable and WINDOWS and sys.version_info < (3, 8): + self.usable = False + or_ffprobe = " or python >= 3.8" + msg = "\033[31mfound ffprobe but your python is too old; need 3.8 or newer" + self.log(msg) + if not self.usable: - msg = "\033[31mneed mutagen or ffprobe to read media tags so please run this:\n {} -m pip install --user mutagen \033[0m" - self.log(msg.format(os.path.basename(sys.executable))) + msg = "\033[31mneed mutagen{} to read media tags so please run this:\n {} -m pip install --user mutagen \033[0m" + self.log(msg.format(or_ffprobe, os.path.basename(sys.executable))) return # https://picard-docs.musicbrainz.org/downloads/MusicBrainz_Picard_Tag_Map.html @@ -206,7 +216,7 @@ class MTag(object): return self.normalize_tags(ret, md) def get_ffprobe(self, abspath): - cmd = ["ffprobe", "-hide_banner", "--", fsenc(abspath)] + cmd = [b"ffprobe", b"-hide_banner", b"--", fsenc(abspath)] p = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE) r = p.communicate() txt = r[1].decode("utf-8", "replace") diff --git a/copyparty/up2k.py b/copyparty/up2k.py index 378c6a6e..bd0983fb 100644 --- a/copyparty/up2k.py +++ b/copyparty/up2k.py @@ -64,7 +64,6 @@ class Up2k(object): self.flags = {} self.cur = {} self.mtag = None - self.n_mtag_thr_alive = 0 self.n_mtag_tags_added = 0 self.mem_cur = None @@ -432,12 +431,8 @@ class Up2k(object): if self.mtag.prefer_mt and not self.args.no_mtag_mt: # mp.pool.ThreadPool and concurrent.futures.ThreadPoolExecutor # both do crazy runahead so lets reinvent another wheel - nw = os.cpu_count() - if not self.n_mtag_thr_alive: - msg = 'using {} cores for tag reader "{}"' - self.log(msg.format(nw, self.mtag.backend)) - - self.n_mtag_thr_alive = nw + nw = os.cpu_count() if hasattr(os, "cpu_count") else 4 + self.log("using {}x {}".format(nw, self.mtag.backend)) mpool = Queue(nw) for _ in range(nw): thr = threading.Thread(target=self._tag_thr, args=(mpool,)) @@ -474,11 +469,12 @@ class Up2k(object): last_write = time.time() n_buf = 0 - if self.n_mtag_thr_alive: - mpool.join() - for _ in range(self.n_mtag_thr_alive): + if mpool: + for _ in range(mpool.maxsize): mpool.put(None) + mpool.join() + c3.close() c2.close() @@ -488,7 +484,8 @@ class Up2k(object): while True: task = q.get() if not task: - break + q.task_done() + return try: write_cur, entags, wark, abspath = task @@ -497,11 +494,10 @@ class Up2k(object): n = self._tag_file(write_cur, entags, wark, abspath, tags) self.n_mtag_tags_added += n except: - with self.mutex: - self.n_mtag_thr_alive -= 1 - raise - finally: - q.task_done() + msg = "\033[33m{} failed to read tags from {}:\n{}" + self.log(msg.format(self.mtag.backend, abspath, traceback.format_exc())) + + q.task_done() def _tag_file(self, write_cur, entags, wark, abspath, tags=None): tags = tags or self.mtag.get(abspath) @@ -919,7 +915,7 @@ class Up2k(object): ret = [] with open(path, "rb", 512 * 1024) as f: while fsz > 0: - self.pp.msg = "{} MB".format(int(fsz / 1024 / 1024)) + self.pp.msg = "{} MB, {}".format(int(fsz / 1024 / 1024), path) hashobj = hashlib.sha512() rem = min(csz, fsz) fsz -= rem