contrib: remove references to 2to3
The custom porting fixers are removed. A comment related to 2to3
has been removed from the import checker.
After this patch, no references to 2to3 remain.
--- a/contrib/hgfixes/fix_bytes.py Sat Feb 27 21:14:17 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-"""Fixer that changes plain strings to bytes strings."""
-
-import re
-
-from lib2to3 import fixer_base
-from lib2to3.pgen2 import token
-from lib2to3.fixer_util import Name
-from lib2to3.pygram import python_symbols as syms
-
-_re = re.compile(r'[rR]?[\'\"]')
-
-# XXX: Implementing a blacklist in 2to3 turned out to be more troublesome than
-# blacklisting some modules inside the fixers. So, this is what I came with.
-
-blacklist = ('mercurial/demandimport.py',
- 'mercurial/py3kcompat.py', # valid python 3 already
- 'mercurial/i18n.py',
- )
-
-def isdocstring(node):
- def isclassorfunction(ancestor):
- symbols = (syms.funcdef, syms.classdef)
- # if the current node is a child of a function definition, a class
- # definition or a file, then it is a docstring
- if ancestor.type == syms.simple_stmt:
- try:
- while True:
- if ancestor.type in symbols:
- return True
- ancestor = ancestor.parent
- except AttributeError:
- return False
- return False
-
- def ismodule(ancestor):
- # Our child is a docstring if we are a simple statement, and our
- # ancestor is file_input. In other words, our child is a lone string in
- # the source file.
- try:
- if (ancestor.type == syms.simple_stmt and
- ancestor.parent.type == syms.file_input):
- return True
- except AttributeError:
- return False
-
- def isdocassignment(ancestor):
- # Assigning to __doc__, definitely a string
- try:
- while True:
- if (ancestor.type == syms.expr_stmt and
- Name('__doc__') in ancestor.children):
- return True
- ancestor = ancestor.parent
- except AttributeError:
- return False
-
- if ismodule(node.parent) or \
- isdocassignment(node.parent) or \
- isclassorfunction(node.parent):
- return True
- return False
-
-def shouldtransform(node):
- specialnames = ['__main__']
-
- if node.value in specialnames:
- return False
-
- ggparent = node.parent.parent.parent
- sggparent = str(ggparent)
-
- if 'getattr' in sggparent or \
- 'hasattr' in sggparent or \
- 'setattr' in sggparent or \
- 'encode' in sggparent or \
- 'decode' in sggparent:
- return False
-
- return True
-
-class FixBytes(fixer_base.BaseFix):
-
- PATTERN = 'STRING'
-
- def transform(self, node, results):
- # The filename may be prefixed with a build directory.
- if self.filename.endswith(blacklist):
- return
- if node.type == token.STRING:
- if _re.match(node.value):
- if isdocstring(node):
- return
- if not shouldtransform(node):
- return
- new = node.clone()
- new.value = 'b' + new.value
- return new
-
--- a/contrib/hgfixes/fix_bytesmod.py Sat Feb 27 21:14:17 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-"""Fixer that changes bytes % whatever to a function that actually formats
-it."""
-
-from lib2to3 import fixer_base
-from lib2to3.fixer_util import is_tuple, Call, Comma, Name, touch_import
-
-# XXX: Implementing a blacklist in 2to3 turned out to be more troublesome than
-# blacklisting some modules inside the fixers. So, this is what I came with.
-
-blacklist = ['mercurial/demandimport.py',
- 'mercurial/py3kcompat.py',
- 'mercurial/i18n.py',
- ]
-
-def isnumberremainder(formatstr, data):
- try:
- if data.value.isdigit():
- return True
- except AttributeError:
- return False
-
-class FixBytesmod(fixer_base.BaseFix):
- # XXX: There's one case (I suppose) I can't handle: when a remainder
- # operation like foo % bar is performed, I can't really know what the
- # contents of foo and bar are. I believe the best approach is to "correct"
- # the to-be-converted code and let bytesformatter handle that case in
- # runtime.
- PATTERN = '''
- term< formatstr=STRING '%' data=STRING > |
- term< formatstr=STRING '%' data=atom > |
- term< formatstr=NAME '%' data=any > |
- term< formatstr=any '%' data=any >
- '''
-
- def transform(self, node, results):
- for bfn in blacklist:
- if self.filename.endswith(bfn):
- return
- if not self.filename.endswith('mercurial/py3kcompat.py'):
- touch_import('mercurial', 'py3kcompat', node=node)
-
- formatstr = results['formatstr'].clone()
- data = results['data'].clone()
- formatstr.prefix = '' # remove spaces from start
-
- if isnumberremainder(formatstr, data):
- return
-
- # We have two possibilities:
- # 1- An identifier or name is passed, it is going to be a leaf, thus, we
- # just need to copy its value as an argument to the formatter;
- # 2- A tuple is explicitly passed. In this case, we're gonna explode it
- # to pass to the formatter
- # TODO: Check for normal strings. They don't need to be translated
-
- if is_tuple(data):
- args = [formatstr, Comma().clone()] + \
- [c.clone() for c in data.children[:]]
- else:
- args = [formatstr, Comma().clone(), data]
-
- call = Call(Name('bytesformatter', prefix=' '), args)
- return call
--- a/contrib/hgfixes/fix_leftover_imports.py Sat Feb 27 21:14:17 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-"Fixer that translates some APIs ignored by the default 2to3 fixers."
-
-# FIXME: This fixer has some ugly hacks. Its main design is based on that of
-# fix_imports, from lib2to3. Unfortunately, the fix_imports framework only
-# changes module names "without dots", meaning it won't work for some changes
-# in the email module/package. Thus this fixer was born. I believe that with a
-# bit more thinking, a more generic fixer can be implemented, but I'll leave
-# that as future work.
-
-from lib2to3.fixer_util import Name
-from lib2to3.fixes import fix_imports
-
-# This maps the old names to the new names. Note that a drawback of the current
-# design is that the dictionary keys MUST have EXACTLY one dot (.) in them,
-# otherwise things will break. (If you don't need a module hierarchy, you're
-# better of just inherit from fix_imports and overriding the MAPPING dict.)
-
-MAPPING = {'email.Utils': 'email.utils',
- 'email.Errors': 'email.errors',
- 'email.Header': 'email.header',
- 'email.Parser': 'email.parser',
- 'email.Encoders': 'email.encoders',
- 'email.MIMEText': 'email.mime.text',
- 'email.MIMEBase': 'email.mime.base',
- 'email.Generator': 'email.generator',
- 'email.MIMEMultipart': 'email.mime.multipart',
-}
-
-def alternates(members):
- return "(" + "|".join(map(repr, members)) + ")"
-
-def build_pattern(mapping=MAPPING):
- packages = {}
- for key in mapping:
- # What we are doing here is the following: with dotted names, we'll
- # have something like package_name <trailer '.' module>. Then, we are
- # making a dictionary to copy this structure. For example, if
- # mapping={'A.B': 'a.b', 'A.C': 'a.c'}, it will generate the dictionary
- # {'A': ['b', 'c']} to, then, generate something like "A <trailer '.'
- # ('b' | 'c')".
- name = key.split('.')
- prefix = name[0]
- if prefix in packages:
- packages[prefix].append(name[1:][0])
- else:
- packages[prefix] = name[1:]
-
- mod_list = ' | '.join(["'%s' '.' ('%s')" %
- (key, "' | '".join(packages[key])) for key in packages])
- mod_list = '(' + mod_list + ' )'
-
- yield """name_import=import_name< 'import' module_name=dotted_name< %s > >
- """ % mod_list
-
- yield """name_import=import_name< 'import'
- multiple_imports=dotted_as_names< any*
- module_name=dotted_name< %s >
- any* >
- >""" % mod_list
-
- packs = ' | '.join(["'%s' trailer<'.' ('%s')>" % (key,
- "' | '".join(packages[key])) for key in packages])
-
- yield "power< package=(%s) trailer<'.' any > any* >" % packs
-
-class FixLeftoverImports(fix_imports.FixImports):
- # We want to run this fixer after fix_import has run (this shouldn't matter
- # for hg, though, as setup3k prefers to run the default fixers first)
- mapping = MAPPING
-
- def build_pattern(self):
- return "|".join(build_pattern(self.mapping))
-
- def transform(self, node, results):
- # Mostly copied from fix_imports.py
- import_mod = results.get("module_name")
- if import_mod:
- try:
- mod_name = import_mod.value
- except AttributeError:
- # XXX: A hack to remove whitespace prefixes and suffixes
- mod_name = str(import_mod).strip()
- new_name = self.mapping[mod_name]
- import_mod.replace(Name(new_name, prefix=import_mod.prefix))
- if "name_import" in results:
- # If it's not a "from x import x, y" or "import x as y" import,
- # marked its usage to be replaced.
- self.replace[mod_name] = new_name
- if "multiple_imports" in results:
- # This is a nasty hack to fix multiple imports on a line (e.g.,
- # "import StringIO, urlparse"). The problem is that I can't
- # figure out an easy way to make a pattern recognize the keys of
- # MAPPING randomly sprinkled in an import statement.
- results = self.match(node)
- if results:
- self.transform(node, results)
- else:
- # Replace usage of the module.
- # Now this is, mostly, a hack
- bare_name = results["package"][0]
- bare_name_text = ''.join(map(str, results['package'])).strip()
- new_name = self.replace.get(bare_name_text)
- prefix = results['package'][0].prefix
- if new_name:
- bare_name.replace(Name(new_name, prefix=prefix))
- results["package"][1].replace(Name(''))
-
--- a/contrib/import-checker.py Sat Feb 27 21:14:17 2016 -0800
+++ b/contrib/import-checker.py Sat Feb 27 21:15:16 2016 -0800
@@ -495,10 +495,6 @@
"""Given some python source, verify that stdlib imports are done
in separate statements from relative local module imports.
- Observing this limitation is important as it works around an
- annoying lib2to3 bug in relative import rewrites:
- http://bugs.python.org/issue19510.
-
>>> list(verify_stdlib_on_own_line(ast.parse('import sys, foo')))
[('mixed imports\\n stdlib: sys\\n relative: foo', 1)]
>>> list(verify_stdlib_on_own_line(ast.parse('import sys, os')))
--- a/tests/test-check-py3-compat.t Sat Feb 27 21:14:17 2016 -0800
+++ b/tests/test-check-py3-compat.t Sat Feb 27 21:15:16 2016 -0800
@@ -6,9 +6,6 @@
contrib/check-code.py not using absolute_import
contrib/check-code.py requires print_function
contrib/debugshell.py not using absolute_import
- contrib/hgfixes/fix_bytes.py not using absolute_import
- contrib/hgfixes/fix_bytesmod.py not using absolute_import
- contrib/hgfixes/fix_leftover_imports.py not using absolute_import
contrib/import-checker.py not using absolute_import
contrib/import-checker.py requires print_function
contrib/memory.py not using absolute_import