diff --git a/bin/j2py b/bin/j2py index 6eb1a40..e967a58 100755 --- a/bin/j2py +++ b/bin/j2py @@ -17,7 +17,7 @@ from java2python.compiler import Module, buildAST, transformAST from java2python.config import Config from java2python.lib import escapes - +import codecs version = '0.5.1' @@ -107,7 +107,7 @@ def runTransform(options): try: if filein != '-': - source = open(filein).read() + source = codecs.open(filein,"r","utf-8").read() else: source = sys.stdin.read() except (IOError, ), exc: @@ -136,7 +136,7 @@ def runTransform(options): timed['visit_finish'] timed['encode'] - source = unicode(module) + source = module.__unicode__() timed['encode_finish'] timed['overall_finish'] diff --git a/j2py b/j2py new file mode 100755 index 0000000..e967a58 --- /dev/null +++ b/j2py @@ -0,0 +1,259 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" j2py -> Java to Python compiler script. + +This is all very ordinary. We import the package bits, open and read +a file, translate it, and write it out. + +""" +import sys +from argparse import ArgumentParser, ArgumentTypeError +from collections import defaultdict +from logging import _levelNames as logLevels, exception, warning, info, basicConfig +from os import path, makedirs +from time import time + +from java2python.compiler import Module, buildAST, transformAST +from java2python.config import Config +from java2python.lib import escapes + +import codecs +version = '0.5.1' + + +def logLevel(value): + """ Returns a valid logging level or raises and exception. """ + msg = 'invalid loglevel: %r' + try: + lvl = int(value) + except (ValueError, ): + name = value.upper() + if name not in logLevels: + raise ArgumentTypeError(msg % value) + lvl = logLevels[name] + else: + if lvl not in logLevels: + raise ArgumentTypeError(msg % value) + return lvl + + +def configFromDir(inname, dirname): + """ Returns a file name from the given config directory. """ + name = path.join(dirname, path.basename(path.splitext(inname)[0])) + return '%s.py' % path.abspath(name) + + +def runMain(options): + """ Runs our main function with profiling if indicated by options. """ + if options.profile: + import cProfile, pstats + prof = cProfile.Profile() + prof.runcall(runOneOrMany, options) + stats = pstats.Stats(prof, stream=sys.stderr) + stats.strip_dirs().sort_stats('cumulative') + stats.print_stats().print_callers() + return 0 + else: + return runOneOrMany(options) + +def runOneOrMany(options): + """ Runs our main transformer with each of the input files. """ + infile, outfile = options.inputfile, options.outputfile + + if infile and not isinstance(infile, file) and path.isdir(infile): + if outfile and not isinstance(outfile, file) and not path.isdir(outfile): + warning('Must specify output directory or stdout when using input directory.') + return 2 + def walker(arg, dirname, files): + for name in [name for name in files if name.endswith('.java')]: + fullname = path.join(dirname, name) + options.inputfile = fullname + info('opening %s', fullname) + if outfile and outfile != '-' and not isinstance(outfile, file): + full = path.abspath(path.join(outfile, fullname)) + head, tail = path.split(full) + tail = path.splitext(tail)[0] + '.py' + if not path.exists(head): + makedirs(head) + options.outputfile = path.join(head, tail) + runTransform(options) + path.walk(infile, walker, None) + return 0 + else: + return runTransform(options) + + +def runTransform(options): + """ Compile the indicated java source with the given options. """ + timed = defaultdict(time) + timed['overall'] + + filein = fileout = filedefault = '-' + if options.inputfile and not isinstance(options.inputfile, file): + filein = options.inputfile + if options.outputfile and not isinstance(options.outputfile, file): + fileout = options.outputfile + elif fileout != filedefault: + fileout = '%s.py' % (path.splitext(filein)[0]) + + configs = options.configs + if options.configdirs and not isinstance(filein, file): + for configdir in options.configdirs: + dirname = configFromDir(filein, configdir) + if path.exists(dirname): + configs.insert(0, dirname) + if options.includedefaults: + configs.insert(0, 'java2python.config.default') + + try: + if filein != '-': + source = codecs.open(filein,"r","utf-8").read() + else: + source = sys.stdin.read() + except (IOError, ), exc: + code, msg = exc.args[0:2] + print 'IOError: %s.' % (msg, ) + return code + + timed['comp'] + try: + tree = buildAST(source) + except (Exception, ), exc: + exception('exception while parsing') + return 1 + timed['comp_finish'] + + config = Config(configs) + timed['xform'] + transformAST(tree, config) + timed['xform_finish'] + + timed['visit'] + module = Module(config) + module.sourceFilename = path.abspath(filein) if filein != '-' else None + module.name = path.splitext(path.basename(filein))[0] if filein != '-' else '' + module.walk(tree) + timed['visit_finish'] + + timed['encode'] + source = module.__unicode__() + timed['encode_finish'] + timed['overall_finish'] + + if options.lexertokens: + for idx, tok in enumerate(tree.parser.input.tokens): + print >> sys.stderr, '{0} {1}'.format(idx, tok) + print >> sys.stderr + + if options.javaast: + tree.dump(sys.stderr) + print >> sys.stderr + + if options.pytree: + module.dumpRepr(sys.stderr) + print >> sys.stderr + + if not options.skipsource: + if fileout == filedefault: + output = sys.stdout + else: + output = open(fileout, 'w') + module.name = path.splitext(filein)[0] if filein != '-' else '' + print >> output, source + + if not options.skipcompile: + try: + compile(source, '', 'exec') + except (SyntaxError, ), ex: + warning('Generated source has invalid syntax. %s', ex) + else: + info('Generated source has valid syntax.') + + info('Parse: %.4f seconds', timed['comp_finish'] - timed['comp']) + info('Visit: %.4f seconds', timed['visit_finish'] - timed['visit']) + info('Transform: %.4f seconds', timed['xform_finish'] - timed['xform']) + info('Encode: %.4f seconds', timed['encode_finish'] - timed['encode']) + info('Total: %.4f seconds', timed['overall_finish'] - timed['overall']) + return 0 + + +def isWindows(): + """ True if running on Windows. """ + return sys.platform.startswith('win') + + +def configLogging(loglevel): + """ Configure the logging package. """ + fmt = '# %(levelname)s %(funcName)s: %(message)s' + basicConfig(level=loglevel, format=fmt) + + +def configColors(nocolor): + """ Configure the color escapes. """ + if isWindows() or nocolor: + escapes.clear() + + +def configScript(argv): + """ Return an options object from the given argument sequence. """ + parser = ArgumentParser( + description='Translate Java source code to Python.', + epilog='Refer to https://github.com/natural/java2python for docs and support.' + ) + + add = parser.add_argument + add(dest='inputfile', nargs='?', + help='Read from INPUT. May use - for stdin (default).', + metavar='INPUT', default=None) + add(dest='outputfile', nargs='?', + help='Write to OUTPUT. May use - for stdout (default).', + metavar='OUTPUT', default=None) + add('-c', '--config', dest='configs', + help='Use CONFIG file or module. May be repeated.', + metavar='CONFIG', default=[], action='append') + add('-d', '--config-dir', dest='configdirs', + help='Use DIR to match input filename with config filename.', + metavar='DIR', default=[], action='append') + add('-f', '--profile', dest='profile', + help='Profile execution and print results to stderr.', + default=False, action='store_true') + add('-j', '--java-ast', dest='javaast', + help='Print java source AST tree to stderr.', + default=False, action='store_true') + add('-k', '--skip-compile', dest='skipcompile', + help='Skip compile check on translated source.', + default=False, action='store_true') + add('-l', '--log-level', dest='loglevel', + help='Set log level by name or value.', + default='WARN', type=logLevel) + add('-n', '--no-defaults', dest='includedefaults', + help='Ignore default configuration module.', + default=True, action='store_false') + add('-p', '--python-tree', dest='pytree', + help='Print python object tree to stderr.', + default=False, action='store_true') + add('-r', '--no-color', dest='nocolor', + help='Disable color output.' +\ + (' No effect on Win OS.' if isWindows() else ''), + default=False, action='store_true') + add('-s', '--skip-source', dest='skipsource', + help='Skip writing translated source; useful when printing trees', + default=False, action='store_true') + add('-t', '--lexer-tokens', dest='lexertokens', + help='Print lexer tokens to stderr.', + default=False, action='store_true') + add('-v', '--version', action='version', version='%(prog)s ' + version) + + ns = parser.parse_args(argv) + if ns.inputfile == '-': + ns.inputfile = sys.stdin + if ns.outputfile == '-': + ns.outputfile = sys.stdout + + configColors(ns.nocolor) + configLogging(ns.loglevel) + return ns + + +if __name__ == '__main__': + sys.exit(runMain(configScript(sys.argv[1:]))) diff --git a/java2python/compiler/template.py b/java2python/compiler/template.py index e117df3..b8d3386 100644 --- a/java2python/compiler/template.py +++ b/java2python/compiler/template.py @@ -19,8 +19,7 @@ from java2python.lang import tokens from java2python.lib import FS, colors - - +from java2python.utils import *; class Factory(object): """ Factory -> creates pre-configured callables for new block instances. @@ -73,7 +72,7 @@ def __init__(cls, name, bases, namespace): except (AttributeError, ): pass - +@python_2_unicode_compatible class Base(object): """ Base -> base class for formatting Python output. @@ -290,7 +289,7 @@ def wrapper(*a, **b): yield value return wrapper - +@python_2_unicode_compatible class Expression(Base): """ Expression -> formatting for Python expressions. """ @@ -321,7 +320,12 @@ def __repr__(self): def __str__(self): """ Returns the Python source code representation of this template. """ - return self.fs.format(left=self.left, right=self.right) + self.tail + #print "==========" + fs=unicode(self.fs) + #print fs,":",self.left,",",self.right + #print type(fs),type(self.left),type(self.right) + r=fs.format(left=self.left, right=self.right) + return r + self.tail def dump(self, fd, level=0): """ Writes the Python source code for this template to the given file. """ diff --git a/java2python/compiler/visitor.py b/java2python/compiler/visitor.py index 4109883..cf398fa 100644 --- a/java2python/compiler/visitor.py +++ b/java2python/compiler/visitor.py @@ -19,7 +19,7 @@ from java2python.lang import tokens from java2python.lib import FS - +from java2python.utils import * class Memo(object): """ Memo -> AST walking luggage. """ diff --git a/java2python/utils/__init__.py b/java2python/utils/__init__.py new file mode 100644 index 0000000..8b145bd --- /dev/null +++ b/java2python/utils/__init__.py @@ -0,0 +1,17 @@ +import six +def python_2_unicode_compatible(klass): + """ +A decorator that defines __unicode__ and __str__ methods under Python 2. +Under Python 3 it does nothing. + +To support Python 2 and 3 with a single code base, define a __str__ method +returning text and apply this decorator to the class. +""" + if six.PY2: + if '__str__' not in klass.__dict__: + raise ValueError("@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % + klass.__name__) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode('utf-8') + return klass \ No newline at end of file diff --git a/java2python/utils/six.py b/java2python/utils/six.py new file mode 100644 index 0000000..0b1b3f9 --- /dev/null +++ b/java2python/utils/six.py @@ -0,0 +1,662 @@ +"""Utilities for writing code that runs on Python 2 and 3""" + +# Copyright (c) 2010-2014 Benjamin Peterson +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import operator +import sys +import types + +__author__ = "Benjamin Peterson " +__version__ = "1.5.2" + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + result = self._resolve() + setattr(obj, self.name, result) # Invokes __set__. + # This is a bit ugly, but it avoids running this again. + delattr(obj.__class__, self.name) + return result + + +class MovedModule(_LazyDescr): + + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + def __getattr__(self, attr): + # Hack around the Django autoreloader. The reloader tries to get + # __file__ or __name__ of every module in sys.modules. This doesn't work + # well if this MovedModule is for an module that is unavailable on this + # machine (like winreg on Unix systems). Thus, we pretend __file__ and + # __name__ don't exist if the module hasn't been loaded yet. See issues + # #51 and #53. + if attr in ("__file__", "__name__") and self.mod not in sys.modules: + raise AttributeError + _module = self._resolve() + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + + +class MovedAttribute(_LazyDescr): + + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + + +class _MovedItems(_LazyModule): + """Lazy loading of moved objects""" + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("reload_module", "__builtin__", "imp", "reload"), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserString", "UserString", "collections"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), + + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", + "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", + "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", + "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("winreg", "_winreg"), +] +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + sys.modules[__name__ + ".moves." + attr.name] = attr +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = sys.modules[__name__ + ".moves"] = _MovedItems(__name__ + ".moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("urlencode", "urllib", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +sys.modules[__name__ + ".moves.urllib_parse"] = sys.modules[__name__ + ".moves.urllib.parse"] = Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse") + + +class Module_six_moves_urllib_error(_LazyModule): + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +sys.modules[__name__ + ".moves.urllib_error"] = sys.modules[__name__ + ".moves.urllib.error"] = Module_six_moves_urllib_error(__name__ + ".moves.urllib.error") + + +class Module_six_moves_urllib_request(_LazyModule): + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), +] +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +sys.modules[__name__ + ".moves.urllib_request"] = sys.modules[__name__ + ".moves.urllib.request"] = Module_six_moves_urllib_request(__name__ + ".moves.urllib.request") + + +class Module_six_moves_urllib_response(_LazyModule): + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +sys.modules[__name__ + ".moves.urllib_response"] = sys.modules[__name__ + ".moves.urllib.response"] = Module_six_moves_urllib_response(__name__ + ".moves.urllib.response") + + +class Module_six_moves_urllib_robotparser(_LazyModule): + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) +del attr + +Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes + +sys.modules[__name__ + ".moves.urllib_robotparser"] = sys.modules[__name__ + ".moves.urllib.robotparser"] = Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser") + + +class Module_six_moves_urllib(types.ModuleType): + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + parse = sys.modules[__name__ + ".moves.urllib_parse"] + error = sys.modules[__name__ + ".moves.urllib_error"] + request = sys.modules[__name__ + ".moves.urllib_request"] + response = sys.modules[__name__ + ".moves.urllib_response"] + robotparser = sys.modules[__name__ + ".moves.urllib_robotparser"] + + def __dir__(self): + return ['parse', 'error', 'request', 'response', 'robotparser'] + + +sys.modules[__name__ + ".moves.urllib"] = Module_six_moves_urllib(__name__ + ".moves.urllib") + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_closure = "__closure__" + _func_code = "__code__" + _func_defaults = "__defaults__" + _func_globals = "__globals__" + + _iterkeys = "keys" + _itervalues = "values" + _iteritems = "items" + _iterlists = "lists" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_closure = "func_closure" + _func_code = "func_code" + _func_defaults = "func_defaults" + _func_globals = "func_globals" + + _iterkeys = "iterkeys" + _itervalues = "itervalues" + _iteritems = "iteritems" + _iterlists = "iterlists" + + +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + +try: + callable = callable +except NameError: + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + + +if PY3: + def get_unbound_function(unbound): + return unbound + + create_bound_method = types.MethodType + + Iterator = object +else: + def get_unbound_function(unbound): + return unbound.im_func + + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + class Iterator(object): + + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc(get_unbound_function, + """Get the function out of a possibly unbound function""") + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) + + +def iterkeys(d, **kw): + """Return an iterator over the keys of a dictionary.""" + return iter(getattr(d, _iterkeys)(**kw)) + +def itervalues(d, **kw): + """Return an iterator over the values of a dictionary.""" + return iter(getattr(d, _itervalues)(**kw)) + +def iteritems(d, **kw): + """Return an iterator over the (key, value) pairs of a dictionary.""" + return iter(getattr(d, _iteritems)(**kw)) + +def iterlists(d, **kw): + """Return an iterator over the (key, [values]) pairs of a dictionary.""" + return iter(getattr(d, _iterlists)(**kw)) + + +if PY3: + def b(s): + return s.encode("latin-1") + def u(s): + return s + unichr = chr + if sys.version_info[1] <= 1: + def int2byte(i): + return bytes((i,)) + else: + # This is about 2x faster than the implementation above on 3.2+ + int2byte = operator.methodcaller("to_bytes", 1, "big") + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + StringIO = io.StringIO + BytesIO = io.BytesIO +else: + def b(s): + return s + # Workaround for standalone backslash + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr + int2byte = chr + def byte2int(bs): + return ord(bs[0]) + def indexbytes(buf, i): + return ord(buf[i]) + def iterbytes(buf): + return (ord(byte) for byte in buf) + import StringIO + StringIO = BytesIO = StringIO.StringIO +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + + def reraise(tp, value, tb=None): + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + +else: + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + + + exec_("""def reraise(tp, value, tb=None): + raise tp, value, tb +""") + + +print_ = getattr(moves.builtins, "print", None) +if print_ is None: + def print_(*args, **kwargs): + """The new-style print function for Python 2.4 and 2.5.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + def write(data): + if not isinstance(data, basestring): + data = str(data) + # If the file has an encoding, encode unicode with it. + if (isinstance(fp, file) and + isinstance(data, unicode) and + fp.encoding is not None): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) + +_add_doc(reraise, """Reraise an exception.""") + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + return meta("NewBase", bases, {}) + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + + +### Additional customizations for Django ### + +if PY3: + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" + memoryview = memoryview +else: + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + # memoryview and buffer are not stricly equivalent, but should be fine for + # django core usage (mainly BinaryField). However, Jython doesn't support + # buffer (see http://bugs.jython.org/issue1521), so we have to be careful. + if sys.platform.startswith('java'): + memoryview = memoryview + else: + memoryview = buffer + + +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) + + +add_move(MovedModule("_dummy_thread", "dummy_thread")) +add_move(MovedModule("_thread", "thread"))