modernize-0.7/0000775000175000017500000000000013434507641015463 5ustar takluyvertakluyver00000000000000modernize-0.7/CHANGELOG.rst0000664000175000017500000000571413132653477017517 0ustar takluyvertakluyver00000000000000Unreleased ========== * Added the opt-in classic_division fixer. * Updated the ``dict_six`` fixer to support ``six.viewitems()`` and friends. * New fixer for ``unichr``, changed to ``six.unichr``. * Documentation corrections. Version 0.4 =========== Released 2014-10-14. * `Documentation`_ has been added. * All fixers are now idempotent, which allows modernize to safely be applied more than once to the same source code. * The option to include default fixers when ``-f`` options are used is now spelled ``-f default``, rather than ``-f all``. * Added a ``--version`` option to the modernize command. * Calls to ``zip``, ``map``, and ``filter`` are now wrapped with ``list()`` in non-iterator contexts, to preserve Python 2 semantics. * Improved fixer for ``xrange`` using ``six.moves.range``. * Simplified use of ``six.with_metaclass`` for classes with more than one base class. * New fixer for imports of renamed standard library modules, using ``six.moves``. * New fixer to add ``from __future__ import absolute_import`` to all files with imports, and change any implicit relative imports to explicit (see PEP 328). * New fixer for ``input()`` and ``raw_input()``, changed to ``eval(input())`` and ``input()`` respectively. * New fixer for ``file()``, changed to ``open()``. There is also an opt-in fixer that changes both of these to ``io.open()``. * New fixer for ``(int, long)`` or ``(long, int)``, changed to ``six.integer_types``. Other references to ``long`` are changed to ``int``. * New fixer for ``basestring``, changed to ``six.string_types``. * New fixer for ``unicode``, changed to ``six.text_type``. * The ``fix_next`` fixer uses the ``next()`` builtin rather than ``six.advance_iterator``. * There is test coverage for all ``libmodernize`` fixers. * Simplified the implementation of many ``libmodernize`` fixers by extending similar fixers from ``lib2to3``. * Fixed a bug where ``fix_raise_six`` was adding an incorrect import statement. * Support for targeting Python 2.5 or lower has been officially dropped. (Previously some fixers did output constructs that were only added in Python 2.6, such as the ``except ... as`` construct, but this was not documented.) .. _Documentation: http://python-modernize.readthedocs.org/en/latest/ Version 0.3 =========== Released 2014-08-12. * New fixer for ``raise E, V, T``, changed to ``six.reraise(E, V, T)``. * New fixer for metaclasses, using ``six.with_metaclass``. * Avoid adding redundant parentheses to ``print(x)``. * python-modernize can now be installed and run on Python 3. * Fixed a bug where ``__future__`` imports were added multiple times. * Fixed a bug where fixer for ``zip()`` was recognising ``map()``. * The default is now to leave Unicode literals unchanged. (In previous versions this required the ``--compat-unicode`` option, which has now been removed.) A new ``--six-unicode`` option has been added to obtain the previous behaviour of adding ``six.u`` wrappers around Unicode literals. modernize-0.7/LICENSE0000664000175000017500000000316313132653477016477 0ustar takluyvertakluyver00000000000000Copyright (c) 2011 by Armin Ronacher. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. Parts of this software package are built on lib2to3 which is licensed under the PSF license. For more information refer to the Python license: http://docs.python.org/license.html THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. modernize-0.7/MANIFEST.in0000664000175000017500000000010113132653477017215 0ustar takluyvertakluyver00000000000000include CHANGELOG.rst LICENSE README.rst global-exclude *~ *.pyc modernize-0.7/PKG-INFO0000664000175000017500000000502013434507641016555 0ustar takluyvertakluyver00000000000000Metadata-Version: 1.1 Name: modernize Version: 0.7 Summary: A hack on top of 2to3 for modernizing code for hybrid codebases. Home-page: https://github.com/python-modernize/python-modernize Author: Armin Ronacher Author-email: armin.ronacher@active-4.com License: UNKNOWN Description: :: Python _ _ _ __ ___ __| |___ _ _ _ _ (_)______ | ' \/ _ \/ _` / -_) '_| ' \| |_ / -_) |_|_|_\___/\__,_\___|_| |_||_|_/__\___| This library is a very thin wrapper around `lib2to3 `_ to utilize it to make Python 2 code more modern with the intention of eventually porting it over to Python 3. The ``python-modernize`` command works like `2to3 `_. Here's how you'd rewrite a single file:: python-modernize -w example.py It does not guarantee, but it attempts to spit out a codebase compatible with Python 2.6+ or Python 3. The code that it generates has a runtime dependency on `six `_, unless the ``--no-six`` option is used. Version 1.9.0 or later of ``six`` is recommended. Some of the fixers output code that is not compatible with Python 2.5 or lower. **Documentation:** `python-modernize.readthedocs.io `_. See the ``LICENSE`` file for the license of ``python-modernize``. Using this tool does not affect licensing of the modernized code. .. image:: https://readthedocs.org/projects/python-modernize/badge/ :target: https://readthedocs.org/projects/python-modernize/?badge=latest :alt: Documentation Status .. image:: https://api.travis-ci.org/python-modernize/python-modernize.svg?branch=master :target: https://travis-ci.org/python-modernize/python-modernize .. image:: https://coveralls.io/repos/python-modernize/python-modernize/badge.png?branch=master :target: https://coveralls.io/r/python-modernize/python-modernize?branch=master Platform: UNKNOWN Classifier: License :: OSI Approved :: BSD License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 3 modernize-0.7/README.rst0000664000175000017500000000325713132653477017165 0ustar takluyvertakluyver00000000000000:: Python _ _ _ __ ___ __| |___ _ _ _ _ (_)______ | ' \/ _ \/ _` / -_) '_| ' \| |_ / -_) |_|_|_\___/\__,_\___|_| |_||_|_/__\___| This library is a very thin wrapper around `lib2to3 `_ to utilize it to make Python 2 code more modern with the intention of eventually porting it over to Python 3. The ``python-modernize`` command works like `2to3 `_. Here's how you'd rewrite a single file:: python-modernize -w example.py It does not guarantee, but it attempts to spit out a codebase compatible with Python 2.6+ or Python 3. The code that it generates has a runtime dependency on `six `_, unless the ``--no-six`` option is used. Version 1.9.0 or later of ``six`` is recommended. Some of the fixers output code that is not compatible with Python 2.5 or lower. **Documentation:** `python-modernize.readthedocs.io `_. See the ``LICENSE`` file for the license of ``python-modernize``. Using this tool does not affect licensing of the modernized code. .. image:: https://readthedocs.org/projects/python-modernize/badge/ :target: https://readthedocs.org/projects/python-modernize/?badge=latest :alt: Documentation Status .. image:: https://api.travis-ci.org/python-modernize/python-modernize.svg?branch=master :target: https://travis-ci.org/python-modernize/python-modernize .. image:: https://coveralls.io/repos/python-modernize/python-modernize/badge.png?branch=master :target: https://coveralls.io/r/python-modernize/python-modernize?branch=master modernize-0.7/libmodernize/0000775000175000017500000000000013434507641020146 5ustar takluyvertakluyver00000000000000modernize-0.7/libmodernize/__init__.py0000664000175000017500000000660613434507442022266 0ustar takluyvertakluyver00000000000000from __future__ import absolute_import from lib2to3 import fixer_util from lib2to3.pytree import Leaf, Node from lib2to3.pygram import python_symbols as syms from lib2to3.pgen2 import token __version__ = '0.7' def check_future_import(node): """If this is a future import, return set of symbols that are imported, else return None.""" # node should be the import statement here if not (node.type == syms.simple_stmt and node.children): return set() node = node.children[0] # now node is the import_from node if not (node.type == syms.import_from and node.children[1].type == token.NAME and node.children[1].value == u'__future__'): return set() if node.children[3].type == token.LPAR: # from __future__ import (.. node = node.children[4] else: # from __future__ import ... node = node.children[3] # now node is the import_as_name[s] # print(python_grammar.number2symbol[node.type]) if node.type == syms.import_as_names: result = set() for n in node.children: if n.type == token.NAME: result.add(n.value) elif n.type == syms.import_as_name: n = n.children[0] assert n.type == token.NAME result.add(n.value) return result elif node.type == syms.import_as_name: node = node.children[0] assert node.type == token.NAME return set([node.value]) elif node.type == token.NAME: return set([node.value]) else: # pragma: no cover assert 0, "strange import" def add_future(node, symbol): root = fixer_util.find_root(node) for idx, node in enumerate(root.children): if node.type == syms.simple_stmt and \ len(node.children) > 0 and node.children[0].type == token.STRING: # skip over docstring continue names = check_future_import(node) if not names: # not a future statement; need to insert before this break if symbol in names: # already imported return import_ = fixer_util.FromImport('__future__', [Leaf(token.NAME, symbol, prefix=" ")]) # Place after any comments or whitespace. (copyright, shebang etc.) import_.prefix = node.prefix node.prefix = '' children = [import_, fixer_util.Newline()] root.insert_child(idx, Node(syms.simple_stmt, children)) def touch_import(package, name, node): fixer_util.touch_import(package, name, node) def is_listcomp(node): def _is_listcomp(node): return (isinstance(node, Node) and node.type == syms.atom and len(node.children) >= 2 and isinstance(node.children[0], Leaf) and node.children[0].value == '[' and isinstance(node.children[-1], Leaf) and node.children[-1].value == ']') def _is_noop_power_node(node): """https://github.com/python/cpython/pull/2235 changed the node structure for fix_map / fix_filter to contain a top-level `power` node """ return ( isinstance(node, Node) and node.type == syms.power and len(node.children) == 1 ) return ( _is_listcomp(node) or _is_noop_power_node(node) and _is_listcomp(node.children[0]) ) modernize-0.7/libmodernize/fixes/0000775000175000017500000000000013434507641021264 5ustar takluyvertakluyver00000000000000modernize-0.7/libmodernize/fixes/__init__.py0000664000175000017500000000332313132653477023402 0ustar takluyvertakluyver00000000000000 lib2to3_fix_names = set([ 'lib2to3.fixes.fix_apply', 'lib2to3.fixes.fix_except', 'lib2to3.fixes.fix_exec', 'lib2to3.fixes.fix_execfile', 'lib2to3.fixes.fix_exitfunc', 'lib2to3.fixes.fix_funcattrs', 'lib2to3.fixes.fix_has_key', 'lib2to3.fixes.fix_idioms', 'lib2to3.fixes.fix_long', 'lib2to3.fixes.fix_methodattrs', 'lib2to3.fixes.fix_ne', 'lib2to3.fixes.fix_numliterals', 'lib2to3.fixes.fix_operator', 'lib2to3.fixes.fix_paren', 'lib2to3.fixes.fix_reduce', 'lib2to3.fixes.fix_renames', 'lib2to3.fixes.fix_repr', 'lib2to3.fixes.fix_set_literal', 'lib2to3.fixes.fix_standarderror', 'lib2to3.fixes.fix_sys_exc', 'lib2to3.fixes.fix_throw', 'lib2to3.fixes.fix_tuple_params', 'lib2to3.fixes.fix_types', 'lib2to3.fixes.fix_ws_comma', 'lib2to3.fixes.fix_xreadlines' ]) # fixes that involve using six six_fix_names = set([ 'libmodernize.fixes.fix_basestring', 'libmodernize.fixes.fix_dict_six', 'libmodernize.fixes.fix_filter', 'libmodernize.fixes.fix_imports_six', 'libmodernize.fixes.fix_itertools_six', 'libmodernize.fixes.fix_itertools_imports_six', 'libmodernize.fixes.fix_input_six', 'libmodernize.fixes.fix_int_long_tuple', 'libmodernize.fixes.fix_map', 'libmodernize.fixes.fix_metaclass', 'libmodernize.fixes.fix_raise_six', 'libmodernize.fixes.fix_unicode', 'libmodernize.fixes.fix_unicode_type', 'libmodernize.fixes.fix_urllib_six', 'libmodernize.fixes.fix_unichr', 'libmodernize.fixes.fix_xrange_six', 'libmodernize.fixes.fix_zip', ]) # Fixes that are opt-in only. opt_in_fix_names = set([ 'libmodernize.fixes.fix_classic_division', 'libmodernize.fixes.fix_open', ]) modernize-0.7/libmodernize/fixes/fix_basestring.py0000664000175000017500000000060613132653477024653 0ustar takluyvertakluyver00000000000000from __future__ import absolute_import from lib2to3 import fixer_base from lib2to3 import fixer_util import libmodernize class FixBasestring(fixer_base.BaseFix): BM_compatible = True PATTERN = """'basestring'""" def transform(self, node, results): libmodernize.touch_import(None, u'six', node) return fixer_util.Name(u'six.string_types', prefix=node.prefix) modernize-0.7/libmodernize/fixes/fix_classic_division.py0000664000175000017500000000120713132653477026035 0ustar takluyvertakluyver00000000000000from __future__ import absolute_import from lib2to3 import fixer_base from lib2to3 import pytree from lib2to3.pgen2 import token import libmodernize class FixClassicDivision(fixer_base.BaseFix): _accept_type = token.SLASH def start_tree(self, tree, name): super(FixClassicDivision, self).start_tree(tree, name) self.skip = "division" in tree.future_features def match(self, node): return node.value == "/" def transform(self, node, results): if self.skip: return libmodernize.add_future(node, u'division') return pytree.Leaf(token.SLASH, "//", prefix=node.prefix) modernize-0.7/libmodernize/fixes/fix_dict_six.py0000664000175000017500000000236713132653477024326 0ustar takluyvertakluyver00000000000000"""Fixer for iterkeys() -> six.iterkeys(), and similarly for iteritems and itervalues.""" from __future__ import absolute_import # Local imports from lib2to3 import fixer_util from lib2to3.fixes import fix_dict import libmodernize class FixDictSix(fix_dict.FixDict): def transform_iter(self, method_name, node, base): """Call six.(iter|view)items() and friends.""" libmodernize.touch_import(None, u'six', node) new_node = [n.clone() for n in base] new_node[0].prefix = u'' name = fixer_util.Name(u'six.' + method_name, prefix=node.prefix) node.replace(fixer_util.Call(name, new_node)) def transform(self, node, results): method = results['method'][0] method_name = method.value if method_name in ('keys', 'items', 'values'): return super(FixDictSix, self).transform(node, results) else: return self.transform_iter(method_name, node, results['head']) def in_special_context(self, node, isiter): # Redefined from parent class to make "for x in d.items()" count as # in special context; 2to3 only counts for loops as special context # for the iter* methods. return super(FixDictSix, self).in_special_context(node, True) modernize-0.7/libmodernize/fixes/fix_file.py0000664000175000017500000000065313132653477023433 0ustar takluyvertakluyver00000000000000from __future__ import absolute_import from lib2to3 import fixer_base from lib2to3.fixer_util import Name class FixFile(fixer_base.BaseFix): BM_compatible = True order = 'pre' PATTERN = """ power< name='file' trailer< '(' any ')' > any* > """ def transform(self, node, results): name = results["name"] name.replace(Name("open", prefix=name.prefix)) modernize-0.7/libmodernize/fixes/fix_filter.py0000664000175000017500000000114713132653477024000 0ustar takluyvertakluyver00000000000000# Copyright 2008 Armin Ronacher. # Licensed to PSF under a Contributor Agreement. from __future__ import absolute_import from lib2to3.fixes import fix_filter import libmodernize class FixFilter(fix_filter.FixFilter): skip_on = "six.moves.filter" def transform(self, node, results): result = super(FixFilter, self).transform(node, results) if not libmodernize.is_listcomp(result): # Keep performance improvement from six.moves.filter in iterator # contexts on Python 2.7. libmodernize.touch_import(u'six.moves', u'filter', node) return result modernize-0.7/libmodernize/fixes/fix_import.py0000664000175000017500000000144213132653477024023 0ustar takluyvertakluyver00000000000000from __future__ import absolute_import from lib2to3.fixes import fix_import from lib2to3.fixer_util import syms import libmodernize class FixImport(fix_import.FixImport): # Make sure this runs before any other fixer to guarantee that any other # added absolute_import doesn't block this fixer's execution. run_order = 1 def transform(self, node, results): if self.skip: return # We're not interested in __future__ imports here if node.type == syms.import_from \ and getattr(results['imp'], 'value', None) == '__future__': return # If there are any non-future imports, add absolute_import libmodernize.add_future(node, 'absolute_import') return super(FixImport, self).transform(node, results) modernize-0.7/libmodernize/fixes/fix_imports_six.py0000664000175000017500000000464713132653477025103 0ustar takluyvertakluyver00000000000000from __future__ import absolute_import from lib2to3.fixes import fix_imports class FixImportsSix(fix_imports.FixImports): mapping = { '__builtin__': 'six.moves.builtins', '_winreg': 'six.moves.winreg', 'BaseHTTPServer': 'six.moves.BaseHTTPServer', 'CGIHTTPServer': 'six.moves.CGIHTTPServer', 'ConfigParser': 'six.moves.configparser', 'copy_reg': 'six.moves.copyreg', 'Cookie': 'six.moves.http_cookies', 'cookielib': 'six.moves.http_cookiejar', 'cPickle': 'six.moves.cPickle', 'Dialog': 'six.moves.tkinter_dialog', 'dummy_thread': 'six.moves._dummy_thread', # cStringIO.StringIO() # email.MIMEBase # email.MIMEMultipart # email.MIMENonMultipart # email.MIMEText 'FileDialog': 'six.moves.tkinter_filedialog', 'gdbm': 'six.moves.dbm_gnu', 'htmlentitydefs': 'six.moves.html_entities', 'HTMLParser': 'six.moves.html_parser', 'httplib': 'six.moves.http_client', # intern() # itertools.ifilter() # itertools.ifilterfalse() # itertools.imap() # itertools.izip() # itertools.zip_longest() # pipes.quote 'Queue': 'six.moves.queue', # reduce() # reload() 'repr': 'six.moves.reprlib', 'robotparser': 'six.moves.urllib_robotparser', 'ScrolledText': 'six.moves.tkinter_scrolledtext', 'SimpleDialog': 'six.moves.tkinter_simpledialog', 'SimpleHTTPServer': 'six.moves.SimpleHTTPServer', 'SimpleXMLRPCServer': 'six.moves.xmlrpc_server', 'SocketServer': 'six.moves.socketserver', 'thread': 'six.moves._thread', 'Tix': 'six.moves.tkinter_tix', 'tkColorChooser': 'six.moves.tkinter_colorchooser', 'tkCommonDialog': 'six.moves.tkinter_commondialog', 'Tkconstants': 'six.moves.tkinter_constants', 'Tkdnd': 'six.moves.tkinter_dnd', 'tkFileDialog': 'six.moves.tkinter_filedialog', 'tkFont': 'six.moves.tkinter_font', 'Tkinter': 'six.moves.tkinter', 'tkMessageBox': 'six.moves.tkinter_messagebox', 'tkSimpleDialog': 'six.moves.tkinter_tksimpledialog', 'ttk': 'six.moves.tkinter_ttk', # urllib 'urlparse' : 'six.moves.urllib.parse', # UserDict.UserDict # UserList.UserList # UserString.UserString 'xmlrpclib': 'six.moves.xmlrpc_client', } modernize-0.7/libmodernize/fixes/fix_input_six.py0000664000175000017500000000235613132653477024540 0ustar takluyvertakluyver00000000000000# This is a derived work of Lib/lib2to3/fixes/fix_input.py and # Lib/lib2to3/fixes/fix_raw_input.py. Those files are under the # copyright of the Python Software Foundation and licensed under the # Python Software Foundation License 2. # # Copyright notice: # # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012, 2013, 2014 Python Software Foundation. All rights reserved. from __future__ import absolute_import from lib2to3 import fixer_base from lib2to3.fixer_util import Call, Name from libmodernize import touch_import class FixInputSix(fixer_base.ConditionalFix): BM_compatible = True order = 'pre' skip_on = 'six.moves.input' PATTERN = """ power< (name='input' | name='raw_input') trailer< '(' [any] ')' > any* > """ def transform(self, node, results): if self.should_skip(node): return touch_import(u'six.moves', u'input', node) name = results['name'] if name.value == 'raw_input': name.replace(Name('input', prefix=name.prefix)) else: new_node = node.clone() new_node.prefix = '' return Call(Name('eval'), [new_node], prefix=node.prefix) modernize-0.7/libmodernize/fixes/fix_int_long_tuple.py0000664000175000017500000000105713132653477025535 0ustar takluyvertakluyver00000000000000from __future__ import absolute_import from lib2to3 import fixer_base from lib2to3 import fixer_util from libmodernize import touch_import class FixIntLongTuple(fixer_base.BaseFix): run_order = 4 # Must run before fix_long. PATTERN = """ pair=atom < '(' testlist_gexp < ( ('int' ',' 'long') | ('long' ',' 'int') ) > ')' > """ def transform(self, node, results): touch_import(None, 'six', node) pair = results['pair'] pair.replace(fixer_util.Name('six.integer_types', prefix=pair.prefix)) modernize-0.7/libmodernize/fixes/fix_itertools_imports_six.py0000664000175000017500000000454713132653477027206 0ustar takluyvertakluyver00000000000000""" Fixer for imports of itertools.(imap|ifilter|izip|ifilterfalse) """ # This is a derived work of Lib/lib2to3/fixes/fix_itertools_imports.py. That file # is under the copyright of the Python Software Foundation and licensed # under the Python Software Foundation License 2. # # Copyright notice: # # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012, 2013 Python Software Foundation. All rights reserved. # Local imports from lib2to3 import fixer_base from lib2to3.fixer_util import BlankLine, syms, token import libmodernize class FixItertoolsImportsSix(fixer_base.BaseFix): BM_compatible = True PATTERN = """ import_from< 'from' 'itertools' 'import' imports=any > """ %(locals()) def transform(self, node, results): imports = results['imports'] if imports.type == syms.import_as_name or not imports.children: children = [imports] else: children = imports.children for child in children[::2]: if child.type == token.NAME: member = child.value name_node = child elif child.type == token.STAR: # Just leave the import as is. return else: assert child.type == syms.import_as_name name_node = child.children[0] member_name = name_node.value if member_name in ('imap', 'izip', 'ifilter', 'ifilterfalse', 'izip_longest'): child.value = None libmodernize.touch_import(u'six.moves', member_name[1:], node) child.remove() # Make sure the import statement is still sane children = imports.children[:] or [imports] remove_comma = True for child in children: if remove_comma and child.type == token.COMMA: child.remove() else: remove_comma ^= True while children and children[-1].type == token.COMMA: children.pop().remove() # If there are no imports left, just get rid of the entire statement if (not (imports.children or getattr(imports, 'value', None)) or imports.parent is None): p = node.prefix node = BlankLine() node.prefix = p return node modernize-0.7/libmodernize/fixes/fix_itertools_six.py0000664000175000017500000000403213132653477025416 0ustar takluyvertakluyver00000000000000""" Fixer for itertools.(imap|ifilter|izip) --> (six.moves.map|six.moves.filter|six.moves.zip) and itertools.ifilterfalse --> six.moves.filterfalse (bugs 2360-2363) imports from itertools are fixed in fix_itertools_imports_six.py If itertools is imported as something else (ie: import itertools as it; it.izip(spam, eggs)) method calls will not get fixed. """ # This is a derived work of Lib/lib2to3/fixes/fix_itertools_import.py. That file # is under the copyright of the Python Software Foundation and licensed # under the Python Software Foundation License 2. # # Copyright notice: # # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012, 2013 Python Software Foundation. All rights reserved. # Local imports from lib2to3 import fixer_base from lib2to3.fixer_util import Name import libmodernize class FixItertoolsSix(fixer_base.BaseFix): BM_compatible = True it_funcs = "('imap'|'ifilter'|'izip'|'izip_longest'|'ifilterfalse')" PATTERN = """ power< it='itertools' trailer< dot='.' func=%(it_funcs)s > trailer< '(' [any] ')' > > | power< func=%(it_funcs)s trailer< '(' [any] ')' > > """ %(locals()) # Needs to be run after fix_(map|zip|filter) run_order = 6 def transform(self, node, results): prefix = None func = results['func'][0] if ('it' in results and func.value not in (u'ifilterfalse', u'izip_longest')): dot, it = (results['dot'], results['it']) # Remove the 'itertools' prefix = it.prefix it.remove() # Replace the node wich contains ('.', 'function') with the # function (to be consistant with the second part of the pattern) dot.remove() func.parent.replace(func) libmodernize.touch_import(u'six.moves', func.value[1:], node) prefix = prefix or func.prefix func.replace(Name(func.value[1:], prefix=prefix)) modernize-0.7/libmodernize/fixes/fix_map.py0000664000175000017500000000117213132653477023266 0ustar takluyvertakluyver00000000000000# Copyright 2008 Armin Ronacher. # Licensed to PSF under a Contributor Agreement. from __future__ import absolute_import from lib2to3.fixes import fix_map import libmodernize class FixMap(fix_map.FixMap): skip_on = "six.moves.map" def transform(self, node, results): result = super(FixMap, self).transform(node, results) if not libmodernize.is_listcomp(result): # Always use the import even if no change is required so as to have # improved performance in iterator contexts even on Python 2.7. libmodernize.touch_import(u'six.moves', u'map', node) return result modernize-0.7/libmodernize/fixes/fix_metaclass.py0000664000175000017500000002065013132653477024467 0ustar takluyvertakluyver00000000000000# coding: utf-8 """Fixer for __metaclass__ = X -> (six.with_metaclass(X)) methods. The various forms of classdef (inherits nothing, inherits once, inherits many) don't parse the same in the CST, so we look at ALL classes for a __metaclass__ and if we find one normalize the inherits to all be an arglist. For one-liner classes ('class X: pass') there is no indent/dedent so we normalize those into having a suite. Moving the __metaclass__ into the classdef can also cause the class body to be empty so there is some special casing for that as well. This fixer also tries very hard to keep original indenting and spacing in all those corner cases. """ # This is a derived work of Lib/lib2to3/fixes/fix_metaclass.py. That file # is under the copyright of the Python Software Foundation and licensed # under the Python Software Foundation License 2. # # Copyright notice: # # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012, 2013 Python Software Foundation. All rights reserved. # Author: Jack Diederich, Daniel Neuhäuser from __future__ import absolute_import # Local imports from lib2to3 import fixer_base from lib2to3.pygram import token from lib2to3.fixer_util import Name, syms, Node, Leaf, Call, Comma from libmodernize import touch_import def has_metaclass(parent): """ we have to check the cls_node without changing it. There are two possibilities: 1) clsdef => suite => simple_stmt => expr_stmt => Leaf('__meta') 2) clsdef => simple_stmt => expr_stmt => Leaf('__meta') """ for node in parent.children: if node.type == syms.suite: return has_metaclass(node) elif node.type == syms.simple_stmt and node.children: expr_node = node.children[0] if expr_node.type == syms.expr_stmt and expr_node.children: left_side = expr_node.children[0] if isinstance(left_side, Leaf) and \ left_side.value == '__metaclass__': return True return False def fixup_parse_tree(cls_node): """ one-line classes don't get a suite in the parse tree so we add one to normalize the tree """ for node in cls_node.children: if node.type == syms.suite: # already in the preferred format, do nothing return # !%@#! oneliners have no suite node, we have to fake one up for i, node in enumerate(cls_node.children): if node.type == token.COLON: break else: raise ValueError("No class suite and no ':'!") # pragma: no cover # move everything into a suite node suite = Node(syms.suite, []) while cls_node.children[i+1:]: move_node = cls_node.children[i+1] suite.append_child(move_node.clone()) move_node.remove() cls_node.append_child(suite) node = suite def fixup_simple_stmt(parent, i, stmt_node): """ if there is a semi-colon all the parts count as part of the same simple_stmt. We just want the __metaclass__ part so we move everything efter the semi-colon into its own simple_stmt node """ for semi_ind, node in enumerate(stmt_node.children): if node.type == token.SEMI: # *sigh* break else: return node.remove() # kill the semicolon new_expr = Node(syms.expr_stmt, []) new_stmt = Node(syms.simple_stmt, [new_expr]) while stmt_node.children[semi_ind:]: move_node = stmt_node.children[semi_ind] new_expr.append_child(move_node.clone()) move_node.remove() parent.insert_child(i, new_stmt) new_leaf1 = new_stmt.children[0].children[0] old_leaf1 = stmt_node.children[0].children[0] new_leaf1.prefix = old_leaf1.prefix def remove_trailing_newline(node): if node.children and node.children[-1].type == token.NEWLINE: node.children[-1].remove() def find_metas(cls_node): # find the suite node (Mmm, sweet nodes) for node in cls_node.children: if node.type == syms.suite: break else: raise ValueError("No class suite!") # pragma: no cover # look for simple_stmt[ expr_stmt[ Leaf('__metaclass__') ] ] for i, simple_node in list(enumerate(node.children)): if simple_node.type == syms.simple_stmt and simple_node.children: expr_node = simple_node.children[0] if expr_node.type == syms.expr_stmt and expr_node.children: # Check if the expr_node is a simple assignment. left_node = expr_node.children[0] if isinstance(left_node, Leaf) and \ left_node.value == u'__metaclass__': # We found an assignment to __metaclass__. fixup_simple_stmt(node, i, simple_node) remove_trailing_newline(simple_node) yield (node, i, simple_node) def fixup_indent(suite): """ If an INDENT is followed by a thing with a prefix then nuke the prefix Otherwise we get in trouble when removing __metaclass__ at suite start """ kids = suite.children[::-1] # find the first indent while kids: node = kids.pop() if node.type == token.INDENT: break # find the first Leaf while kids: node = kids.pop() if isinstance(node, Leaf) and node.type != token.DEDENT: if node.prefix: node.prefix = u'' return else: kids.extend(node.children[::-1]) class FixMetaclass(fixer_base.BaseFix): BM_compatible = True PATTERN = """ classdef """ def transform(self, node, results): if not has_metaclass(node): return # pragma: no cover fixup_parse_tree(node) # find metaclasses, keep the last one last_metaclass = None for suite, i, stmt in find_metas(node): last_metaclass = stmt stmt.remove() text_type = node.children[0].type # always Leaf(nnn, 'class') # figure out what kind of classdef we have if len(node.children) == 7: # Node(classdef, ['class', 'name', '(', arglist, ')', ':', suite]) # 0 1 2 3 4 5 6 if node.children[3].type == syms.arglist: arglist = node.children[3] # Node(classdef, ['class', 'name', '(', 'Parent', ')', ':', suite]) else: parent = node.children[3].clone() arglist = Node(syms.arglist, [parent]) node.set_child(3, arglist) elif len(node.children) == 6: # Node(classdef, ['class', 'name', '(', ')', ':', suite]) # 0 1 2 3 4 5 arglist = Node(syms.arglist, []) node.insert_child(3, arglist) elif len(node.children) == 4: # Node(classdef, ['class', 'name', ':', suite]) # 0 1 2 3 arglist = Node(syms.arglist, []) node.insert_child(2, Leaf(token.RPAR, u')')) node.insert_child(2, arglist) node.insert_child(2, Leaf(token.LPAR, u'(')) else: raise ValueError("Unexpected class definition") # pragma: no cover touch_import(None, u'six', node) metaclass = last_metaclass.children[0].children[2].clone() metaclass.prefix = u'' arguments = [metaclass] if arglist.children: bases = arglist.clone() bases.prefix = u' ' arguments.extend([Comma(), bases]) arglist.replace(Call( Name(u'six.with_metaclass', prefix=arglist.prefix), arguments )) fixup_indent(suite) # check for empty suite if not suite.children: # one-liner that was just __metaclass__ suite.remove() pass_leaf = Leaf(text_type, u'pass') pass_leaf.prefix = last_metaclass.prefix node.append_child(pass_leaf) node.append_child(Leaf(token.NEWLINE, u'\n')) elif len(suite.children) > 1 and \ (suite.children[-2].type == token.INDENT and suite.children[-1].type == token.DEDENT): # there was only one line in the class body and it was __metaclass__ pass_leaf = Leaf(text_type, u'pass') suite.insert_child(-1, pass_leaf) suite.insert_child(-1, Leaf(token.NEWLINE, u'\n')) modernize-0.7/libmodernize/fixes/fix_next.py0000664000175000017500000000122213132653477023463 0ustar takluyvertakluyver00000000000000"""Fixer for it.next() -> next(it)""" from __future__ import absolute_import # Local imports from lib2to3 import fixer_base from lib2to3.fixer_util import Name, Call bind_warning = "Calls to builtin next() possibly shadowed by global binding" class FixNext(fixer_base.BaseFix): BM_compatible = True PATTERN = """ power< base=any+ trailer< '.' attr='next' > trailer< '(' ')' > > """ order = "pre" # Pre-order tree traversal def transform(self, node, results): base = results['base'] base = [n.clone() for n in base] base[0].prefix = u"" node.replace(Call(Name(u"next", prefix=node.prefix), base)) modernize-0.7/libmodernize/fixes/fix_open.py0000664000175000017500000000063013132653477023450 0ustar takluyvertakluyver00000000000000from __future__ import absolute_import from lib2to3 import fixer_base import libmodernize class FixOpen(fixer_base.BaseFix): BM_compatible = True # Fixers don't directly stack, so make sure the 'file' case is covered. PATTERN = """ power< ('open' | 'file') trailer< '(' any+ ')' > > """ def transform(self, node, results): libmodernize.touch_import(u'io', u'open', node) modernize-0.7/libmodernize/fixes/fix_print.py0000664000175000017500000000047513132653477023652 0ustar takluyvertakluyver00000000000000from __future__ import absolute_import from lib2to3.fixes import fix_print import libmodernize class FixPrint(fix_print.FixPrint): def transform(self, node, results): result = super(FixPrint, self).transform(node, results) libmodernize.add_future(node, u'print_function') return result modernize-0.7/libmodernize/fixes/fix_raise.py0000664000175000017500000000143213132653477023613 0ustar takluyvertakluyver00000000000000"""Fixer for 'raise E, V, T' raise -> raise raise E -> raise E raise E, V -> raise E(V) raise (((E, E'), E''), E'''), V -> raise E(V) CAVEATS: 1) "raise E, V" will be incorrectly translated if V is an exception instance. The correct Python 3 idiom is raise E from V but since we can't detect instance-hood by syntax alone and since any client code would have to be changed as well, we don't automate this. """ # Author: Collin Winter, Armin Ronacher from __future__ import absolute_import from lib2to3.fixes import fix_raise class FixRaise(fix_raise.FixRaise): # We don't want to match 3-argument raise, with a traceback; # that is handled separately by fix_raise_six PATTERN = """ raise_stmt< 'raise' exc=any [',' val=any] > """modernize-0.7/libmodernize/fixes/fix_raise_six.py0000664000175000017500000000144013132653477024475 0ustar takluyvertakluyver00000000000000"""Fixer for 'raise E, V, T' raise E, V, T -> six.reraise(E, V, T) """ # Author : Markus Unterwaditzer from __future__ import absolute_import # Local imports from lib2to3 import fixer_base from lib2to3.fixer_util import Name, Call, Comma from libmodernize import touch_import class FixRaiseSix(fixer_base.BaseFix): BM_compatible = True PATTERN = """ raise_stmt< 'raise' exc=any ',' val=any ',' tb=any > """ def transform(self, node, results): exc = results["exc"].clone() val = results["val"].clone() tb = results["tb"].clone() exc.prefix = u"" val.prefix = tb.prefix = u" " touch_import(None, u'six', node) return Call(Name(u"six.reraise"), [exc, Comma(), val, Comma(), tb], prefix=node.prefix) modernize-0.7/libmodernize/fixes/fix_unichr.py0000664000175000017500000000073113132653477024001 0ustar takluyvertakluyver00000000000000from __future__ import absolute_import from lib2to3 import fixer_base from lib2to3.fixer_util import is_probably_builtin import libmodernize class FixUnichr(fixer_base.ConditionalFix): BM_compatible = True skip_on = 'six.moves.unichr' PATTERN = """'unichr'""" def transform(self, node, results): if self.should_skip(node): return if is_probably_builtin(node): libmodernize.touch_import(u'six', u'unichr', node) modernize-0.7/libmodernize/fixes/fix_unicode.py0000664000175000017500000000121513132653477024135 0ustar takluyvertakluyver00000000000000from __future__ import absolute_import import re from lib2to3 import fixer_base from lib2to3.fixer_util import Name, Call from libmodernize import touch_import _mapping = {u"unichr" : u"chr", u"unicode" : u"str"} _literal_re = re.compile(u"[uU][rR]?[\\'\\\"]") class FixUnicode(fixer_base.BaseFix): BM_compatible = True PATTERN = """STRING""" def transform(self, node, results): if _literal_re.match(node.value): touch_import(None, u'six', node) new = node.clone() new.value = new.value[1:] new.prefix = '' node.replace(Call(Name(u'six.u', prefix=node.prefix), [new])) modernize-0.7/libmodernize/fixes/fix_unicode_future.py0000664000175000017500000000054413132653477025533 0ustar takluyvertakluyver00000000000000from __future__ import absolute_import from lib2to3.fixes import fix_unicode from libmodernize import add_future class FixUnicodeFuture(fix_unicode.FixUnicode): def transform(self, node, results): res = super(FixUnicodeFuture, self).transform(node, results) if res: add_future(node, 'unicode_literals') return res modernize-0.7/libmodernize/fixes/fix_unicode_type.py0000664000175000017500000000060013132653477025173 0ustar takluyvertakluyver00000000000000from __future__ import absolute_import from lib2to3 import fixer_base from lib2to3 import fixer_util import libmodernize class FixUnicodeType(fixer_base.BaseFix): BM_compatible = True PATTERN = """'unicode'""" def transform(self, node, results): libmodernize.touch_import(None, u'six', node) return fixer_util.Name(u'six.text_type', prefix=node.prefix) modernize-0.7/libmodernize/fixes/fix_urllib_six.py0000664000175000017500000002120313132653477024662 0ustar takluyvertakluyver00000000000000"""Fix changes imports of urllib which are now incompatible. This is a copy of Lib/lib2to3/fixes/fix_urllib.py, but modified to point to the six.moves locations for new libraries instead of the Python 3 locations. """ # This is a derived work of Lib/lib2to3/fixes/fix_urllib.py. That file # is under the copyright of the Python Software Foundation and licensed # under the Python Software Foundation License 2. # # Copyright notice: # # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012, 2013 Python Software Foundation. All rights reserved. # Author: Nick Edds # Local imports from lib2to3.fixes.fix_imports import alternates, FixImports from lib2to3 import fixer_base from lib2to3.fixer_util import (Name, Comma, FromImport, Newline, find_indentation, Node, syms) MAPPING = {"urllib": [ ("six.moves.urllib.request", ["URLopener", "FancyURLopener", "urlretrieve", "_urlopener", "urlopen", "urlcleanup", "pathname2url", "url2pathname"]), ("six.moves.urllib.parse", ["quote", "quote_plus", "unquote", "unquote_plus", "urlencode", "splitattr", "splithost", "splitnport", "splitpasswd", "splitport", "splitquery", "splittag", "splittype", "splituser", "splitvalue", ]), ("six.moves.urllib.error", ["ContentTooShortError"])], "urllib2" : [ ("six.moves.urllib.request", ["urlopen", "install_opener", "build_opener", "Request", "OpenerDirector", "BaseHandler", "HTTPDefaultErrorHandler", "HTTPRedirectHandler", "HTTPCookieProcessor", "ProxyHandler", "HTTPPasswordMgr", "HTTPPasswordMgrWithDefaultRealm", "AbstractBasicAuthHandler", "HTTPBasicAuthHandler", "ProxyBasicAuthHandler", "AbstractDigestAuthHandler", "HTTPDigestAuthHandler", "ProxyDigestAuthHandler", "HTTPHandler", "HTTPSHandler", "FileHandler", "FTPHandler", "CacheFTPHandler", "UnknownHandler"]), ("six.moves.urllib.error", ["URLError", "HTTPError"]), ] } # Duplicate the url parsing functions for urllib2. MAPPING["urllib2"].append(MAPPING["urllib"][1]) def build_pattern(): bare = set() for old_module, changes in MAPPING.items(): for change in changes: new_module, members = change members = alternates(members) yield """import_name< 'import' (module=%r | dotted_as_names< any* module=%r any* >) > """ % (old_module, old_module) yield """import_from< 'from' mod_member=%r 'import' ( member=%s | import_as_name< member=%s 'as' any > | import_as_names< members=any* >) > """ % (old_module, members, members) yield """import_from< 'from' module_star=%r 'import' star='*' > """ % old_module yield """import_name< 'import' dotted_as_name< module_as=%r 'as' any > > """ % old_module # bare_with_attr has a special significance for FixImports.match(). yield """power< bare_with_attr=%r trailer< '.' member=%s > any* > """ % (old_module, members) class FixUrllibSix(FixImports): def build_pattern(self): return "|".join(build_pattern()) def transform_import(self, node, results): """Transform for the basic import case. Replaces the old import name with a comma separated list of its replacements. """ import_mod = results.get("module") pref = import_mod.prefix names = [] # create a Node list of the replacement modules for name in MAPPING[import_mod.value][:-1]: names.extend([Name(name[0], prefix=pref), Comma()]) names.append(Name(MAPPING[import_mod.value][-1][0], prefix=pref)) import_mod.replace(names) def transform_member(self, node, results): """Transform for imports of specific module elements. Replaces the module to be imported from with the appropriate new module. """ mod_member = results.get("mod_member") pref = mod_member.prefix member = results.get("member") # Simple case with only a single member being imported if member: # this may be a list of length one, or just a node if isinstance(member, list): member = member[0] new_name = None for change in MAPPING[mod_member.value]: if member.value in change[1]: new_name = change[0] break if new_name: mod_member.replace(Name(new_name, prefix=pref)) else: self.cannot_convert(node, "This is an invalid module element") # Multiple members being imported else: # a dictionary for replacements, order matters modules = [] mod_dict = {} members = results["members"] for member in members: # we only care about the actual members if member.type == syms.import_as_name: as_name = member.children[2].value member_name = member.children[0].value else: member_name = member.value as_name = None if member_name != u",": for change in MAPPING[mod_member.value]: if member_name in change[1]: if change[0] not in mod_dict: modules.append(change[0]) mod_dict.setdefault(change[0], []).append(member) new_nodes = [] indentation = find_indentation(node) first = True def handle_name(name, prefix): if name.type == syms.import_as_name: kids = [Name(name.children[0].value, prefix=prefix), name.children[1].clone(), name.children[2].clone()] return [Node(syms.import_as_name, kids)] return [Name(name.value, prefix=prefix)] for module in modules: elts = mod_dict[module] names = [] for elt in elts[:-1]: names.extend(handle_name(elt, pref)) names.append(Comma()) names.extend(handle_name(elts[-1], pref)) new = FromImport(module, names) if not first or node.parent.prefix.endswith(indentation): new.prefix = indentation new_nodes.append(new) first = False if new_nodes: nodes = [] for new_node in new_nodes[:-1]: nodes.extend([new_node, Newline()]) nodes.append(new_nodes[-1]) node.replace(nodes) else: self.cannot_convert(node, "All module elements are invalid") def transform_dot(self, node, results): """Transform for calls to module members in code.""" module_dot = results.get("bare_with_attr") member = results.get("member") new_name = None if isinstance(member, list): member = member[0] for change in MAPPING[module_dot.value]: if member.value in change[1]: new_name = change[0] break if new_name: module_dot.replace(Name(new_name, prefix=module_dot.prefix)) else: self.cannot_convert(node, "This is an invalid module element") def transform(self, node, results): if results.get("module"): self.transform_import(node, results) elif results.get("mod_member"): self.transform_member(node, results) elif results.get("bare_with_attr"): self.transform_dot(node, results) # Renaming and star imports are not supported for these modules. elif results.get("module_star"): self.cannot_convert(node, "Cannot handle star imports.") elif results.get("module_as"): self.cannot_convert(node, "This module is now multiple modules") modernize-0.7/libmodernize/fixes/fix_xrange_six.py0000664000175000017500000000104113132653477024653 0ustar takluyvertakluyver00000000000000# Copyright 2008 Armin Ronacher. # Licensed to PSF under a Contributor Agreement. from __future__ import absolute_import from lib2to3 import fixer_base from lib2to3.fixes import fix_xrange from libmodernize import touch_import class FixXrangeSix(fixer_base.ConditionalFix, fix_xrange.FixXrange): skip_on = 'six.moves.range' def transform(self, node, results): if self.should_skip(node): return touch_import(u'six.moves', u'range', node) return super(FixXrangeSix, self).transform(node, results) modernize-0.7/libmodernize/fixes/fix_zip.py0000664000175000017500000000106013132653477023307 0ustar takluyvertakluyver00000000000000# Copyright 2008 Armin Ronacher. # Licensed to PSF under a Contributor Agreement. from __future__ import absolute_import from lib2to3.fixes import fix_zip import libmodernize class FixZip(fix_zip.FixZip): skip_on = "six.moves.zip" def transform(self, node, results): result = super(FixZip, self).transform(node, results) # Always use six.moves.zip so that even Python 2.7 gets performance # boost from using itertools in iterator contexts. libmodernize.touch_import(u'six.moves', u'zip', node) return result modernize-0.7/libmodernize/main.py0000664000175000017500000002014313434507331021440 0ustar takluyvertakluyver00000000000000"""\ Python _ _ _ __ ___ __| |___ _ _ _ _ (_)______ | ' \/ _ \/ _` / -_) '_| ' \| |_ / -_) |_|_|_\___/\__,_\___|_| |_||_|_/__\___|\ """ from __future__ import absolute_import, print_function import sys import logging import optparse import os from lib2to3.main import warn, StdoutRefactoringTool from lib2to3 import refactor from libmodernize import __version__ from libmodernize.fixes import lib2to3_fix_names, six_fix_names, opt_in_fix_names usage = __doc__ + """\ %s Usage: modernize [options] file|dir ... """ % __version__ def format_usage(usage): """Method that doesn't output "Usage:" prefix""" return usage def main(args=None): """Main program. Returns a suggested exit status (0, 1, 2). """ # Set up option parser parser = optparse.OptionParser(usage=usage, version="modernize %s" % __version__) parser.formatter.format_usage = format_usage parser.add_option("-v", "--verbose", action="store_true", help="Show more verbose logging.") parser.add_option("--no-diffs", action="store_true", help="Don't show diffs of the refactoring.") parser.add_option("-l", "--list-fixes", action="store_true", help="List standard transformations.") parser.add_option("-d", "--doctests_only", action="store_true", help="Fix up doctests only.") parser.add_option("-f", "--fix", action="append", default=[], help="Each FIX specifies a transformation; '-f default' includes default fixers.") parser.add_option("--fixers-here", action="store_true", help="Add current working directory to python path (so fixers can be found)") parser.add_option("-j", "--processes", action="store", default=1, type="int", help="Run 2to3 concurrently.") parser.add_option("-x", "--nofix", action="append", default=[], help="Prevent a fixer from being run.") parser.add_option("-p", "--print-function", action="store_true", help="Modify the grammar so that print() is a function.") parser.add_option("-w", "--write", action="store_true", help="Write back modified files.") parser.add_option("-n", "--nobackups", action="store_true", default=False, help="Don't write backups for modified files.") parser.add_option("--six-unicode", action="store_true", default=False, help="Wrap unicode literals in six.u().") parser.add_option("--future-unicode", action="store_true", default=False, help="Use 'from __future__ import unicode_literals'" "(only useful for Python 2.6+).") parser.add_option("--no-six", action="store_true", default=False, help="Exclude fixes that depend on the six package.") parser.add_option("--enforce", action="store_true", default=False, help="Returns non-zero exit code of any fixers had to be applied. " "Useful for enforcing Python 3 compatibility.") fixer_pkg = 'libmodernize.fixes' avail_fixes = set(refactor.get_fixers_from_package(fixer_pkg)) avail_fixes.update(lib2to3_fix_names) # Parse command line arguments refactor_stdin = False flags = {} options, args = parser.parse_args(args) if not options.write and options.no_diffs: warn("Not writing files and not printing diffs; that's not very useful.") if not options.write and options.nobackups: parser.error("Can't use '-n' without '-w'.") if options.list_fixes: print("Standard transformations available for the -f/--fix and -x/--nofix options:") for fixname in sorted(avail_fixes): print(" {} ({})".format(fixname, fixname.split(".fix_", 1)[1])) print() if not args: return 0 if not args: print("At least one file or directory argument required.", file=sys.stderr) print("Use --help to show usage.", file=sys.stderr) return 2 if "-" in args: refactor_stdin = True if options.write: print("Can't write to stdin.", file=sys.stderr) return 2 if options.print_function: flags["print_function"] = True if options.fixers_here: sys.path.append(os.getcwd()) # Set up logging handler level = logging.DEBUG if options.verbose else logging.INFO logging.basicConfig(format='%(name)s: %(message)s', level=level) # Initialize the refactoring tool unwanted_fixes = set() splitfixes = [] for fix in options.nofix: splitfixes.extend(fix.split(',')) for fix in splitfixes: matched = None for tgt in avail_fixes: if tgt == fix or tgt.endswith(".fix_{}".format(fix)): matched = tgt unwanted_fixes.add(matched) break else: print("Error: fix '{}' was not found".format(fix), file=sys.stderr) return 2 default_fixes = avail_fixes.difference(opt_in_fix_names) # Remove unicode fixers depending on command line options if options.six_unicode: unwanted_fixes.add('libmodernize.fixes.fix_unicode_future') elif options.future_unicode: unwanted_fixes.add('libmodernize.fixes.fix_unicode') else: unwanted_fixes.add('libmodernize.fixes.fix_unicode') unwanted_fixes.add('libmodernize.fixes.fix_unicode_future') if options.no_six: unwanted_fixes.update(six_fix_names) explicit = set() if options.fix: default_present = False splitfixes = [] for fix in options.fix: splitfixes.extend(fix.split(',')) for fix in splitfixes: if fix == "default": default_present = True else: matched = None for tgt in avail_fixes: if tgt == fix or tgt.endswith(".fix_{}".format(fix)): matched = tgt explicit.add(matched) break else: # A non-standard fix -- trust user to have supplied path explicit.add(fix) requested = default_fixes.union(explicit) if default_present else explicit else: requested = default_fixes fixer_names = requested.difference(unwanted_fixes) # Filter out unwanted fixers explicit = explicit.intersection(fixer_names) # Filter `explicit` fixers vs remaining fixers print(" Loading the following fixers:", file=sys.stderr) if fixer_names: for fixname in sorted(fixer_names): print(" {} ({})".format(fixname, fixname.split(".fix_", 1)[1]), file=sys.stderr) else: print(" (None)", file=sys.stderr) print(" Applying the following explicit transformations:", file=sys.stderr) if explicit: for fixname in sorted(explicit): print(" {} ({})".format(fixname, fixname.split(".fix_", 1)[1]), file=sys.stderr) else: print(" (None)", file=sys.stderr) print(file=sys.stderr) # Refactor all files and directories passed as arguments rt = StdoutRefactoringTool(sorted(fixer_names), flags, sorted(explicit), options.nobackups, not options.no_diffs) if not rt.errors: if refactor_stdin: rt.refactor_stdin() else: try: rt.refactor(args, options.write, options.doctests_only, options.processes) except refactor.MultiprocessingUnsupported: # pragma: no cover assert options.processes > 1 print("Sorry, -j isn't supported on this platform.", file=sys.stderr) return 1 rt.summarize() # Return error status (0 if rt.errors is zero) return_code = int(bool(rt.errors)) # If we are enforcing python 3 compatibility, return a non-zero exit code if we had to modify # any files. if options.enforce and rt.files: return_code |= 2 return return_code modernize-0.7/modernize.egg-info/0000775000175000017500000000000013434507641021151 5ustar takluyvertakluyver00000000000000modernize-0.7/modernize.egg-info/PKG-INFO0000664000175000017500000000502013434507641022243 0ustar takluyvertakluyver00000000000000Metadata-Version: 1.1 Name: modernize Version: 0.7 Summary: A hack on top of 2to3 for modernizing code for hybrid codebases. Home-page: https://github.com/python-modernize/python-modernize Author: Armin Ronacher Author-email: armin.ronacher@active-4.com License: UNKNOWN Description: :: Python _ _ _ __ ___ __| |___ _ _ _ _ (_)______ | ' \/ _ \/ _` / -_) '_| ' \| |_ / -_) |_|_|_\___/\__,_\___|_| |_||_|_/__\___| This library is a very thin wrapper around `lib2to3 `_ to utilize it to make Python 2 code more modern with the intention of eventually porting it over to Python 3. The ``python-modernize`` command works like `2to3 `_. Here's how you'd rewrite a single file:: python-modernize -w example.py It does not guarantee, but it attempts to spit out a codebase compatible with Python 2.6+ or Python 3. The code that it generates has a runtime dependency on `six `_, unless the ``--no-six`` option is used. Version 1.9.0 or later of ``six`` is recommended. Some of the fixers output code that is not compatible with Python 2.5 or lower. **Documentation:** `python-modernize.readthedocs.io `_. See the ``LICENSE`` file for the license of ``python-modernize``. Using this tool does not affect licensing of the modernized code. .. image:: https://readthedocs.org/projects/python-modernize/badge/ :target: https://readthedocs.org/projects/python-modernize/?badge=latest :alt: Documentation Status .. image:: https://api.travis-ci.org/python-modernize/python-modernize.svg?branch=master :target: https://travis-ci.org/python-modernize/python-modernize .. image:: https://coveralls.io/repos/python-modernize/python-modernize/badge.png?branch=master :target: https://coveralls.io/r/python-modernize/python-modernize?branch=master Platform: UNKNOWN Classifier: License :: OSI Approved :: BSD License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 3 modernize-0.7/modernize.egg-info/SOURCES.txt0000664000175000017500000000233713434507641023042 0ustar takluyvertakluyver00000000000000CHANGELOG.rst LICENSE MANIFEST.in README.rst modernize.py setup.cfg setup.py libmodernize/__init__.py libmodernize/main.py libmodernize/fixes/__init__.py libmodernize/fixes/fix_basestring.py libmodernize/fixes/fix_classic_division.py libmodernize/fixes/fix_dict_six.py libmodernize/fixes/fix_file.py libmodernize/fixes/fix_filter.py libmodernize/fixes/fix_import.py libmodernize/fixes/fix_imports_six.py libmodernize/fixes/fix_input_six.py libmodernize/fixes/fix_int_long_tuple.py libmodernize/fixes/fix_itertools_imports_six.py libmodernize/fixes/fix_itertools_six.py libmodernize/fixes/fix_map.py libmodernize/fixes/fix_metaclass.py libmodernize/fixes/fix_next.py libmodernize/fixes/fix_open.py libmodernize/fixes/fix_print.py libmodernize/fixes/fix_raise.py libmodernize/fixes/fix_raise_six.py libmodernize/fixes/fix_unichr.py libmodernize/fixes/fix_unicode.py libmodernize/fixes/fix_unicode_future.py libmodernize/fixes/fix_unicode_type.py libmodernize/fixes/fix_urllib_six.py libmodernize/fixes/fix_xrange_six.py libmodernize/fixes/fix_zip.py modernize.egg-info/PKG-INFO modernize.egg-info/SOURCES.txt modernize.egg-info/dependency_links.txt modernize.egg-info/entry_points.txt modernize.egg-info/not-zip-safe modernize.egg-info/top_level.txtmodernize-0.7/modernize.egg-info/dependency_links.txt0000664000175000017500000000000113434507641025217 0ustar takluyvertakluyver00000000000000 modernize-0.7/modernize.egg-info/entry_points.txt0000664000175000017500000000007513434507641024451 0ustar takluyvertakluyver00000000000000[console_scripts] python-modernize = libmodernize.main:main modernize-0.7/modernize.egg-info/not-zip-safe0000664000175000017500000000000113266571353023403 0ustar takluyvertakluyver00000000000000 modernize-0.7/modernize.egg-info/top_level.txt0000664000175000017500000000002713434507641023702 0ustar takluyvertakluyver00000000000000libmodernize modernize modernize-0.7/modernize.py0000664000175000017500000000015113434507331020022 0ustar takluyvertakluyver00000000000000from __future__ import absolute_import import sys from libmodernize.main import main sys.exit(main()) modernize-0.7/setup.cfg0000664000175000017500000000010313434507641017276 0ustar takluyvertakluyver00000000000000[bdist_wheel] universal = 1 [egg_info] tag_build = tag_date = 0 modernize-0.7/setup.py0000664000175000017500000000246013132653477017203 0ustar takluyvertakluyver00000000000000from __future__ import absolute_import import os, re from setuptools import setup readme = open(os.path.join(os.path.dirname(__file__), 'README.rst'), 'r').read() module_file = open(os.path.join(os.path.dirname(__file__), 'libmodernize', '__init__.py'), 'r').read() version_match = re.search(r"__version__ = ['\"]([^'\"]*)['\"]", module_file, re.M) if not version_match: raise Exception("couldn't find version number") version = version_match.group(1) setup( name='modernize', author='Armin Ronacher', author_email='armin.ronacher@active-4.com', version=version, url='https://github.com/python-modernize/python-modernize', packages=['libmodernize', 'libmodernize.fixes'], py_modules=['modernize'], description='A hack on top of 2to3 for modernizing code for ' 'hybrid codebases.', long_description=readme, entry_points={ 'console_scripts': [ 'python-modernize = libmodernize.main:main' ] }, zip_safe=False, tests_require='nose', test_suite='nose.collector', classifiers=[ 'License :: OSI Approved :: BSD License', 'Programming Language :: Python', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 3', ] )