On Thu, 2024-12-19 at 15:57 +0100, Scott Kostyshak wrote:
> Is the problem that the object should not be a string?

Yes, it was expecting bytes.

> $ python3 --version
> Python 3.12.3

Do you know the Whac-A-Mole game? :-)

It was the same game that I was playing here.

I modernized the code a bit, changing from bytes to str as soon as
possible since that is now possible. I use kate that uses already some
plugins to reformat the code on save and so the patch it is a lot
larger...

Tell me if this works.

Best regards,
-- 
José Abílio
diff --git a/lib/scripts/lyxpak.py b/lib/scripts/lyxpak.py
index 38cd4c62b8..9a3fdd1b61 100755
--- a/lib/scripts/lyxpak.py
+++ b/lib/scripts/lyxpak.py
@@ -13,7 +13,10 @@
 # a gzip compressed tar archive on *nix. This can be controlled by command
 # line options, however.
 
-import gzip, os, re, sys
+import gzip
+import os
+import re
+import sys
 from io import BytesIO
 import subprocess
 
@@ -21,7 +24,7 @@ import subprocess
 # this case we revert to simply calling "python" from the path.
 PYTHON_BIN = sys.executable if sys.executable else "python"
 
-running_on_windows = (os.name == 'nt')
+running_on_windows = os.name == "nt"
 
 if running_on_windows:
     from shutil import copyfile
@@ -31,20 +34,24 @@ else:
     from getopt import getopt
 
 # Pre-compiled regular expressions.
-re_lyxfile = re.compile(br"\.lyx$")
-re_input = re.compile(b'^(.*)\\\\(input|include){(\\s*)(.+)(\\s*)}.*$')
-re_ertinput = re.compile(b'^(input|include)({)(\\s*)(.+)(\\s*)}.*$')
-re_package = re.compile(b'^(.*)\\\\(usepackage){(\\s*)(.+)(\\s*)}.*$')
-re_class = re.compile(b'^(\\\\)(textclass)(\\s+)(.+)\\s*$')
-re_norecur = re.compile(b'^(.*)\\\\(verbatiminput|lstinputlisting|includegraphics\\[*.*\\]*){(\\s*)(.+)(\\s*)}.*$')
-re_ertnorecur = re.compile(b'^(verbatiminput|lstinputlisting|includegraphics\\[*.*\\]*)({)(\\s*)(.+)(\\s*)}.*$')
-re_filename = re.compile(b'^(\\s*)(filename)(\\s+)(.+)\\s*$')
-re_options = re.compile(b'^(\\s*)options(\\s+)(.+)\\s*$')
-re_bibfiles = re.compile(b'^(\\s*)bibfiles(\\s+)(.+)\\s*$')
+re_lyxfile = re.compile(r"\.lyx$")
+re_input = re.compile("^(.*)\\\\(input|include){(\\s*)(.+)(\\s*)}.*$")
+re_ertinput = re.compile("^(input|include)({)(\\s*)(.+)(\\s*)}.*$")
+re_package = re.compile("^(.*)\\\\(usepackage){(\\s*)(.+)(\\s*)}.*$")
+re_class = re.compile("^(\\\\)(textclass)(\\s+)(.+)\\s*$")
+re_norecur = re.compile(
+    "^(.*)\\\\(verbatiminput|lstinputlisting|includegraphics\\[*.*\\]*){(\\s*)(.+)(\\s*)}.*$"
+)
+re_ertnorecur = re.compile(
+    "^(verbatiminput|lstinputlisting|includegraphics\\[*.*\\]*)({)(\\s*)(.+)(\\s*)}.*$"
+)
+re_filename = re.compile("^(\\s*)(filename)(\\s+)(.+)\\s*$")
+re_options = re.compile("^(\\s*)options(\\s+)(.+)\\s*$")
+re_bibfiles = re.compile("^(\\s*)bibfiles(\\s+)(.+)\\s*$")
 
 
 def usage(prog_name):
-    msg = '''
+    msg = """
 Usage: %s [-t] [-z] [-l path] [-o output_dir] file.lyx
 Options:
 -l: Path to lyx2lyx script
@@ -54,26 +61,20 @@ Options:
 By default, we create file.zip on Windows and file.tar.gz on *nix,
 with the file output to where file.lyx is, and we look for lyx2lyx
 in the known locations, querying LyX itself if necessary.
-'''
+"""
     return msg % prog_name
 
 
 def error(message):
-    sys.stderr.write(message + '\n')
+    sys.stderr.write(message + "\n")
     sys.exit(1)
 
 
-def tostr(message):
-    return message.decode(sys.getfilesystemencoding())
-
-
 def gzopen(file):
-    input = open(file.decode('utf-8'), 'rb')
-    magicnum = input.read(2)
-    input.close()
-    if magicnum == b"\x1f\x8b":
-        return gzip.open(file.decode('utf-8'))
-    return open(file.decode('utf-8'), 'rb')
+    with open(file, "rb") as f:
+        magicnum = f.read(2)
+
+    return gzip.open(file) if magicnum == b"\x1f\x8b" else open(file)
 
 
 def find_exe(candidates, extlist, path):
@@ -87,7 +88,7 @@ def find_exe(candidates, extlist, path):
 
 
 def abspath(name):
-    " Resolve symlinks and returns the absolute normalized name."
+    "Resolve symlinks and returns the absolute normalized name."
     newname = os.path.normpath(os.path.abspath(name))
     if not running_on_windows:
         newname = os.path.realpath(newname)
@@ -95,7 +96,7 @@ def abspath(name):
 
 
 def gather_files(curfile, incfiles, lyx2lyx):
-    " Recursively gather files."
+    "Recursively gather files."
     curdir = os.path.dirname(abspath(curfile))
     is_lyxfile = re_lyxfile.search(curfile)
 
@@ -106,35 +107,34 @@ def gather_files(curfile, incfiles, lyx2lyx):
             # code page. So, we resort to running lyx2lyx on a copy.
             tmp = NamedTemporaryFile(delete=False)
             tmp.close()
-            copyfile(curfile.decode('utf-8'), tmp.name)
+            copyfile(curfile, tmp.name)
             try:
                 l2l_stdout = subprocess.check_output([PYTHON_BIN, lyx2lyx, tmp.name])
             except subprocess.CalledProcessError:
-                error(f'{lyx2lyx} failed to convert "{tostr(curfile)}"')
+                error(f'{lyx2lyx} failed to convert "{curfile}"')
             os.unlink(tmp.name)
         else:
             try:
                 l2l_stdout = subprocess.check_output([PYTHON_BIN, lyx2lyx, curfile])
             except subprocess.CalledProcessError:
-                error(f'{lyx2lyx} failed to convert "{tostr(curfile)}"')
+                error(f'{lyx2lyx} failed to convert "{curfile}"')
         if l2l_stdout.startswith(b"\x1f\x8b"):
             l2l_stdout = gzip.GzipFile("", "rb", 0, BytesIO(l2l_stdout)).read()
         elif running_on_windows:
             # For some unknown reason, there can be a spurious '\r' in the line
             # separators, causing spurious empty lines when calling splitlines.
-            l2l_stdout = l2l_stdout.replace(b'\r\r\n', b'\r\n')
-        lines = l2l_stdout.splitlines()
+            l2l_stdout = l2l_stdout.replace(b"\r\r\n", b"\r\n")
+        lines = l2l_stdout.decode("utf-8").splitlines()
     else:
-        input = gzopen(curfile)
-        lines = input.readlines()
-        input.close()
+        with gzopen(curfile) as f:
+            lines = f.readlines()
 
     maybe_in_ert = False
     i = 0
     while i < len(lines):
         # Gather used files.
         recursive = True
-        extlist = [b'']
+        extlist = [""]
         match = re_filename.match(lines[i])
         if not match:
             if maybe_in_ert:
@@ -143,20 +143,20 @@ def gather_files(curfile, incfiles, lyx2lyx):
                 match = re_input.match(lines[i])
             if not match:
                 match = re_package.match(lines[i])
-                extlist = [b'.sty']
+                extlist = [".sty"]
                 if not match:
                     match = re_class.match(lines[i])
-                    extlist = [b'.cls']
+                    extlist = [".cls"]
                     if not match:
                         if maybe_in_ert:
                             match = re_ertnorecur.match(lines[i])
                         else:
                             match = re_norecur.match(lines[i])
-                        extlist = [b'', b'.eps', b'.pdf', b'.png', b'.jpg']
+                        extlist = ["", ".eps", ".pdf", ".png", ".jpg"]
                         recursive = False
-        maybe_in_ert = is_lyxfile and lines[i] == b"\\backslash"
+        maybe_in_ert = is_lyxfile and lines[i] == "\\backslash"
         if match:
-            file = match.group(4).strip(b'"')
+            file = match.group(4).strip('"')
             if not os.path.isabs(file):
                 file = os.path.join(curdir, file)
             file_exists = False
@@ -180,12 +180,12 @@ def gather_files(curfile, incfiles, lyx2lyx):
         # Gather bibtex *.bst files.
         match = re_options.match(lines[i])
         if match:
-            file = match.group(3).strip(b'"')
-            if file.startswith(b"bibtotoc,"):
+            file = match.group(3).strip('"')
+            if file.startswith("bibtotoc,"):
                 file = file[9:]
             ext = os.path.splitext(file)[-1]
-            if ext != b'.bst':
-                file = file + b'.bst'
+            if ext != ".bst":
+                file = file + ".bst"
             if not os.path.isabs(file):
                 file = os.path.join(curdir, file)
             if os.path.exists(file):
@@ -196,13 +196,13 @@ def gather_files(curfile, incfiles, lyx2lyx):
         # Gather bibtex *.bib files.
         match = re_bibfiles.match(lines[i])
         if match:
-            bibfiles = match.group(3).strip(b'"').split(b',')
+            bibfiles = match.group(3).strip('"').split(",")
             j = 0
             while j < len(bibfiles):
                 file = bibfiles[j]
                 ext = os.path.splitext(file)[-1]
-                if ext != b'.bib':
-                    file = file + b'.bib'
+                if ext != ".bib":
+                    file = file + ".bib"
                 if not os.path.isabs(file):
                     file = os.path.join(curdir, file)
                 if os.path.exists(file):
@@ -217,32 +217,34 @@ def gather_files(curfile, incfiles, lyx2lyx):
 
 
 def find_lyx2lyx(progloc, path):
-    " Find a usable version of the lyx2lyx script. "
+    "Find a usable version of the lyx2lyx script."
     # first we will see if the script is roughly where we are
     # i.e., we will assume we are in $SOMEDIR/scripts and look
     # for $SOMEDIR/lyx2lyx/lyx2lyx.
     ourpath = os.path.dirname(abspath(progloc))
     (upone, discard) = os.path.split(ourpath)
     if running_on_windows:
-        tryit = os.path.join(upone, b"lyx2lyx", b"lyx2lyx")
+        tryit = os.path.join(upone, "lyx2lyx", "lyx2lyx")
     else:
         tryit = os.path.join(upone, "lyx2lyx", "lyx2lyx")
     if os.access(tryit, os.X_OK):
         return tryit
 
     # now we will try to query LyX itself to find the path.
-    extlist = ['']
+    extlist = [""]
     if "PATHEXT" in os.environ:
         extlist = extlist + os.environ["PATHEXT"].split(os.pathsep)
     lyx_exe, full_path = find_exe(["lyxc", "lyx"], extlist, path)
     if lyx_exe is None:
-        error('Cannot find the LyX executable in the path.')
+        error("Cannot find the LyX executable in the path.")
     try:
-        cmd_stdout = subprocess.check_output([lyx_exe, '-version'], stderr=subprocess.STDOUT)
+        cmd_stdout = subprocess.check_output(
+            [lyx_exe, "-version"], stderr=subprocess.STDOUT
+        )
     except subprocess.CalledProcessError:
-        error('Cannot query LyX about the lyx2lyx script.')
-    re_msvc = re.compile(r'^(\s*)(Host type:)(\s+)(win32)$')
-    re_sysdir = re.compile(r'^(\s*)(LyX files dir:)(\s+)(\S+)$')
+        error("Cannot query LyX about the lyx2lyx script.")
+    re_msvc = re.compile(r"^(\s*)(Host type:)(\s+)(win32)$")
+    re_sysdir = re.compile(r"^(\s*)(LyX files dir:)(\s+)(\S+)$")
     lines = cmd_stdout.splitlines()
     for line in lines:
         match = re_msvc.match(line)
@@ -250,15 +252,15 @@ def find_lyx2lyx(progloc, path):
             # The LyX executable was built with MSVC, so the
             # "LyX files dir:" line is unusable
             basedir = os.path.dirname(os.path.dirname(full_path))
-            tryit = os.path.join(basedir, 'Resources', 'lyx2lyx', 'lyx2lyx')
+            tryit = os.path.join(basedir, "Resources", "lyx2lyx", "lyx2lyx")
             break
         match = re_sysdir.match(line)
         if match:
-            tryit = os.path.join(match.group(4), 'lyx2lyx', 'lyx2lyx')
+            tryit = os.path.join(match.group(4), "lyx2lyx", "lyx2lyx")
             break
 
     if not os.access(tryit, os.X_OK):
-        error('Unable to find the lyx2lyx script.')
+        error("Unable to find the lyx2lyx script.")
     return tryit
 
 
@@ -268,7 +270,7 @@ def main(args):
 
     try:
         if running_on_windows:
-            (options, argv) = getopt(args[1:], b"htzl:o:")
+            (options, argv) = getopt(args[1:], "htzl:o:")
         else:
             (options, argv) = getopt(args[1:], "htzl:o:")
     except:
@@ -282,7 +284,7 @@ def main(args):
     outdir = ""
     lyx2lyx = None
 
-    for (opt, param) in options:
+    for opt, param in options:
         if opt == "-h":
             print(usage(ourprog))
             sys.exit(0)
@@ -299,25 +301,25 @@ def main(args):
 
     lyxfile = argv[0]
     if not os.path.exists(lyxfile):
-        error('File "%s" not found.' % tostr(lyxfile))
+        error(f'File "{lyxfile}" not found.')
 
     # Check that it actually is a LyX document
-    input = gzopen(lyxfile)
-    line = input.readline()
-    input.close()
-    if not (line and line.startswith(b'#LyX')):
-        error('File "%s" is not a LyX document.' % tostr(lyxfile))
+    with gzopen(lyxfile) as f:
+        line = f.readline()
+
+    if not (line and line.startswith("#LyX")):
+        error(f'File "{lyxfile}" is not a LyX document.')
 
     if makezip:
         import zipfile
     else:
         import tarfile
 
-    ar_ext = b".tar.gz"
+    ar_ext = ".tar.gz"
     if makezip:
-        ar_ext = b".zip"
+        ar_ext = ".zip"
 
-    ar_name = re_lyxfile.sub(ar_ext, abspath(lyxfile)).decode('utf-8')
+    ar_name = re_lyxfile.sub(ar_ext, abspath(lyxfile))
     if outdir:
         ar_name = os.path.join(abspath(outdir), os.path.basename(ar_name))
 
@@ -332,7 +334,7 @@ def main(args):
     gather_files(lyxfile, incfiles, lyx2lyx)
 
     # Find the topmost dir common to all files
-    path_sep = os.path.sep.encode('utf-8')
+    path_sep = os.path.sep
     if len(incfiles) > 1:
         topdir = os.path.commonprefix(incfiles)
         # As os.path.commonprefix() works on a character by character basis,
@@ -344,32 +346,28 @@ def main(args):
     # Remove the prefix common to all paths in the list
     i = 0
     while i < len(incfiles):
-        incfiles[i] = incfiles[i].replace(topdir, b'', 1)
+        incfiles[i] = incfiles[i].replace(topdir, "", 1)
         i += 1
 
     # Remove duplicates and sort the list
     incfiles = list(set(incfiles))
     incfiles.sort()
 
-    if topdir != '':
+    if topdir != "":
         os.chdir(topdir)
 
     # Create the archive
-    try:
-        if makezip:
-            zip = zipfile.ZipFile(ar_name, "w", zipfile.ZIP_DEFLATED)
+    # try:
+    if makezip:
+        with zipfile.ZipFile(ar_name, "w", zipfile.ZIP_DEFLATED) as zip:
             for file in incfiles:
-                zip.write(file.decode('utf-8'))
-            zip.close()
-        else:
-            tar = tarfile.open(ar_name, "w:gz")
+                zip.write(file)
+    else:
+        with tarfile.open(ar_name, "w:gz") as tar:
             for file in incfiles:
-                tar.add(file.decode('utf-8'))
-            tar.close()
-    except:
-        error('Failed to create LyX archive "%s"' % ar_name)
+                tar.add(file)
 
-    print('LyX archive "%s" created successfully.' % ar_name)
+    print(f'LyX archive "{ar_name}" created successfully.')
     return 0
 
 
@@ -388,15 +386,18 @@ if __name__ == "__main__":
         # as all other paths are extracted from the document in utf-8 format.
         from ctypes import WINFUNCTYPE, windll, POINTER, byref, c_int
         from ctypes.wintypes import LPWSTR, LPCWSTR
+
         GetCommandLineW = WINFUNCTYPE(LPWSTR)(("GetCommandLineW", windll.kernel32))
-        CommandLineToArgvW = WINFUNCTYPE(POINTER(LPWSTR), LPCWSTR, POINTER(c_int))(("CommandLineToArgvW", windll.shell32))
+        CommandLineToArgvW = WINFUNCTYPE(POINTER(LPWSTR), LPCWSTR, POINTER(c_int))(
+            ("CommandLineToArgvW", windll.shell32)
+        )
         argc = c_int(0)
         argv_unicode = CommandLineToArgvW(GetCommandLineW(), byref(argc))
         # unicode_argv[0] is the Python interpreter, so skip that.
-        argv = [argv_unicode[i].encode('utf-8') for i in range(1, argc.value)]
+        argv = [argv_unicode[i].encode("utf-8") for i in range(1, argc.value)]
         # Also skip option arguments to the Python interpreter.
         while len(argv) > 0:
-            if not argv[0].startswith(b"-"):
+            if not argv[0].startswith("-"):
                 break
             argv = argv[1:]
         sys.argv = argv
-- 
lyx-devel mailing list
lyx-devel@lists.lyx.org
https://lists.lyx.org/mailman/listinfo/lyx-devel

Reply via email to