convert: stringify `shlex` class argument
authorMatt Harbison <matt_harbison@yahoo.com>
Thu, 11 Jul 2024 21:16:45 -0400
changeset 51686 39033e7a6e0a
parent 51685 0eb515c7bec8
child 51687 1eab9e40c0c8
convert: stringify `shlex` class argument The documentation is handwavy, but typeshed says this should be `str`[1]. I'm not sure if this is the correct encoding (vs `fsencode` or "latin1" like the tokens returned by the proxy class). While we're here, we can add a few more type hints that would have caused pytype to flag the problem. [1] https://github.com/python/typeshed/blob/6a9b53e719a139c2d6b41cf265ed0990cf438192/stdlib/shlex.pyi#L51
hgext/convert/common.py
hgext/convert/filemap.py
--- a/hgext/convert/common.py	Thu Jul 11 20:54:06 2024 -0400
+++ b/hgext/convert/common.py	Thu Jul 11 21:16:45 2024 -0400
@@ -72,8 +72,10 @@
         return _encodeornone(self._l.get_token())
 
     @property
-    def infile(self):
-        return self._l.infile or b'<unknown>'
+    def infile(self) -> bytes:
+        if self._l.infile is not None:
+            return encoding.strtolocal(self._l.infile)
+        return b'<unknown>'
 
     @property
     def lineno(self) -> int:
@@ -82,7 +84,7 @@
 
 def shlexer(
     data=None,
-    filepath: Optional[str] = None,
+    filepath: Optional[bytes] = None,
     wordchars: Optional[bytes] = None,
     whitespace: Optional[bytes] = None,
 ):
@@ -94,7 +96,8 @@
                 b'shlexer only accepts data or filepath, not both'
             )
         data = data.decode('latin1')
-    l = shlex.shlex(data, infile=filepath, posix=True)
+    infile = encoding.strfromlocal(filepath) if filepath is not None else None
+    l = shlex.shlex(data, infile=infile, posix=True)
     if whitespace is not None:
         l.whitespace_split = True
         l.whitespace += whitespace.decode('latin1')
--- a/hgext/convert/filemap.py	Thu Jul 11 20:54:06 2024 -0400
+++ b/hgext/convert/filemap.py	Thu Jul 11 21:16:45 2024 -0400
@@ -76,7 +76,7 @@
     rename: MutableMapping[bytes, bytes]
     targetprefixes: Optional[Set[bytes]]
 
-    def __init__(self, ui: "uimod.ui", path=None) -> None:
+    def __init__(self, ui: "uimod.ui", path: Optional[bytes] = None) -> None:
         self.ui = ui
         self.include = {}
         self.exclude = {}
@@ -86,8 +86,7 @@
             if self.parse(path):
                 raise error.Abort(_(b'errors in filemap'))
 
-    # TODO: cmd==b'source' case breaks if ``path``is str
-    def parse(self, path) -> int:
+    def parse(self, path: Optional[bytes]) -> int:
         errs = 0
 
         def check(name: bytes, mapping, listname: bytes):
@@ -218,7 +217,9 @@
 
 
 class filemap_source(common.converter_source):
-    def __init__(self, ui: "uimod.ui", baseconverter, filemap) -> None:
+    def __init__(
+        self, ui: "uimod.ui", baseconverter, filemap: Optional[bytes]
+    ) -> None:
         super(filemap_source, self).__init__(ui, baseconverter.repotype)
         self.base = baseconverter
         self.filemapper = filemapper(ui, filemap)