py3: fix str vs bytes in enough places to run `hg version` on Windows
I don't have Visual Studio 2015 at home, but this now works with a handful of
extensions (blackbox, extdiff, patchbomb, phabricator and rebase, but not
evolve):
$ HGMODULEPOLICY=py py -3 ../hg version
Enabling the evolve extension causes the usual "failed to import ..." line, but
then print this before the usual version output:
('commit', '[b'debugancestor', b'debugapplystreamclonebundle', ...,
b'verify', b'version']')
... where the elided part seems to be every command and alias known.
--- a/mercurial/color.py Thu Sep 13 20:54:53 2018 -0400
+++ b/mercurial/color.py Thu Sep 13 22:07:00 2018 -0400
@@ -408,21 +408,21 @@
_INVALID_HANDLE_VALUE = -1
class _COORD(ctypes.Structure):
- _fields_ = [('X', ctypes.c_short),
- ('Y', ctypes.c_short)]
+ _fields_ = [(r'X', ctypes.c_short),
+ (r'Y', ctypes.c_short)]
class _SMALL_RECT(ctypes.Structure):
- _fields_ = [('Left', ctypes.c_short),
- ('Top', ctypes.c_short),
- ('Right', ctypes.c_short),
- ('Bottom', ctypes.c_short)]
+ _fields_ = [(r'Left', ctypes.c_short),
+ (r'Top', ctypes.c_short),
+ (r'Right', ctypes.c_short),
+ (r'Bottom', ctypes.c_short)]
class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
- _fields_ = [('dwSize', _COORD),
- ('dwCursorPosition', _COORD),
- ('wAttributes', _WORD),
- ('srWindow', _SMALL_RECT),
- ('dwMaximumWindowSize', _COORD)]
+ _fields_ = [(r'dwSize', _COORD),
+ (r'dwCursorPosition', _COORD),
+ (r'wAttributes', _WORD),
+ (r'srWindow', _SMALL_RECT),
+ (r'dwMaximumWindowSize', _COORD)]
_STD_OUTPUT_HANDLE = 0xfffffff5 # (DWORD)-11
_STD_ERROR_HANDLE = 0xfffffff4 # (DWORD)-12
@@ -484,7 +484,7 @@
w32effects = None
else:
origattr = csbi.wAttributes
- ansire = re.compile('\033\[([^m]*)m([^\033]*)(.*)',
+ ansire = re.compile(b'\033\[([^m]*)m([^\033]*)(.*)',
re.MULTILINE | re.DOTALL)
def win32print(ui, writefunc, *msgs, **opts):
@@ -516,15 +516,15 @@
# them if not found
pass
# hack to ensure regexp finds data
- if not text.startswith('\033['):
- text = '\033[m' + text
+ if not text.startswith(b'\033['):
+ text = b'\033[m' + text
# Look for ANSI-like codes embedded in text
m = re.match(ansire, text)
try:
while m:
- for sattr in m.group(1).split(';'):
+ for sattr in m.group(1).split(b';'):
if sattr:
attr = mapcolor(int(sattr), attr)
ui.flush()
--- a/mercurial/pure/osutil.py Thu Sep 13 20:54:53 2018 -0400
+++ b/mercurial/pure/osutil.py Thu Sep 13 22:07:00 2018 -0400
@@ -14,6 +14,7 @@
import stat as statmod
from .. import (
+ encoding,
pycompat,
)
@@ -193,7 +194,8 @@
def _raiseioerror(name):
err = ctypes.WinError()
- raise IOError(err.errno, '%s: %s' % (name, err.strerror))
+ raise IOError(err.errno, r'%s: %s' % (encoding.strfromlocal(name),
+ err.strerror))
class posixfile(object):
'''a file object aiming for POSIX-like semantics
@@ -207,14 +209,14 @@
remains but cannot be opened again or be recreated under the same name,
until all reading processes have closed the file.'''
- def __init__(self, name, mode='r', bufsize=-1):
- if 'b' in mode:
+ def __init__(self, name, mode=b'r', bufsize=-1):
+ if b'b' in mode:
flags = _O_BINARY
else:
flags = _O_TEXT
- m0 = mode[0]
- if m0 == 'r' and '+' not in mode:
+ m0 = mode[0:1]
+ if m0 == b'r' and b'+' not in mode:
flags |= _O_RDONLY
access = _GENERIC_READ
else:
@@ -223,15 +225,15 @@
flags |= _O_RDWR
access = _GENERIC_READ | _GENERIC_WRITE
- if m0 == 'r':
+ if m0 == b'r':
creation = _OPEN_EXISTING
- elif m0 == 'w':
+ elif m0 == b'w':
creation = _CREATE_ALWAYS
- elif m0 == 'a':
+ elif m0 == b'a':
creation = _OPEN_ALWAYS
flags |= _O_APPEND
else:
- raise ValueError("invalid mode: %s" % mode)
+ raise ValueError(r"invalid mode: %s" % pycompat.sysstr(mode))
fh = _kernel32.CreateFileA(name, access,
_FILE_SHARE_READ | _FILE_SHARE_WRITE | _FILE_SHARE_DELETE,
--- a/mercurial/windows.py Thu Sep 13 20:54:53 2018 -0400
+++ b/mercurial/windows.py Thu Sep 13 22:07:00 2018 -0400
@@ -389,7 +389,7 @@
"""
global _quotere
if _quotere is None:
- _quotere = re.compile(r'(\\*)("|\\$)')
+ _quotere = re.compile(br'(\\*)("|\\$)')
global _needsshellquote
if _needsshellquote is None:
# ":" is also treated as "safe character", because it is used as a part
@@ -397,11 +397,11 @@
# safe because shlex.split() (kind of) treats it as an escape char and
# drops it. It will leave the next character, even if it is another
# "\".
- _needsshellquote = re.compile(r'[^a-zA-Z0-9._:/-]').search
+ _needsshellquote = re.compile(br'[^a-zA-Z0-9._:/-]').search
if s and not _needsshellquote(s) and not _quotere.search(s):
# "s" shouldn't have to be quoted
return s
- return '"%s"' % _quotere.sub(r'\1\1\\\2', s)
+ return b'"%s"' % _quotere.sub(br'\1\1\\\2', s)
def _unquote(s):
if s.startswith(b'"') and s.endswith(b'"'):