Patchwork [1,of,3] py3: make a bytes version of getopt.getopt()

login
register
mail settings
Submitter Pulkit Goyal
Date Dec. 9, 2016, 11:40 p.m.
Message ID <4b57889d58056f95c58f.1481326825@pulkit-goyal>
Download mbox | patch
Permalink /patch/17887/
State Accepted
Headers show

Comments

Pulkit Goyal - Dec. 9, 2016, 11:40 p.m.
# HG changeset patch
# User Pulkit Goyal <7895pulkit@gmail.com>
# Date 1480986396 -19800
#      Tue Dec 06 06:36:36 2016 +0530
# Node ID 4b57889d58056f95c58f2379836437a65950424c
# Parent  a2b053b8d31aa01b1dcae2d3001b060ff59e8a68
py3: make a bytes version of getopt.getopt()

getopt.getopt() deals with unicodes on Python 3 internally and if bytes
arguments are passed, then it will return TypeError. So we have now
pycompat.getoptb() which takes bytes arguments, convert them to unicode, call
getopt.getopt() and then convert the returned value back to bytes and then
return those value.
All the instances of getopt.getopt() are replaced with pycompat.getoptb().
Pulkit Goyal - Dec. 9, 2016, 11:44 p.m.
The latest one is V5, I missed adding the flag.

On Sat, Dec 10, 2016 at 5:10 AM, Pulkit Goyal <7895pulkit@gmail.com> wrote:
> # HG changeset patch
> # User Pulkit Goyal <7895pulkit@gmail.com>
> # Date 1480986396 -19800
> #      Tue Dec 06 06:36:36 2016 +0530
> # Node ID 4b57889d58056f95c58f2379836437a65950424c
> # Parent  a2b053b8d31aa01b1dcae2d3001b060ff59e8a68
> py3: make a bytes version of getopt.getopt()
>
> getopt.getopt() deals with unicodes on Python 3 internally and if bytes
> arguments are passed, then it will return TypeError. So we have now
> pycompat.getoptb() which takes bytes arguments, convert them to unicode, call
> getopt.getopt() and then convert the returned value back to bytes and then
> return those value.
> All the instances of getopt.getopt() are replaced with pycompat.getoptb().
>
> diff -r a2b053b8d31a -r 4b57889d5805 mercurial/fancyopts.py
> --- a/mercurial/fancyopts.py    Tue Dec 06 11:44:49 2016 +0000
> +++ b/mercurial/fancyopts.py    Tue Dec 06 06:36:36 2016 +0530
> @@ -7,10 +7,11 @@
>
>  from __future__ import absolute_import
>
> -import getopt
> -
>  from .i18n import _
> -from . import error
> +from . import (
> +    error,
> +    pycompat,
> +)
>
>  # Set of flags to not apply boolean negation logic on
>  nevernegate = set([
> @@ -34,13 +35,14 @@
>          stopindex = args.index('--')
>          extraargs = args[stopindex + 1:]
>          args = args[:stopindex]
> -    opts, parseargs = getopt.getopt(args, options, longoptions)
> +    opts, parseargs = pycompat.getoptb(args, options, longoptions)
>      args = []
>      while parseargs:
>          arg = parseargs.pop(0)
>          if arg and arg[0] == '-' and len(arg) > 1:
>              parseargs.insert(0, arg)
> -            topts, newparseargs = getopt.getopt(parseargs, options, longoptions)
> +            topts, newparseargs = pycompat.getoptb(parseargs,\
> +                                            options, longoptions)
>              opts = opts + topts
>              parseargs = newparseargs
>          else:
> @@ -125,7 +127,7 @@
>      if gnu:
>          parse = gnugetopt
>      else:
> -        parse = getopt.getopt
> +        parse = pycompat.getoptb
>      opts, args = parse(args, shortlist, namelist)
>
>      # transfer result to state
> diff -r a2b053b8d31a -r 4b57889d5805 mercurial/pycompat.py
> --- a/mercurial/pycompat.py     Tue Dec 06 11:44:49 2016 +0000
> +++ b/mercurial/pycompat.py     Tue Dec 06 06:36:36 2016 +0530
> @@ -10,6 +10,7 @@
>
>  from __future__ import absolute_import
>
> +import getopt
>  import os
>  import sys
>
> @@ -87,6 +88,19 @@
>      setattr = _wrapattrfunc(builtins.setattr)
>      xrange = builtins.range
>
> +    # getopt.getopt() on Python 3 deals with unicodes internally so we cannot
> +    # pass bytes there. Passing unicodes will result in unicodes as return
> +    # values which we need to convert again to bytes.
> +    def getoptb(args, shortlist, namelist):
> +        args = [a.decode('latin-1') for a in args]
> +        shortlist = shortlist.decode('latin-1')
> +        namelist = [a.decode('latin-1') for a in namelist]
> +        opts, args = getopt.getopt(args, shortlist, namelist)
> +        opts = [(a[0].enocde('latin-1'), a[1].enocde('latin-1'))
> +                            for a in opts]
> +        args = [a.encode('latin-1') for a in args]
> +        return opts, args
> +
>  else:
>      def sysstr(s):
>          return s
> @@ -106,6 +120,9 @@
>      def fsdecode(filename):
>          return filename
>
> +    def getoptb(args, shortlist, namelist):
> +        return getopt.getopt(args, shortlist, namelist)
> +
>      osname = os.name
>      ospathsep = os.pathsep
>      ossep = os.sep
> diff -r a2b053b8d31a -r 4b57889d5805 mercurial/statprof.py
> --- a/mercurial/statprof.py     Tue Dec 06 11:44:49 2016 +0000
> +++ b/mercurial/statprof.py     Tue Dec 06 06:36:36 2016 +0530
> @@ -116,6 +116,10 @@
>  import threading
>  import time
>
> +from . import (
> +    pycompat,
> +)
> +
>  defaultdict = collections.defaultdict
>  contextmanager = contextlib.contextmanager
>
> @@ -771,7 +775,7 @@
>
>      # process options
>      try:
> -        opts, args = getopt.getopt(sys.argv[optstart:], "hl:f:o:p:",
> +        opts, args = pycompat.getoptb(sys.argv[optstart:], "hl:f:o:p:",
>                                     ["help", "limit=", "file=", "output-file=", "script-path="])
>      except getopt.error as msg:
>          print(msg)
Yuya Nishihara - Dec. 11, 2016, 1:35 p.m.
On Sat, 10 Dec 2016 05:10:25 +0530, Pulkit Goyal wrote:
> # HG changeset patch
> # User Pulkit Goyal <7895pulkit@gmail.com>
> # Date 1480986396 -19800
> #      Tue Dec 06 06:36:36 2016 +0530
> # Node ID 4b57889d58056f95c58f2379836437a65950424c
> # Parent  a2b053b8d31aa01b1dcae2d3001b060ff59e8a68
> py3: make a bytes version of getopt.getopt()

Queued this, thanks.

> --- a/mercurial/pycompat.py	Tue Dec 06 11:44:49 2016 +0000
> +++ b/mercurial/pycompat.py	Tue Dec 06 06:36:36 2016 +0530
> @@ -10,6 +10,7 @@
>  
>  from __future__ import absolute_import
>  
> +import getopt
>  import os
>  import sys
>  
> @@ -87,6 +88,19 @@
>      setattr = _wrapattrfunc(builtins.setattr)
>      xrange = builtins.range
>  
> +    # getopt.getopt() on Python 3 deals with unicodes internally so we cannot
> +    # pass bytes there. Passing unicodes will result in unicodes as return
> +    # values which we need to convert again to bytes.
> +    def getoptb(args, shortlist, namelist):
> +        args = [a.decode('latin-1') for a in args]
> +        shortlist = shortlist.decode('latin-1')
> +        namelist = [a.decode('latin-1') for a in namelist]
> +        opts, args = getopt.getopt(args, shortlist, namelist)
> +        opts = [(a[0].enocde('latin-1'), a[1].enocde('latin-1'))
> +                            for a in opts]

Fixed typo in flight: s/enocde/encode/.
Pulkit Goyal - Dec. 11, 2016, 2:47 p.m.
On Sun, Dec 11, 2016 at 7:05 PM, Yuya Nishihara <yuya@tcha.org> wrote:
> On Sat, 10 Dec 2016 05:10:25 +0530, Pulkit Goyal wrote:
>> # HG changeset patch
>> # User Pulkit Goyal <7895pulkit@gmail.com>
>> # Date 1480986396 -19800
>> #      Tue Dec 06 06:36:36 2016 +0530
>> # Node ID 4b57889d58056f95c58f2379836437a65950424c
>> # Parent  a2b053b8d31aa01b1dcae2d3001b060ff59e8a68
>> py3: make a bytes version of getopt.getopt()
>
> Queued this, thanks.
>
>> --- a/mercurial/pycompat.py   Tue Dec 06 11:44:49 2016 +0000
>> +++ b/mercurial/pycompat.py   Tue Dec 06 06:36:36 2016 +0530
>> @@ -10,6 +10,7 @@
>>
>>  from __future__ import absolute_import
>>
>> +import getopt
>>  import os
>>  import sys
>>
>> @@ -87,6 +88,19 @@
>>      setattr = _wrapattrfunc(builtins.setattr)
>>      xrange = builtins.range
>>
>> +    # getopt.getopt() on Python 3 deals with unicodes internally so we cannot
>> +    # pass bytes there. Passing unicodes will result in unicodes as return
>> +    # values which we need to convert again to bytes.
>> +    def getoptb(args, shortlist, namelist):
>> +        args = [a.decode('latin-1') for a in args]
>> +        shortlist = shortlist.decode('latin-1')
>> +        namelist = [a.decode('latin-1') for a in namelist]
>> +        opts, args = getopt.getopt(args, shortlist, namelist)
>> +        opts = [(a[0].enocde('latin-1'), a[1].enocde('latin-1'))
>> +                            for a in opts]
>
> Fixed typo in flight: s/enocde/encode/.

Oh! thanks for catching this.

Patch

diff -r a2b053b8d31a -r 4b57889d5805 mercurial/fancyopts.py
--- a/mercurial/fancyopts.py	Tue Dec 06 11:44:49 2016 +0000
+++ b/mercurial/fancyopts.py	Tue Dec 06 06:36:36 2016 +0530
@@ -7,10 +7,11 @@ 
 
 from __future__ import absolute_import
 
-import getopt
-
 from .i18n import _
-from . import error
+from . import (
+    error,
+    pycompat,
+)
 
 # Set of flags to not apply boolean negation logic on
 nevernegate = set([
@@ -34,13 +35,14 @@ 
         stopindex = args.index('--')
         extraargs = args[stopindex + 1:]
         args = args[:stopindex]
-    opts, parseargs = getopt.getopt(args, options, longoptions)
+    opts, parseargs = pycompat.getoptb(args, options, longoptions)
     args = []
     while parseargs:
         arg = parseargs.pop(0)
         if arg and arg[0] == '-' and len(arg) > 1:
             parseargs.insert(0, arg)
-            topts, newparseargs = getopt.getopt(parseargs, options, longoptions)
+            topts, newparseargs = pycompat.getoptb(parseargs,\
+                                            options, longoptions)
             opts = opts + topts
             parseargs = newparseargs
         else:
@@ -125,7 +127,7 @@ 
     if gnu:
         parse = gnugetopt
     else:
-        parse = getopt.getopt
+        parse = pycompat.getoptb
     opts, args = parse(args, shortlist, namelist)
 
     # transfer result to state
diff -r a2b053b8d31a -r 4b57889d5805 mercurial/pycompat.py
--- a/mercurial/pycompat.py	Tue Dec 06 11:44:49 2016 +0000
+++ b/mercurial/pycompat.py	Tue Dec 06 06:36:36 2016 +0530
@@ -10,6 +10,7 @@ 
 
 from __future__ import absolute_import
 
+import getopt
 import os
 import sys
 
@@ -87,6 +88,19 @@ 
     setattr = _wrapattrfunc(builtins.setattr)
     xrange = builtins.range
 
+    # getopt.getopt() on Python 3 deals with unicodes internally so we cannot
+    # pass bytes there. Passing unicodes will result in unicodes as return
+    # values which we need to convert again to bytes.
+    def getoptb(args, shortlist, namelist):
+        args = [a.decode('latin-1') for a in args]
+        shortlist = shortlist.decode('latin-1')
+        namelist = [a.decode('latin-1') for a in namelist]
+        opts, args = getopt.getopt(args, shortlist, namelist)
+        opts = [(a[0].enocde('latin-1'), a[1].enocde('latin-1'))
+                            for a in opts]
+        args = [a.encode('latin-1') for a in args]
+        return opts, args
+
 else:
     def sysstr(s):
         return s
@@ -106,6 +120,9 @@ 
     def fsdecode(filename):
         return filename
 
+    def getoptb(args, shortlist, namelist):
+        return getopt.getopt(args, shortlist, namelist)
+
     osname = os.name
     ospathsep = os.pathsep
     ossep = os.sep
diff -r a2b053b8d31a -r 4b57889d5805 mercurial/statprof.py
--- a/mercurial/statprof.py	Tue Dec 06 11:44:49 2016 +0000
+++ b/mercurial/statprof.py	Tue Dec 06 06:36:36 2016 +0530
@@ -116,6 +116,10 @@ 
 import threading
 import time
 
+from . import (
+    pycompat,
+)
+
 defaultdict = collections.defaultdict
 contextmanager = contextlib.contextmanager
 
@@ -771,7 +775,7 @@ 
 
     # process options
     try:
-        opts, args = getopt.getopt(sys.argv[optstart:], "hl:f:o:p:",
+        opts, args = pycompat.getoptb(sys.argv[optstart:], "hl:f:o:p:",
                                    ["help", "limit=", "file=", "output-file=", "script-path="])
     except getopt.error as msg:
         print(msg)