diff --git a/python/helpers/profiler/_imps/_pydev_pkgutil_old.py b/python/helpers/profiler/_imps/_pydev_pkgutil_old.py index fae295a800e4..f69655c05179 100644 --- a/python/helpers/profiler/_imps/_pydev_pkgutil_old.py +++ b/python/helpers/profiler/_imps/_pydev_pkgutil_old.py @@ -3,10 +3,10 @@ # NOTE: This module must remain compatible with Python 2.3, as it is shared # by setuptools for distribution with Python 2.3 and up. -import imp import os -import os.path import sys +import imp +import os.path from types import ModuleType __all__ = [ @@ -540,7 +540,7 @@ def extend_path(path, name): if os.path.isfile(pkgfile): try: f = open(pkgfile) - except IOError, msg: + except IOError as msg: sys.stderr.write("Can't open %s: %s\n" % (pkgfile, msg)) else: diff --git a/python/helpers/pydev/MANIFEST.in b/python/helpers/pydev/MANIFEST.in new file mode 100644 index 000000000000..d44f18c04e10 --- /dev/null +++ b/python/helpers/pydev/MANIFEST.in @@ -0,0 +1,4 @@ +include *.rst *.txt *.md LICENSE VERSION *.pyx +recursive-include pydevd_attach_to_process *.py *.dll *.so *.dylib *.txt *.c *.h *.bat Makefile *.sh *.pyx +recursive-include _pydevd_bundle *.pyx +recursive-include build_tools *.py \ No newline at end of file diff --git a/python/helpers/pydev/README.rst b/python/helpers/pydev/README.rst index 2843d88120a8..1a1818598442 100644 --- a/python/helpers/pydev/README.rst +++ b/python/helpers/pydev/README.rst @@ -9,27 +9,22 @@ In general, the debugger backend should **NOT** be installed separately if you'r bundles it (such as PyDev or PyCharm). It is however available in PyPi so that it can be installed for doing remote debugging with `pip` -- so, when -debugging a process which runs in another machine, it's possible to `pip install pydevd` and in the code use -`pydevd.settrace(host='10.1.1.1')` to connect the debugger backend to the debugger UI running in the IDE +debugging a process which runs in another machine, it's possible to `pip install pydevd-pycharm` and in the code use +`pydevd_pycharm.settrace(host='10.1.1.1')` to connect the debugger backend to the debugger UI running in the IDE (whereas previously the sources had to be manually copied from the IDE installation). -It should be compatible with Python 2.4 onwards (as well as Jython 2.2.1, IronPython and PyPy -- and +It should be compatible with Python 2.6 onwards (as well as Jython 2.7, IronPython and PyPy -- and any other variant which properly supports the Python structure for debuggers -- i.e.: sys.settrace/threading.settrace). Recent versions contain speedup modules using Cython, which are generated with a few changes in the regular files to `cythonize` the files. To update and compile the cython sources (and generate some other auto-generated files), `build_tools/build.py` should be run -- note that the resulting .pyx and .c files should be commited. -To see performance changes, see: - -https://www.speedtin.com/reports/7_pydevd_cython (performance results with cython). -https://www.speedtin.com/reports/8_pydevd_pure_python (performance results without cython). - To generate a distribution with the precompiled binaries for the IDE, `build_binaries_windows.py` should be run ( note that the environments must be pre-created as specified in that file). To generate a distribution to upload to PyPi, `python setup.py sdist bdist_wheel` should be run for each python version -which should have a wheel and afterwards `twine upload -s dist/pydevd-*` shoud be run to actually upload the contents +which should have a wheel and afterwards `twine upload -s dist/pydevd-*` should be run to actually upload the contents to PyPi. Travis (Linux CI): diff --git a/python/helpers/pydev/_pydev_imps/_pydev_BaseHTTPServer.py b/python/helpers/pydev/_pydev_imps/_pydev_BaseHTTPServer.py index f8dd911127f6..5d8a320d1f27 100644 --- a/python/helpers/pydev/_pydev_imps/_pydev_BaseHTTPServer.py +++ b/python/helpers/pydev/_pydev_imps/_pydev_BaseHTTPServer.py @@ -596,7 +596,7 @@ def test(HandlerClass = BaseHTTPRequestHandler, httpd = ServerClass(server_address, HandlerClass) sa = httpd.socket.getsockname() - print ("Serving HTTP on", sa[0], "port", sa[1], "...") + print("Serving HTTP on", sa[0], "port", sa[1], "...") httpd.serve_forever() diff --git a/python/helpers/pydev/_pydev_imps/_pydev_SimpleXMLRPCServer.py b/python/helpers/pydev/_pydev_imps/_pydev_SimpleXMLRPCServer.py index c5f77426a6e0..20a8adb0f0f9 100644 --- a/python/helpers/pydev/_pydev_imps/_pydev_SimpleXMLRPCServer.py +++ b/python/helpers/pydev/_pydev_imps/_pydev_SimpleXMLRPCServer.py @@ -260,7 +260,7 @@ class SimpleXMLRPCDispatcher: response = (response,) response = xmlrpclib.dumps(response, methodresponse=1, allow_none=self.allow_none, encoding=self.encoding) - except Fault, fault: + except Fault as fault: response = xmlrpclib.dumps(fault, allow_none=self.allow_none, encoding=self.encoding) except: @@ -363,7 +363,7 @@ class SimpleXMLRPCDispatcher: # XXX A marshalling error in any response will fail the entire # multicall. If someone cares they should fix this. results.append([self._dispatch(method_name, params)]) - except Fault, fault: + except Fault as fault: results.append( {'faultCode' : fault.faultCode, 'faultString' : fault.faultString} diff --git a/python/helpers/pydev/_pydev_imps/_pydev_SocketServer.py b/python/helpers/pydev/_pydev_imps/_pydev_SocketServer.py index 7af2777ac7ea..0595b9f3c93e 100644 --- a/python/helpers/pydev/_pydev_imps/_pydev_SocketServer.py +++ b/python/helpers/pydev/_pydev_imps/_pydev_SocketServer.py @@ -336,12 +336,12 @@ class BaseServer: The default is to print a traceback and continue. """ - print '-'*40 - print 'Exception happened during processing of request from', - print client_address + print('-'*40) + print('Exception happened during processing of request from') + print(client_address) import traceback traceback.print_exc() # XXX But this goes to stderr! - print '-'*40 + print('-'*40) class TCPServer(BaseServer): @@ -528,7 +528,7 @@ class ForkingMixIn: if not pid: continue try: self.active_children.remove(pid) - except ValueError, e: + except ValueError as e: raise ValueError('%s. x=%d and list=%r' % (e.message, pid, self.active_children)) diff --git a/python/helpers/pydev/_pydev_imps/_pydev_inspect.py b/python/helpers/pydev/_pydev_imps/_pydev_inspect.py index 5fd33d876c1b..56657d400b91 100644 --- a/python/helpers/pydev/_pydev_imps/_pydev_inspect.py +++ b/python/helpers/pydev/_pydev_imps/_pydev_inspect.py @@ -1,3 +1,4 @@ +# -*- coding: iso-8859-1 -*- """Get useful information from live Python objects. This module encapsulates the interface provided by the internal special @@ -6,8 +7,9 @@ It also provides some help for examining source code and class layout. Here are some of the useful functions provided by this module: - ismodule(), isclass(), ismethod(), isfunction(), istraceback(), - isframe(), iscode(), isbuiltin(), isroutine() - check object types + ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(), + isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(), + isroutine() - check object types getmembers() - get members of an object that satisfy a given condition getfile(), getsourcefile(), getsource() - find an object's source code @@ -15,7 +17,7 @@ Here are some of the useful functions provided by this module: getmodule() - determine the module that an object came from getclasstree() - arrange classes so as to represent their hierarchy - getargspec(), getargvalues() - get info about function arguments + getargspec(), getargvalues(), getcallargs() - get info about function arguments formatargspec(), formatargvalues() - format an argument spec getouterframes(), getinnerframes() - get info about frames currentframe() - get the current stack frame @@ -27,7 +29,23 @@ Here are some of the useful functions provided by this module: __author__ = 'Ka-Ping Yee ' __date__ = '1 Jan 2001' -import sys, os, types, string, re, imp, tokenize +import sys +import os +import types +import string +import re +import dis +import imp +import tokenize +import linecache +from operator import attrgetter +from collections import namedtuple + +# These constants are from Include/code.h. +CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 0x1, 0x2, 0x4, 0x8 +CO_NESTED, CO_GENERATOR, CO_NOFREE = 0x10, 0x20, 0x40 +# See Include/object.h +TPFLAGS_IS_ABSTRACT = 1 << 20 # ----------------------------------------------------------- type-checking def ismodule(object): @@ -44,7 +62,7 @@ def isclass(object): Class objects provide these attributes: __doc__ documentation string __module__ name of module in which this class was defined""" - return isinstance(object, types.ClassType) or hasattr(object, '__bases__') + return isinstance(object, (type, types.ClassType)) def ismethod(object): """Return true if the object is an instance method. @@ -77,6 +95,50 @@ def ismethoddescriptor(object): and not isfunction(object) and not isclass(object)) +def isdatadescriptor(object): + """Return true if the object is a data descriptor. + + Data descriptors have both a __get__ and a __set__ attribute. Examples are + properties (defined in Python) and getsets and members (defined in C). + Typically, data descriptors will also have __name__ and __doc__ attributes + (properties, getsets, and members have both of these attributes), but this + is not guaranteed.""" + return (hasattr(object, "__set__") and hasattr(object, "__get__")) + +if hasattr(types, 'MemberDescriptorType'): + # CPython and equivalent + def ismemberdescriptor(object): + """Return true if the object is a member descriptor. + + Member descriptors are specialized descriptors defined in extension + modules.""" + return isinstance(object, types.MemberDescriptorType) +else: + # Other implementations + def ismemberdescriptor(object): + """Return true if the object is a member descriptor. + + Member descriptors are specialized descriptors defined in extension + modules.""" + return False + +if hasattr(types, 'GetSetDescriptorType'): + # CPython and equivalent + def isgetsetdescriptor(object): + """Return true if the object is a getset descriptor. + + getset descriptors are specialized descriptors defined in extension + modules.""" + return isinstance(object, types.GetSetDescriptorType) +else: + # Other implementations + def isgetsetdescriptor(object): + """Return true if the object is a getset descriptor. + + getset descriptors are specialized descriptors defined in extension + modules.""" + return False + def isfunction(object): """Return true if the object is a user-defined function. @@ -90,6 +152,32 @@ def isfunction(object): func_name (same as __name__)""" return isinstance(object, types.FunctionType) +def isgeneratorfunction(object): + """Return true if the object is a user-defined generator function. + + Generator function objects provides same attributes as functions. + + See help(isfunction) for attributes listing.""" + return bool((isfunction(object) or ismethod(object)) and + object.func_code.co_flags & CO_GENERATOR) + +def isgenerator(object): + """Return true if the object is a generator. + + Generator objects provide these attributes: + __iter__ defined to support iteration over container + close raises a new GeneratorExit exception inside the + generator to terminate the iteration + gi_code code object + gi_frame frame object or possibly None once the generator has + been exhausted + gi_running set to 1 when generator is executing, 0 otherwise + next return the next item from the container + send resumes the generator and "sends" a value that becomes + the result of the current yield-expression + throw used to raise an exception inside the generator""" + return isinstance(object, types.GeneratorType) + def istraceback(object): """Return true if the object is a traceback. @@ -152,17 +240,26 @@ def isroutine(object): or ismethod(object) or ismethoddescriptor(object)) +def isabstract(object): + """Return true if the object is an abstract base class (ABC).""" + return bool(isinstance(object, type) and object.__flags__ & TPFLAGS_IS_ABSTRACT) + def getmembers(object, predicate=None): """Return all members of an object as (name, value) pairs sorted by name. Optionally, only return members that satisfy a given predicate.""" results = [] for key in dir(object): - value = getattr(object, key) + try: + value = getattr(object, key) + except AttributeError: + continue if not predicate or predicate(value): results.append((key, value)) results.sort() return results +Attribute = namedtuple('Attribute', 'name kind defining_class object') + def classify_class_attrs(cls): """Return list of attribute-descriptor tuples. @@ -191,30 +288,21 @@ def classify_class_attrs(cls): names = dir(cls) result = [] for name in names: - # Get the object associated with the name. + # Get the object associated with the name, and where it was defined. # Getting an obj from the __dict__ sometimes reveals more than # using getattr. Static and class methods are dramatic examples. - if name in cls.__dict__: - obj = cls.__dict__[name] + # Furthermore, some objects may raise an Exception when fetched with + # getattr(). This is the case with some descriptors (bug #1785). + # Thus, we only use getattr() as a last resort. + homecls = None + for base in (cls,) + mro: + if name in base.__dict__: + obj = base.__dict__[name] + homecls = base + break else: obj = getattr(cls, name) - - # Figure out where it was defined. - homecls = getattr(obj, "__objclass__", None) - if homecls is None: - # search the dicts. - for base in mro: - if name in base.__dict__: - homecls = base - break - - # Get the object again, in order to get it from the defining - # __dict__ instead of via getattr (if possible). - if homecls is not None and name in homecls.__dict__: - obj = homecls.__dict__[name] - - # Also get the object via getattr. - obj_via_getattr = getattr(cls, name) + homecls = getattr(obj, "__objclass__", homecls) # Classify the object. if isinstance(obj, staticmethod): @@ -223,13 +311,20 @@ def classify_class_attrs(cls): kind = "class method" elif isinstance(obj, property): kind = "property" - elif (ismethod(obj_via_getattr) or - ismethoddescriptor(obj_via_getattr)): + elif ismethoddescriptor(obj): kind = "method" - else: + elif isdatadescriptor(obj): kind = "data" + else: + obj_via_getattr = getattr(cls, name) + if (ismethod(obj_via_getattr) or + ismethoddescriptor(obj_via_getattr)): + kind = "method" + else: + kind = "data" + obj = obj_via_getattr - result.append((name, kind, homecls, obj)) + result.append(Attribute(name, kind, homecls, obj)) return result @@ -267,22 +362,37 @@ def getdoc(object): doc = object.__doc__ except AttributeError: return None - if not isinstance(doc, (str, unicode)): + if not isinstance(doc, types.StringTypes): return None + return cleandoc(doc) + +def cleandoc(doc): + """Clean up indentation from docstrings. + + Any whitespace that can be uniformly removed from the second line + onwards is removed.""" try: lines = string.split(string.expandtabs(doc), '\n') except UnicodeError: return None else: - margin = None + # Find minimum indentation of any non-blank lines after first line. + margin = sys.maxint for line in lines[1:]: content = len(string.lstrip(line)) - if not content: continue - indent = len(line) - content - if margin is None: margin = indent - else: margin = min(margin, indent) - if margin is not None: + if content: + indent = len(line) - content + margin = min(margin, indent) + # Remove indentation. + if lines: + lines[0] = lines[0].lstrip() + if margin < sys.maxint: for i in range(1, len(lines)): lines[i] = lines[i][margin:] + # Remove any trailing or leading blank lines. + while lines and not lines[-1]: + lines.pop() + while lines and not lines[0]: + lines.pop(0) return string.join(lines, '\n') def getfile(object): @@ -290,12 +400,12 @@ def getfile(object): if ismodule(object): if hasattr(object, '__file__'): return object.__file__ - raise TypeError, 'arg is a built-in module' + raise TypeError('{!r} is a built-in module'.format(object)) if isclass(object): object = sys.modules.get(object.__module__) if hasattr(object, '__file__'): return object.__file__ - raise TypeError, 'arg is a built-in class' + raise TypeError('{!r} is a built-in class'.format(object)) if ismethod(object): object = object.im_func if isfunction(object): @@ -306,18 +416,21 @@ def getfile(object): object = object.f_code if iscode(object): return object.co_filename - raise TypeError, 'arg is not a module, class, method, ' \ - 'function, traceback, frame, or code object' + raise TypeError('{!r} is not a module, class, method, ' + 'function, traceback, frame, or code object'.format(object)) + +ModuleInfo = namedtuple('ModuleInfo', 'name suffix mode module_type') def getmoduleinfo(path): """Get the module name, suffix, mode, and module type for a given file.""" filename = os.path.basename(path) - suffixes = map(lambda (suffix, mode, mtype): - (-len(suffix), suffix, mode, mtype), imp.get_suffixes()) + suffixes = map(lambda info: + (-len(info[0]), info[0], info[1], info[2]), + imp.get_suffixes()) suffixes.sort() # try longest suffixes first, in case they overlap for neglen, suffix, mode, mtype in suffixes: if filename[neglen:] == suffix: - return filename[:neglen], suffix, mode, mtype + return ModuleInfo(filename[:neglen], suffix, mode, mtype) def getmodulename(path): """Return the module name for a given file, or None.""" @@ -325,9 +438,11 @@ def getmodulename(path): if info: return info[0] def getsourcefile(object): - """Return the Python source file an object was defined in, if it exists.""" + """Return the filename that can be used to locate an object's source. + Return None if no way can be identified to get the source. + """ filename = getfile(object) - if string.lower(filename[-4:]) in ['.pyc', '.pyo']: + if string.lower(filename[-4:]) in ('.pyc', '.pyo'): filename = filename[:-4] + '.py' for suffix, mode, kind in imp.get_suffixes(): if 'b' in mode and string.lower(filename[-len(suffix):]) == suffix: @@ -335,39 +450,65 @@ def getsourcefile(object): return None if os.path.exists(filename): return filename + # only return a non-existent filename if the module has a PEP 302 loader + if hasattr(getmodule(object, filename), '__loader__'): + return filename + # or it is in the linecache + if filename in linecache.cache: + return filename -def getabsfile(object): +def getabsfile(object, _filename=None): """Return an absolute path to the source or compiled file for an object. The idea is for each object to have a unique origin, so this routine normalizes the result as much as possible.""" - return os.path.normcase( - os.path.abspath(getsourcefile(object) or getfile(object))) + if _filename is None: + _filename = getsourcefile(object) or getfile(object) + return os.path.normcase(os.path.abspath(_filename)) modulesbyfile = {} +_filesbymodname = {} -def getmodule(object): +def getmodule(object, _filename=None): """Return the module an object was defined in, or None if not found.""" if ismodule(object): return object - if isclass(object): + if hasattr(object, '__module__'): return sys.modules.get(object.__module__) + # Try the filename to modulename cache + if _filename is not None and _filename in modulesbyfile: + return sys.modules.get(modulesbyfile[_filename]) + # Try the cache again with the absolute file name try: - file = getabsfile(object) + file = getabsfile(object, _filename) except TypeError: return None - if modulesbyfile.has_key(file): - return sys.modules[modulesbyfile[file]] - for module in sys.modules.values(): - if hasattr(module, '__file__'): - modulesbyfile[getabsfile(module)] = module.__name__ - if modulesbyfile.has_key(file): - return sys.modules[modulesbyfile[file]] + if file in modulesbyfile: + return sys.modules.get(modulesbyfile[file]) + # Update the filename to module name cache and check yet again + # Copy sys.modules in order to cope with changes while iterating + for modname, module in sys.modules.items(): + if ismodule(module) and hasattr(module, '__file__'): + f = module.__file__ + if f == _filesbymodname.get(modname, None): + # Have already mapped this module, so skip it + continue + _filesbymodname[modname] = f + f = getabsfile(module) + # Always map to the name the module knows itself by + modulesbyfile[f] = modulesbyfile[ + os.path.realpath(f)] = module.__name__ + if file in modulesbyfile: + return sys.modules.get(modulesbyfile[file]) + # Check the main module main = sys.modules['__main__'] + if not hasattr(object, '__name__'): + return None if hasattr(main, object.__name__): mainobject = getattr(main, object.__name__) if mainobject is object: return main + # Check builtins builtin = sys.modules['__builtin__'] if hasattr(builtin, object.__name__): builtinobject = getattr(builtin, object.__name__) @@ -381,22 +522,46 @@ def findsource(object): or code object. The source code is returned as a list of all the lines in the file and the line number indexes a line in that list. An IOError is raised if the source code cannot be retrieved.""" - try: - file = open(getsourcefile(object)) - except (TypeError, IOError): - raise IOError, 'could not get source code' - lines = file.readlines() - file.close() + + file = getfile(object) + sourcefile = getsourcefile(object) + if not sourcefile and file[:1] + file[-1:] != '<>': + raise IOError('source code not available') + file = sourcefile if sourcefile else file + + module = getmodule(object, file) + if module: + lines = linecache.getlines(file, module.__dict__) + else: + lines = linecache.getlines(file) + if not lines: + raise IOError('could not get source code') if ismodule(object): return lines, 0 if isclass(object): name = object.__name__ - pat = re.compile(r'^\s*class\s*' + name + r'\b') + pat = re.compile(r'^(\s*)class\s*' + name + r'\b') + # make some effort to find the best matching class definition: + # use the one with the least indentation, which is the one + # that's most probably not inside a function definition. + candidates = [] for i in range(len(lines)): - if pat.match(lines[i]): return lines, i - else: raise IOError, 'could not find class definition' + match = pat.match(lines[i]) + if match: + # if it's at toplevel, it's already the best one + if lines[i][0] == 'c': + return lines, i + # else add whitespace to candidate list + candidates.append((match.group(1), i)) + if candidates: + # this will sort by whitespace, and by line number, + # less whitespace first + candidates.sort() + return lines, candidates[0][1] + else: + raise IOError('could not find class definition') if ismethod(object): object = object.im_func @@ -408,25 +573,30 @@ def findsource(object): object = object.f_code if iscode(object): if not hasattr(object, 'co_firstlineno'): - raise IOError, 'could not find function definition' + raise IOError('could not find function definition') lnum = object.co_firstlineno - 1 - pat = re.compile(r'^(\s*def\s)|(.*\slambda(:|\s))') + pat = re.compile(r'^(\s*def\s)|(.*(? 0: if pat.match(lines[lnum]): break lnum = lnum - 1 return lines, lnum - raise IOError, 'could not find code object' + raise IOError('could not find code object') def getcomments(object): - """Get lines of comments immediately preceding an object's source code.""" - try: lines, lnum = findsource(object) - except IOError: return None + """Get lines of comments immediately preceding an object's source code. + + Returns None when source can't be found. + """ + try: + lines, lnum = findsource(object) + except (IOError, TypeError): + return None if ismodule(object): # Look for a comment block at the top of the file. start = 0 if lines and lines[0][:2] == '#!': start = 1 - while start < len(lines) and string.strip(lines[start]) in ['', '#']: + while start < len(lines) and string.strip(lines[start]) in ('', '#'): start = start + 1 if start < len(lines) and lines[start][:1] == '#': comments = [] @@ -441,7 +611,7 @@ def getcomments(object): indent = indentsize(lines[lnum]) end = lnum - 1 if end >= 0 and string.lstrip(lines[end])[:1] == '#' and \ - indentsize(lines[end]) == indent: + indentsize(lines[end]) == indent: comments = [string.lstrip(string.expandtabs(lines[end]))] if end > 0: end = end - 1 @@ -457,49 +627,57 @@ def getcomments(object): comments[-1:] = [] return string.join(comments, '') -class ListReader: - """Provide a readline() method to return lines from a list of strings.""" - def __init__(self, lines): - self.lines = lines - self.index = 0 - - def readline(self): - i = self.index - if i < len(self.lines): - self.index = i + 1 - return self.lines[i] - else: return '' - class EndOfBlock(Exception): pass class BlockFinder: """Provide a tokeneater() method to detect the end of a code block.""" def __init__(self): self.indent = 0 - self.started = 0 - self.last = 0 + self.islambda = False + self.started = False + self.passline = False + self.last = 1 - def tokeneater(self, type, token, (srow, scol), (erow, ecol), line): + def tokeneater(self, type, token, srow_scol, erow_ecol, line): + srow, scol = srow_scol + erow, ecol = erow_ecol if not self.started: - if type == tokenize.NAME: self.started = 1 + # look for the first "def", "class" or "lambda" + if token in ("def", "class", "lambda"): + if token == "lambda": + self.islambda = True + self.started = True + self.passline = True # skip to the end of the line elif type == tokenize.NEWLINE: + self.passline = False # stop skipping when a NEWLINE is seen self.last = srow + if self.islambda: # lambdas always end at the first NEWLINE + raise EndOfBlock + elif self.passline: + pass elif type == tokenize.INDENT: self.indent = self.indent + 1 + self.passline = True elif type == tokenize.DEDENT: self.indent = self.indent - 1 - if self.indent == 0: raise EndOfBlock, self.last - elif type == tokenize.NAME and scol == 0: - raise EndOfBlock, self.last + # the end of matching indent/dedent pairs end a block + # (note that this only works for "def"/"class" blocks, + # not e.g. for "if: else:" or "try: finally:" blocks) + if self.indent <= 0: + raise EndOfBlock + elif self.indent == 0 and type not in (tokenize.COMMENT, tokenize.NL): + # any other token on the same indentation level end the previous + # block as well, except the pseudo-tokens COMMENT and NL. + raise EndOfBlock def getblock(lines): """Extract the block of code at the top of the given list of lines.""" + blockfinder = BlockFinder() try: - tokenize.tokenize(ListReader(lines).readline, BlockFinder().tokeneater) - except EndOfBlock, eob: - return lines[:eob.args[0]] - # Fooling the indent/dedent logic implies a one-line definition - return lines[:1] + tokenize.tokenize(iter(lines).next, blockfinder.tokeneater) + except (EndOfBlock, IndentationError): + pass + return lines[:blockfinder.last] def getsourcelines(object): """Return a list of source lines and starting line number for an object. @@ -527,10 +705,10 @@ def getsource(object): def walktree(classes, children, parent): """Recursive helper function for getclasstree().""" results = [] - classes.sort(lambda a, b: cmp(a.__name__, b.__name__)) + classes.sort(key=attrgetter('__module__', '__name__')) for c in classes: results.append((c, c.__bases__)) - if children.has_key(c): + if c in children: results.append(walktree(children[c], children, c)) return results @@ -548,20 +726,20 @@ def getclasstree(classes, unique=0): for c in classes: if c.__bases__: for parent in c.__bases__: - if not children.has_key(parent): + if not parent in children: children[parent] = [] - children[parent].append(c) + if c not in children[parent]: + children[parent].append(c) if unique and parent in classes: break elif c not in roots: roots.append(c) - for parent in children.keys(): + for parent in children: if parent not in classes: roots.append(parent) return walktree(roots, children, None) # ------------------------------------------------ argument list extraction -# These constants are from Python's compile.h. -CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 1, 2, 4, 8 +Arguments = namedtuple('Arguments', 'args varargs keywords') def getargs(co): """Get information about the arguments accepted by a code object. @@ -569,7 +747,9 @@ def getargs(co): Three things are returned: (args, varargs, varkw), where 'args' is a list of argument names (possibly containing nested lists), and 'varargs' and 'varkw' are the names of the * and ** arguments or None.""" - if not iscode(co): raise TypeError, 'arg is not a code object' + + if not iscode(co): + raise TypeError('{!r} is not a code object'.format(co)) nargs = co.co_argcount names = co.co_varnames @@ -577,24 +757,29 @@ def getargs(co): step = 0 # The following acrobatics are for anonymous (tuple) arguments. - if not sys.platform.startswith('java'):#Jython doesn't have co_code - code = co.co_code - import dis - for i in range(nargs): - if args[i][:1] in ['', '.']: - stack, remain, count = [], [], [] - while step < len(code): - op = ord(code[step]) - step = step + 1 - if op >= dis.HAVE_ARGUMENT: - opname = dis.opname[op] - value = ord(code[step]) + ord(code[step + 1]) * 256 - step = step + 2 - if opname in ['UNPACK_TUPLE', 'UNPACK_SEQUENCE']: - remain.append(value) - count.append(value) - elif opname == 'STORE_FAST': - stack.append(names[value]) + for i in range(nargs): + if args[i][:1] in ('', '.'): + stack, remain, count = [], [], [] + while step < len(co.co_code): + op = ord(co.co_code[step]) + step = step + 1 + if op >= dis.HAVE_ARGUMENT: + opname = dis.opname[op] + value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256 + step = step + 2 + if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'): + remain.append(value) + count.append(value) + elif opname == 'STORE_FAST': + stack.append(names[value]) + + # Special case for sublists of length 1: def foo((bar)) + # doesn't generate the UNPACK_TUPLE bytecode, so if + # `remain` is empty here, we have such a sublist. + if not remain: + stack[0] = [stack[0]] + break + else: remain[-1] = remain[-1] - 1 while remain[-1] == 0: remain.pop() @@ -603,7 +788,7 @@ def getargs(co): if not remain: break remain[-1] = remain[-1] - 1 if not remain: break - args[i] = stack[0] + args[i] = stack[0] varargs = None if co.co_flags & CO_VARARGS: @@ -612,7 +797,9 @@ def getargs(co): varkw = None if co.co_flags & CO_VARKEYWORDS: varkw = co.co_varnames[nargs] - return args, varargs, varkw + return Arguments(args, varargs, varkw) + +ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults') def getargspec(func): """Get the names and default values of a function's arguments. @@ -620,12 +807,17 @@ def getargspec(func): A tuple of four things is returned: (args, varargs, varkw, defaults). 'args' is a list of the argument names (it may contain nested lists). 'varargs' and 'varkw' are the names of the * and ** arguments or None. - 'defaults' is an n-tuple of the default values of the last n arguments.""" + 'defaults' is an n-tuple of the default values of the last n arguments. + """ + if ismethod(func): func = func.im_func - if not isfunction(func): raise TypeError, 'arg is not a Python function' + if not isfunction(func): + raise TypeError('{!r} is not a Python function'.format(func)) args, varargs, varkw = getargs(func.func_code) - return args, varargs, varkw, func.func_defaults + return ArgSpec(args, varargs, varkw, func.func_defaults) + +ArgInfo = namedtuple('ArgInfo', 'args varargs keywords locals') def getargvalues(frame): """Get information about arguments passed into a particular frame. @@ -635,7 +827,7 @@ def getargvalues(frame): 'varargs' and 'varkw' are the names of the * and ** arguments or None. 'locals' is the locals dictionary of the given frame.""" args, varargs, varkw = getargs(frame.f_code) - return args, varargs, varkw, frame.f_locals + return ArgInfo(args, varargs, varkw, frame.f_locals) def joinseq(seq): if len(seq) == 1: @@ -645,7 +837,7 @@ def joinseq(seq): def strseq(object, convert, join=joinseq): """Recursively walk a sequence, stringifying each element.""" - if type(object) in [types.ListType, types.TupleType]: + if type(object) in (list, tuple): return join(map(lambda o, c=convert, j=join: strseq(o, c, j), object)) else: return convert(object) @@ -665,14 +857,14 @@ def formatargspec(args, varargs=None, varkw=None, defaults=None, specs = [] if defaults: firstdefault = len(args) - len(defaults) - for i in range(len(args)): - spec = strseq(args[i], formatarg, join) + for i, arg in enumerate(args): + spec = strseq(arg, formatarg, join) if defaults and i >= firstdefault: spec = spec + formatvalue(defaults[i - firstdefault]) specs.append(spec) - if varargs: + if varargs is not None: specs.append(formatvarargs(varargs)) - if varkw: + if varkw is not None: specs.append(formatvarkw(varkw)) return '(' + string.join(specs, ', ') + ')' @@ -700,7 +892,99 @@ def formatargvalues(args, varargs, varkw, locals, specs.append(formatvarkw(varkw) + formatvalue(locals[varkw])) return '(' + string.join(specs, ', ') + ')' +def getcallargs(func, *positional, **named): + """Get the mapping of arguments to values. + + A dict is returned, with keys the function argument names (including the + names of the * and ** arguments, if any), and values the respective bound + values from 'positional' and 'named'.""" + args, varargs, varkw, defaults = getargspec(func) + f_name = func.__name__ + arg2value = {} + + # The following closures are basically because of tuple parameter unpacking. + assigned_tuple_params = [] + def assign(arg, value): + if isinstance(arg, str): + arg2value[arg] = value + else: + assigned_tuple_params.append(arg) + value = iter(value) + for i, subarg in enumerate(arg): + try: + subvalue = next(value) + except StopIteration: + raise ValueError('need more than %d %s to unpack' % + (i, 'values' if i > 1 else 'value')) + assign(subarg,subvalue) + try: + next(value) + except StopIteration: + pass + else: + raise ValueError('too many values to unpack') + def is_assigned(arg): + if isinstance(arg,str): + return arg in arg2value + return arg in assigned_tuple_params + if ismethod(func) and func.im_self is not None: + # implicit 'self' (or 'cls' for classmethods) argument + positional = (func.im_self,) + positional + num_pos = len(positional) + num_total = num_pos + len(named) + num_args = len(args) + num_defaults = len(defaults) if defaults else 0 + for arg, value in zip(args, positional): + assign(arg, value) + if varargs: + if num_pos > num_args: + assign(varargs, positional[-(num_pos-num_args):]) + else: + assign(varargs, ()) + elif 0 < num_args < num_pos: + raise TypeError('%s() takes %s %d %s (%d given)' % ( + f_name, 'at most' if defaults else 'exactly', num_args, + 'arguments' if num_args > 1 else 'argument', num_total)) + elif num_args == 0 and num_total: + if varkw: + if num_pos: + # XXX: We should use num_pos, but Python also uses num_total: + raise TypeError('%s() takes exactly 0 arguments ' + '(%d given)' % (f_name, num_total)) + else: + raise TypeError('%s() takes no arguments (%d given)' % + (f_name, num_total)) + for arg in args: + if isinstance(arg, str) and arg in named: + if is_assigned(arg): + raise TypeError("%s() got multiple values for keyword " + "argument '%s'" % (f_name, arg)) + else: + assign(arg, named.pop(arg)) + if defaults: # fill in any missing values with the defaults + for arg, value in zip(args[-num_defaults:], defaults): + if not is_assigned(arg): + assign(arg, value) + if varkw: + assign(varkw, named) + elif named: + unexpected = next(iter(named)) + if isinstance(unexpected, unicode): + unexpected = unexpected.encode(sys.getdefaultencoding(), 'replace') + raise TypeError("%s() got an unexpected keyword argument '%s'" % + (f_name, unexpected)) + unassigned = num_args - len([arg for arg in args if is_assigned(arg)]) + if unassigned: + num_required = num_args - num_defaults + raise TypeError('%s() takes %s %d %s (%d given)' % ( + f_name, 'at least' if defaults else 'exactly', num_required, + 'arguments' if num_required > 1 else 'argument', num_total)) + return arg2value + # -------------------------------------------------- stack frame extraction + +Traceback = namedtuple('Traceback', 'filename lineno function code_context index') + def getframeinfo(frame, context=1): """Get information about a frame or traceback object. @@ -709,44 +993,35 @@ def getframeinfo(frame, context=1): the source code, and the index of the current line within that list. The optional second argument specifies the number of lines of context to return, which are centered around the current line.""" - raise NotImplementedError -# if istraceback(frame): -# frame = frame.tb_frame -# if not isframe(frame): -# raise TypeError, 'arg is not a frame or traceback object' -# -# filename = getsourcefile(frame) -# lineno = getlineno(frame) -# if context > 0: -# start = lineno - 1 - context//2 -# try: -# lines, lnum = findsource(frame) -# except IOError: -# lines = index = None -# else: -# start = max(start, 1) -# start = min(start, len(lines) - context) -# lines = lines[start:start+context] -# index = lineno - 1 - start -# else: -# lines = index = None -# -# return (filename, lineno, frame.f_code.co_name, lines, index) + if istraceback(frame): + lineno = frame.tb_lineno + frame = frame.tb_frame + else: + lineno = frame.f_lineno + if not isframe(frame): + raise TypeError('{!r} is not a frame or traceback object'.format(frame)) + + filename = getsourcefile(frame) or getfile(frame) + if context > 0: + start = lineno - 1 - context//2 + try: + lines, lnum = findsource(frame) + except IOError: + lines = index = None + else: + start = max(start, 1) + start = max(0, min(start, len(lines) - context)) + lines = lines[start:start+context] + index = lineno - 1 - start + else: + lines = index = None + + return Traceback(filename, lineno, frame.f_code.co_name, lines, index) def getlineno(frame): """Get the line number from a frame object, allowing for optimization.""" - # Written by Marc-Andr Lemburg; revised by Jim Hugunin and Fredrik Lundh. - lineno = frame.f_lineno - code = frame.f_code - if hasattr(code, 'co_lnotab'): - table = code.co_lnotab - lineno = code.co_firstlineno - addr = 0 - for i in range(0, len(table), 2): - addr = addr + ord(table[i]) - if addr > frame.f_lasti: break - lineno = lineno + ord(table[i + 1]) - return lineno + # FrameType.f_lineno is now a descriptor that grovels co_lnotab + return frame.f_lineno def getouterframes(frame, context=1): """Get a list of records for a frame and all higher (calling) frames. @@ -770,19 +1045,15 @@ def getinnerframes(tb, context=1): tb = tb.tb_next return framelist -def currentframe(): - """Return the frame object for the caller's stack frame.""" - try: - raise 'catch me' - except: - return sys.exc_traceback.tb_frame.f_back #@UndefinedVariable - -if hasattr(sys, '_getframe'): currentframe = sys._getframe +if hasattr(sys, '_getframe'): + currentframe = sys._getframe +else: + currentframe = lambda _=None: None def stack(context=1): """Return a list of records for the stack above the caller's frame.""" - return getouterframes(currentframe().f_back, context) + return getouterframes(sys._getframe(1), context) def trace(context=1): """Return a list of records for the stack below the current exception.""" - return getinnerframes(sys.exc_traceback, context) #@UndefinedVariable + return getinnerframes(sys.exc_info()[2], context) diff --git a/python/helpers/pydev/_pydev_imps/_pydev_pkgutil_old.py b/python/helpers/pydev/_pydev_imps/_pydev_pkgutil_old.py index ce072ec9ef75..f69655c05179 100644 --- a/python/helpers/pydev/_pydev_imps/_pydev_pkgutil_old.py +++ b/python/helpers/pydev/_pydev_imps/_pydev_pkgutil_old.py @@ -540,7 +540,7 @@ def extend_path(path, name): if os.path.isfile(pkgfile): try: f = open(pkgfile) - except IOError, msg: + except IOError as msg: sys.stderr.write("Can't open %s: %s\n" % (pkgfile, msg)) else: diff --git a/python/helpers/pydev/_pydev_imps/_pydev_uuid_old.py b/python/helpers/pydev/_pydev_imps/_pydev_uuid_old.py deleted file mode 100644 index 20bc43b7d1e0..000000000000 --- a/python/helpers/pydev/_pydev_imps/_pydev_uuid_old.py +++ /dev/null @@ -1,541 +0,0 @@ -r"""UUID objects (universally unique identifiers) according to RFC 4122. - -This module provides immutable UUID objects (class UUID) and the functions -uuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5 -UUIDs as specified in RFC 4122. - -If all you want is a unique ID, you should probably call uuid1() or uuid4(). -Note that uuid1() may compromise privacy since it creates a UUID containing -the computer's network address. uuid4() creates a random UUID. - -Typical usage: - - >>> import uuid - - # make a UUID based on the host ID and current time - >>> uuid.uuid1() - UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') - - # make a UUID using an MD5 hash of a namespace UUID and a name - >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') - UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') - - # make a random UUID - >>> uuid.uuid4() - UUID('16fd2706-8baf-433b-82eb-8c7fada847da') - - # make a UUID using a SHA-1 hash of a namespace UUID and a name - >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') - UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d') - - # make a UUID from a string of hex digits (braces and hyphens ignored) - >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}') - - # convert a UUID to a string of hex digits in standard form - >>> str(x) - '00010203-0405-0607-0809-0a0b0c0d0e0f' - - # get the raw 16 bytes of the UUID - >>> x.bytes - '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f' - - # make a UUID from a 16-byte string - >>> uuid.UUID(bytes=x.bytes) - UUID('00010203-0405-0607-0809-0a0b0c0d0e0f') -""" - -__author__ = 'Ka-Ping Yee ' - -RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [ - 'reserved for NCS compatibility', 'specified in RFC 4122', - 'reserved for Microsoft compatibility', 'reserved for future definition'] - -class UUID(object): - """Instances of the UUID class represent UUIDs as specified in RFC 4122. - UUID objects are immutable, hashable, and usable as dictionary keys. - Converting a UUID to a string with str() yields something in the form - '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts - five possible forms: a similar string of hexadecimal digits, or a tuple - of six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and - 48-bit values respectively) as an argument named 'fields', or a string - of 16 bytes (with all the integer fields in big-endian order) as an - argument named 'bytes', or a string of 16 bytes (with the first three - fields in little-endian order) as an argument named 'bytes_le', or a - single 128-bit integer as an argument named 'int'. - - UUIDs have these read-only attributes: - - bytes the UUID as a 16-byte string (containing the six - integer fields in big-endian byte order) - - bytes_le the UUID as a 16-byte string (with time_low, time_mid, - and time_hi_version in little-endian byte order) - - fields a tuple of the six integer fields of the UUID, - which are also available as six individual attributes - and two derived attributes: - - time_low the first 32 bits of the UUID - time_mid the next 16 bits of the UUID - time_hi_version the next 16 bits of the UUID - clock_seq_hi_variant the next 8 bits of the UUID - clock_seq_low the next 8 bits of the UUID - node the last 48 bits of the UUID - - time the 60-bit timestamp - clock_seq the 14-bit sequence number - - hex the UUID as a 32-character hexadecimal string - - int the UUID as a 128-bit integer - - urn the UUID as a URN as specified in RFC 4122 - - variant the UUID variant (one of the constants RESERVED_NCS, - RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE) - - version the UUID version number (1 through 5, meaningful only - when the variant is RFC_4122) - """ - - def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None, - int=None, version=None): - r"""Create a UUID from either a string of 32 hexadecimal digits, - a string of 16 bytes as the 'bytes' argument, a string of 16 bytes - in little-endian order as the 'bytes_le' argument, a tuple of six - integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version, - 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as - the 'fields' argument, or a single 128-bit integer as the 'int' - argument. When a string of hex digits is given, curly braces, - hyphens, and a URN prefix are all optional. For example, these - expressions all yield the same UUID: - - UUID('{12345678-1234-5678-1234-567812345678}') - UUID('12345678123456781234567812345678') - UUID('urn:uuid:12345678-1234-5678-1234-567812345678') - UUID(bytes='\x12\x34\x56\x78'*4) - UUID(bytes_le='\x78\x56\x34\x12\x34\x12\x78\x56' + - '\x12\x34\x56\x78\x12\x34\x56\x78') - UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678)) - UUID(int=0x12345678123456781234567812345678) - - Exactly one of 'hex', 'bytes', 'bytes_le', 'fields', or 'int' must - be given. The 'version' argument is optional; if given, the resulting - UUID will have its variant and version set according to RFC 4122, - overriding the given 'hex', 'bytes', 'bytes_le', 'fields', or 'int'. - """ - - if [hex, bytes, bytes_le, fields, int].count(None) != 4: - raise TypeError('need one of hex, bytes, bytes_le, fields, or int') - if hex is not None: - hex = hex.replace('urn:', '').replace('uuid:', '') - hex = hex.strip('{}').replace('-', '') - if len(hex) != 32: - raise ValueError('badly formed hexadecimal UUID string') - int = long(hex, 16) - if bytes_le is not None: - if len(bytes_le) != 16: - raise ValueError('bytes_le is not a 16-char string') - bytes = (bytes_le[3] + bytes_le[2] + bytes_le[1] + bytes_le[0] + - bytes_le[5] + bytes_le[4] + bytes_le[7] + bytes_le[6] + - bytes_le[8:]) - if bytes is not None: - if len(bytes) != 16: - raise ValueError('bytes is not a 16-char string') - int = long(('%02x'*16) % tuple(map(ord, bytes)), 16) - if fields is not None: - if len(fields) != 6: - raise ValueError('fields is not a 6-tuple') - (time_low, time_mid, time_hi_version, - clock_seq_hi_variant, clock_seq_low, node) = fields - if not 0 <= time_low < 1<<32L: - raise ValueError('field 1 out of range (need a 32-bit value)') - if not 0 <= time_mid < 1<<16L: - raise ValueError('field 2 out of range (need a 16-bit value)') - if not 0 <= time_hi_version < 1<<16L: - raise ValueError('field 3 out of range (need a 16-bit value)') - if not 0 <= clock_seq_hi_variant < 1<<8L: - raise ValueError('field 4 out of range (need an 8-bit value)') - if not 0 <= clock_seq_low < 1<<8L: - raise ValueError('field 5 out of range (need an 8-bit value)') - if not 0 <= node < 1<<48L: - raise ValueError('field 6 out of range (need a 48-bit value)') - clock_seq = (clock_seq_hi_variant << 8L) | clock_seq_low - int = ((time_low << 96L) | (time_mid << 80L) | - (time_hi_version << 64L) | (clock_seq << 48L) | node) - if int is not None: - if not 0 <= int < 1<<128L: - raise ValueError('int is out of range (need a 128-bit value)') - if version is not None: - if not 1 <= version <= 5: - raise ValueError('illegal version number') - # Set the variant to RFC 4122. - int &= ~(0xc000 << 48L) - int |= 0x8000 << 48L - # Set the version number. - int &= ~(0xf000 << 64L) - int |= version << 76L - self.__dict__['int'] = int - - def __cmp__(self, other): - if isinstance(other, UUID): - return cmp(self.int, other.int) - return NotImplemented - - def __hash__(self): - return hash(self.int) - - def __int__(self): - return self.int - - def __repr__(self): - return 'UUID(%r)' % str(self) - - def __setattr__(self, name, value): - raise TypeError('UUID objects are immutable') - - def __str__(self): - hex = '%032x' % self.int - return '%s-%s-%s-%s-%s' % ( - hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:]) - - def get_bytes(self): - bytes = '' - for shift in range(0, 128, 8): - bytes = chr((self.int >> shift) & 0xff) + bytes - return bytes - - bytes = property(get_bytes) - - def get_bytes_le(self): - bytes = self.bytes - return (bytes[3] + bytes[2] + bytes[1] + bytes[0] + - bytes[5] + bytes[4] + bytes[7] + bytes[6] + bytes[8:]) - - bytes_le = property(get_bytes_le) - - def get_fields(self): - return (self.time_low, self.time_mid, self.time_hi_version, - self.clock_seq_hi_variant, self.clock_seq_low, self.node) - - fields = property(get_fields) - - def get_time_low(self): - return self.int >> 96L - - time_low = property(get_time_low) - - def get_time_mid(self): - return (self.int >> 80L) & 0xffff - - time_mid = property(get_time_mid) - - def get_time_hi_version(self): - return (self.int >> 64L) & 0xffff - - time_hi_version = property(get_time_hi_version) - - def get_clock_seq_hi_variant(self): - return (self.int >> 56L) & 0xff - - clock_seq_hi_variant = property(get_clock_seq_hi_variant) - - def get_clock_seq_low(self): - return (self.int >> 48L) & 0xff - - clock_seq_low = property(get_clock_seq_low) - - def get_time(self): - return (((self.time_hi_version & 0x0fffL) << 48L) | - (self.time_mid << 32L) | self.time_low) - - time = property(get_time) - - def get_clock_seq(self): - return (((self.clock_seq_hi_variant & 0x3fL) << 8L) | - self.clock_seq_low) - - clock_seq = property(get_clock_seq) - - def get_node(self): - return self.int & 0xffffffffffff - - node = property(get_node) - - def get_hex(self): - return '%032x' % self.int - - hex = property(get_hex) - - def get_urn(self): - return 'urn:uuid:' + str(self) - - urn = property(get_urn) - - def get_variant(self): - if not self.int & (0x8000 << 48L): - return RESERVED_NCS - elif not self.int & (0x4000 << 48L): - return RFC_4122 - elif not self.int & (0x2000 << 48L): - return RESERVED_MICROSOFT - else: - return RESERVED_FUTURE - - variant = property(get_variant) - - def get_version(self): - # The version bits are only meaningful for RFC 4122 UUIDs. - if self.variant == RFC_4122: - return int((self.int >> 76L) & 0xf) - - version = property(get_version) - -def _find_mac(command, args, hw_identifiers, get_index): - import os - for dir in ['', '/sbin/', '/usr/sbin']: - executable = os.path.join(dir, command) - if not os.path.exists(executable): - continue - - try: - # LC_ALL to get English output, 2>/dev/null to - # prevent output on stderr - cmd = 'LC_ALL=C %s %s 2>/dev/null' % (executable, args) - pipe = os.popen(cmd) - except IOError: - continue - - for line in pipe: - words = line.lower().split() - for i in range(len(words)): - if words[i] in hw_identifiers: - return int(words[get_index(i)].replace(':', ''), 16) - return None - -def _ifconfig_getnode(): - """Get the hardware address on Unix by running ifconfig.""" - - # This works on Linux ('' or '-a'), Tru64 ('-av'), but not all Unixes. - for args in ('', '-a', '-av'): - mac = _find_mac('ifconfig', args, ['hwaddr', 'ether'], lambda i: i+1) - if mac: - return mac - - import socket - ip_addr = socket.gethostbyname(socket.gethostname()) - - # Try getting the MAC addr from arp based on our IP address (Solaris). - mac = _find_mac('arp', '-an', [ip_addr], lambda i: -1) - if mac: - return mac - - # This might work on HP-UX. - mac = _find_mac('lanscan', '-ai', ['lan0'], lambda i: 0) - if mac: - return mac - - return None - -def _ipconfig_getnode(): - """Get the hardware address on Windows by running ipconfig.exe.""" - import os, re - dirs = ['', r'c:\windows\system32', r'c:\winnt\system32'] - try: - import ctypes - buffer = ctypes.create_string_buffer(300) - ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300) # @UndefinedVariable - dirs.insert(0, buffer.value.decode('mbcs')) - except: - pass - for dir in dirs: - try: - pipe = os.popen(os.path.join(dir, 'ipconfig') + ' /all') - except IOError: - continue - for line in pipe: - value = line.split(':')[-1].strip().lower() - if re.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value): - return int(value.replace('-', ''), 16) - -def _netbios_getnode(): - """Get the hardware address on Windows using NetBIOS calls. - See http://support.microsoft.com/kb/118623 for details.""" - import win32wnet, netbios - ncb = netbios.NCB() - ncb.Command = netbios.NCBENUM - ncb.Buffer = adapters = netbios.LANA_ENUM() - adapters._pack() - if win32wnet.Netbios(ncb) != 0: - return - adapters._unpack() - for i in range(adapters.length): - ncb.Reset() - ncb.Command = netbios.NCBRESET - ncb.Lana_num = ord(adapters.lana[i]) - if win32wnet.Netbios(ncb) != 0: - continue - ncb.Reset() - ncb.Command = netbios.NCBASTAT - ncb.Lana_num = ord(adapters.lana[i]) - ncb.Callname = '*'.ljust(16) - ncb.Buffer = status = netbios.ADAPTER_STATUS() - if win32wnet.Netbios(ncb) != 0: - continue - status._unpack() - bytes = map(ord, status.adapter_address) - return ((bytes[0]<<40L) + (bytes[1]<<32L) + (bytes[2]<<24L) + - (bytes[3]<<16L) + (bytes[4]<<8L) + bytes[5]) - -# Thanks to Thomas Heller for ctypes and for his help with its use here. - -# If ctypes is available, use it to find system routines for UUID generation. -_uuid_generate_random = _uuid_generate_time = _UuidCreate = None -try: - import ctypes, ctypes.util - _buffer = ctypes.create_string_buffer(16) - - # The uuid_generate_* routines are provided by libuuid on at least - # Linux and FreeBSD, and provided by libc on Mac OS X. - for libname in ['uuid', 'c']: - try: - lib = ctypes.CDLL(ctypes.util.find_library(libname)) - except: - continue - if hasattr(lib, 'uuid_generate_random'): - _uuid_generate_random = lib.uuid_generate_random - if hasattr(lib, 'uuid_generate_time'): - _uuid_generate_time = lib.uuid_generate_time - - # On Windows prior to 2000, UuidCreate gives a UUID containing the - # hardware address. On Windows 2000 and later, UuidCreate makes a - # random UUID and UuidCreateSequential gives a UUID containing the - # hardware address. These routines are provided by the RPC runtime. - # NOTE: at least on Tim's WinXP Pro SP2 desktop box, while the last - # 6 bytes returned by UuidCreateSequential are fixed, they don't appear - # to bear any relationship to the MAC address of any network device - # on the box. - try: - lib = ctypes.windll.rpcrt4 - except: - lib = None - _UuidCreate = getattr(lib, 'UuidCreateSequential', - getattr(lib, 'UuidCreate', None)) -except: - pass - -def _unixdll_getnode(): - """Get the hardware address on Unix using ctypes.""" - _uuid_generate_time(_buffer) - return UUID(bytes=_buffer.raw).node - -def _windll_getnode(): - """Get the hardware address on Windows using ctypes.""" - if _UuidCreate(_buffer) == 0: - return UUID(bytes=_buffer.raw).node - -def _random_getnode(): - """Get a random node ID, with eighth bit set as suggested by RFC 4122.""" - import random - return random.randrange(0, 1<<48L) | 0x010000000000L - -_node = None - -def getnode(): - """Get the hardware address as a 48-bit positive integer. - - The first time this runs, it may launch a separate program, which could - be quite slow. If all attempts to obtain the hardware address fail, we - choose a random 48-bit number with its eighth bit set to 1 as recommended - in RFC 4122. - """ - - global _node - if _node is not None: - return _node - - import sys - if sys.platform == 'win32': - getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode] - else: - getters = [_unixdll_getnode, _ifconfig_getnode] - - for getter in getters + [_random_getnode]: - try: - _node = getter() - except: - continue - if _node is not None: - return _node - -_last_timestamp = None - -def uuid1(node=None, clock_seq=None): - """Generate a UUID from a host ID, sequence number, and the current time. - If 'node' is not given, getnode() is used to obtain the hardware - address. If 'clock_seq' is given, it is used as the sequence number; - otherwise a random 14-bit sequence number is chosen.""" - - # When the system provides a version-1 UUID generator, use it (but don't - # use UuidCreate here because its UUIDs don't conform to RFC 4122). - if _uuid_generate_time and node is clock_seq is None: - _uuid_generate_time(_buffer) - return UUID(bytes=_buffer.raw) - - global _last_timestamp - import time - nanoseconds = int(time.time() * 1e9) - # 0x01b21dd213814000 is the number of 100-ns intervals between the - # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00. - timestamp = int(nanoseconds/100) + 0x01b21dd213814000L - if timestamp <= _last_timestamp: - timestamp = _last_timestamp + 1 - _last_timestamp = timestamp - if clock_seq is None: - import random - clock_seq = random.randrange(1<<14L) # instead of stable storage - time_low = timestamp & 0xffffffffL - time_mid = (timestamp >> 32L) & 0xffffL - time_hi_version = (timestamp >> 48L) & 0x0fffL - clock_seq_low = clock_seq & 0xffL - clock_seq_hi_variant = (clock_seq >> 8L) & 0x3fL - if node is None: - node = getnode() - return UUID(fields=(time_low, time_mid, time_hi_version, - clock_seq_hi_variant, clock_seq_low, node), version=1) - -def uuid3(namespace, name): - """Generate a UUID from the MD5 hash of a namespace UUID and a name.""" - import md5 - hash = md5.md5(namespace.bytes + name).digest() - return UUID(bytes=hash[:16], version=3) - -def uuid4(): - """Generate a random UUID.""" - - # When the system provides a version-4 UUID generator, use it. - if _uuid_generate_random: - _uuid_generate_random(_buffer) - return UUID(bytes=_buffer.raw) - - # Otherwise, get randomness from urandom or the 'random' module. - try: - import os - return UUID(bytes=os.urandom(16), version=4) - except: - import random - bytes = [chr(random.randrange(256)) for i in range(16)] - return UUID(bytes=bytes, version=4) - -def uuid5(namespace, name): - """Generate a UUID from the SHA-1 hash of a namespace UUID and a name.""" - import sha - hash = sha.sha(namespace.bytes + name).digest() - return UUID(bytes=hash[:16], version=5) - -# The following standard UUIDs are for use with uuid3() or uuid5(). - -NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8') -NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8') -NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8') -NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8') diff --git a/python/helpers/pydev/_pydev_imps/_pydev_xmlrpclib.py b/python/helpers/pydev/_pydev_imps/_pydev_xmlrpclib.py index 5f6e2b7f138c..e35b82d821d1 100644 --- a/python/helpers/pydev/_pydev_imps/_pydev_xmlrpclib.py +++ b/python/helpers/pydev/_pydev_imps/_pydev_xmlrpclib.py @@ -1,8 +1,6 @@ -#Just a copy of the version in python 2.5 to be used if it's not available in jython 2.1 -import sys - # # XML-RPC CLIENT LIBRARY +# $Id$ # # an XML-RPC client interface for Python. # @@ -51,6 +49,7 @@ import sys # 2003-07-12 gp Correct marshalling of Faults # 2003-10-31 mvl Add multicall support # 2004-08-20 mvl Bump minimum supported Python version to 2.1 +# 2014-12-02 ch/doko Add workaround for gzip bomb vulnerability # # Copyright (c) 1999-2002 by Secret Labs AB. # Copyright (c) 1999-2002 by Fredrik Lundh. @@ -141,6 +140,13 @@ Exported functions: import re, string, time, operator from types import * +import socket +import errno +import httplib +try: + import gzip +except ImportError: + gzip = None #python can be built without zlib/gzip support # -------------------------------------------------------------------- # Internal stuff @@ -157,7 +163,7 @@ except ImportError: try: _bool_is_builtin = False.__class__.__name__ == "bool" -except (NameError, AttributeError): +except NameError: _bool_is_builtin = 0 def _decode(data, encoding, is8bit=re.compile("[\x80-\xff]").search): @@ -185,32 +191,28 @@ else: __version__ = "1.0.1" # xmlrpc integer limits -try: - long -except NameError: - long = int -MAXINT = long(2) ** 31 - 1 -MININT = long(-2) ** 31 +MAXINT = 2L**31-1 +MININT = -2L**31 # -------------------------------------------------------------------- # Error constants (from Dan Libby's specification at # http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php) # Ranges of errors -PARSE_ERROR = -32700 -SERVER_ERROR = -32600 +PARSE_ERROR = -32700 +SERVER_ERROR = -32600 APPLICATION_ERROR = -32500 -SYSTEM_ERROR = -32400 -TRANSPORT_ERROR = -32300 +SYSTEM_ERROR = -32400 +TRANSPORT_ERROR = -32300 # Specific errors -NOT_WELLFORMED_ERROR = -32700 -UNSUPPORTED_ENCODING = -32701 +NOT_WELLFORMED_ERROR = -32700 +UNSUPPORTED_ENCODING = -32701 INVALID_ENCODING_CHAR = -32702 -INVALID_XMLRPC = -32600 -METHOD_NOT_FOUND = -32601 +INVALID_XMLRPC = -32600 +METHOD_NOT_FOUND = -32601 INVALID_METHOD_PARAMS = -32602 -INTERNAL_ERROR = -32603 +INTERNAL_ERROR = -32603 # -------------------------------------------------------------------- # Exceptions @@ -243,9 +245,9 @@ class ProtocolError(Error): self.headers = headers def __repr__(self): return ( - "" % - (self.url, self.errcode, self.errmsg) - ) + "" % + (self.url, self.errcode, self.errmsg) + ) ## # Indicates a broken XML-RPC response package. This exception is @@ -273,9 +275,9 @@ class Fault(Error): self.faultString = faultString def __repr__(self): return ( - "" % - (self.faultCode, repr(self.faultString)) - ) + "" % + (self.faultCode, repr(self.faultString)) + ) # -------------------------------------------------------------------- # Special values @@ -288,10 +290,13 @@ class Fault(Error): # @param value A boolean value. Any true value is interpreted as True, # all other values are interpreted as False. +from sys import modules +mod_dict = modules[__name__].__dict__ if _bool_is_builtin: - boolean = Boolean = bool #@UndefinedVariable + boolean = Boolean = bool # to avoid breaking code which references xmlrpclib.{True,False} - True, False = True, False + mod_dict['True'] = True + mod_dict['False'] = False else: class Boolean: """Boolean-value wrapper. @@ -299,7 +304,7 @@ else: Use True or False to generate a "boolean" XML-RPC value. """ - def __init__(self, value=0): + def __init__(self, value = 0): self.value = operator.truth(value) def encode(self, out): @@ -322,7 +327,8 @@ else: def __nonzero__(self): return self.value - True, False = Boolean(1), Boolean(0) + mod_dict['True'] = Boolean(1) + mod_dict['False'] = Boolean(0) ## # Map true or false value to XML-RPC boolean values. @@ -339,6 +345,8 @@ else: """Convert any Python value to XML-RPC 'boolean'.""" return _truefalse[operator.truth(value)] +del modules, mod_dict + ## # Wrapper for XML-RPC DateTime values. This converts a time value to # the format used by XML-RPC. @@ -352,6 +360,20 @@ else: # @param value The time, given as an ISO 8601 string, a time # tuple, or a integer time value. +def _strftime(value): + if datetime: + if isinstance(value, datetime.datetime): + return "%04d%02d%02dT%02d:%02d:%02d" % ( + value.year, value.month, value.day, + value.hour, value.minute, value.second) + + if not isinstance(value, (TupleType, time.struct_time)): + if value == 0: + value = time.time() + value = time.localtime(value) + + return "%04d%02d%02dT%02d:%02d:%02d" % value[:6] + class DateTime: """DateTime wrapper for an ISO 8601 string or time tuple or localtime integer value to generate 'dateTime.iso8601' XML-RPC @@ -359,28 +381,62 @@ class DateTime: """ def __init__(self, value=0): - if not isinstance(value, StringType): - if datetime and isinstance(value, datetime.datetime): - self.value = value.strftime("%Y%m%dT%H:%M:%S") - return - if datetime and isinstance(value, datetime.date): - self.value = value.strftime("%Y%m%dT%H:%M:%S") - return - if datetime and isinstance(value, datetime.time): - today = datetime.datetime.now().strftime("%Y%m%d") - self.value = value.strftime(today + "T%H:%M:%S") - return - if not isinstance(value, (TupleType, time.struct_time)): #@UndefinedVariable - if value == 0: - value = time.time() - value = time.localtime(value) - value = time.strftime("%Y%m%dT%H:%M:%S", value) - self.value = value + if isinstance(value, StringType): + self.value = value + else: + self.value = _strftime(value) + + def make_comparable(self, other): + if isinstance(other, DateTime): + s = self.value + o = other.value + elif datetime and isinstance(other, datetime.datetime): + s = self.value + o = other.strftime("%Y%m%dT%H:%M:%S") + elif isinstance(other, (str, unicode)): + s = self.value + o = other + elif hasattr(other, "timetuple"): + s = self.timetuple() + o = other.timetuple() + else: + otype = (hasattr(other, "__class__") + and other.__class__.__name__ + or type(other)) + raise TypeError("Can't compare %s and %s" % + (self.__class__.__name__, otype)) + return s, o + + def __lt__(self, other): + s, o = self.make_comparable(other) + return s < o + + def __le__(self, other): + s, o = self.make_comparable(other) + return s <= o + + def __gt__(self, other): + s, o = self.make_comparable(other) + return s > o + + def __ge__(self, other): + s, o = self.make_comparable(other) + return s >= o + + def __eq__(self, other): + s, o = self.make_comparable(other) + return s == o + + def __ne__(self, other): + s, o = self.make_comparable(other) + return s != o + + def timetuple(self): + return time.strptime(self.value, "%Y%m%dT%H:%M:%S") def __cmp__(self, other): - if isinstance(other, DateTime): - other = other.value - return cmp(self.value, other) + s, o = self.make_comparable(other) + return cmp(s, o) ## # Get date/time value. @@ -409,7 +465,7 @@ def _datetime(data): return value def _datetime_type(data): - t = time.strptime(data, "%Y%m%dT%H:%M:%S") #@UndefinedVariable + t = time.strptime(data, "%Y%m%dT%H:%M:%S") return datetime.datetime(*tuple(t)[:6]) ## @@ -466,78 +522,27 @@ if not _bool_is_builtin: try: # optional xmlrpclib accelerator - import _xmlrpclib #@UnresolvedImport + import _xmlrpclib FastParser = _xmlrpclib.Parser FastUnmarshaller = _xmlrpclib.Unmarshaller except (AttributeError, ImportError): FastParser = FastUnmarshaller = None try: - import _xmlrpclib #@UnresolvedImport + import _xmlrpclib FastMarshaller = _xmlrpclib.Marshaller except (AttributeError, ImportError): FastMarshaller = None -# -# the SGMLOP parser is about 15x faster than Python's builtin -# XML parser. SGMLOP sources can be downloaded from: -# -# http://www.pythonware.com/products/xml/sgmlop.htm -# - -try: - import sgmlop - if not hasattr(sgmlop, "XMLParser"): - raise ImportError() -except ImportError: - SgmlopParser = None # sgmlop accelerator not available -else: - class SgmlopParser: - def __init__(self, target): - - # setup callbacks - self.finish_starttag = target.start - self.finish_endtag = target.end - self.handle_data = target.data - self.handle_xml = target.xml - - # activate parser - self.parser = sgmlop.XMLParser() - self.parser.register(self) - self.feed = self.parser.feed - self.entity = { - "amp": "&", "gt": ">", "lt": "<", - "apos": "'", "quot": '"' - } - - def close(self): - try: - self.parser.close() - finally: - self.parser = self.feed = None # nuke circular reference - - def handle_proc(self, tag, attr): - m = re.search("encoding\s*=\s*['\"]([^\"']+)[\"']", attr) #@UndefinedVariable - if m: - self.handle_xml(m.group(1), 1) - - def handle_entityref(self, entity): - # entity - try: - self.handle_data(self.entity[entity]) - except KeyError: - self.handle_data("&%s;" % entity) - try: from xml.parsers import expat if not hasattr(expat, "ParserCreate"): - raise ImportError() + raise ImportError except ImportError: ExpatParser = None # expat not available else: class ExpatParser: - # fast expat parser for Python 2.0 and later. this is about - # 50% slower than sgmlop, on roundtrip testing + # fast expat parser for Python 2.0 and later. def __init__(self, target): self._parser = parser = expat.ParserCreate(None, None) self._target = target @@ -558,8 +563,7 @@ else: class SlowParser: """Default XML parser (based on xmllib.XMLParser).""" - # this is about 10 times slower than sgmlop, on roundtrip - # testing. + # this is the slowest parser. def __init__(self, target): import xmllib # lazy subclassing (!) if xmllib.XMLParser not in SlowParser.__bases__: @@ -636,20 +640,30 @@ class Marshaller: try: f = self.dispatch[type(value)] except KeyError: - raise TypeError("cannot marshal %s objects" % type(value)) - else: - f(self, value, write) + # check if this object can be marshalled as a structure + try: + value.__dict__ + except: + raise TypeError, "cannot marshal %s objects" % type(value) + # check if this class is a sub-class of a basic type, + # because we don't know how to marshal these types + # (e.g. a string sub-class) + for type_ in type(value).__mro__: + if type_ in self.dispatch.keys(): + raise TypeError, "cannot marshal %s objects" % type(value) + f = self.dispatch[InstanceType] + f(self, value, write) def dump_nil (self, value, write): if not self.allow_none: - raise TypeError("cannot marshal None unless allow_none is enabled") + raise TypeError, "cannot marshal None unless allow_none is enabled" write("") dispatch[NoneType] = dump_nil def dump_int(self, value, write): # in case ints are > 32 bits if value > MAXINT or value < MININT: - raise OverflowError("int exceeds XML-RPC limits") + raise OverflowError, "int exceeds XML-RPC limits" write("") write(str(value)) write("\n") @@ -660,11 +674,11 @@ class Marshaller: write("") write(value and "1" or "0") write("\n") - dispatch[bool] = dump_bool #@UndefinedVariable + dispatch[bool] = dump_bool def dump_long(self, value, write): if value > MAXINT or value < MININT: - raise OverflowError("long int exceeds XML-RPC limits") + raise OverflowError, "long int exceeds XML-RPC limits" write("") write(str(int(value))) write("\n") @@ -692,8 +706,8 @@ class Marshaller: def dump_array(self, value, write): i = id(value) - if self.memo.has_key(i): - raise TypeError("cannot marshal recursive sequences") + if i in self.memo: + raise TypeError, "cannot marshal recursive sequences" self.memo[i] = None dump = self.__dump write("\n") @@ -706,8 +720,8 @@ class Marshaller: def dump_struct(self, value, write, escape=escape): i = id(value) - if self.memo.has_key(i): - raise TypeError("cannot marshal recursive dictionaries") + if i in self.memo: + raise TypeError, "cannot marshal recursive dictionaries" self.memo[i] = None dump = self.__dump write("\n") @@ -717,7 +731,7 @@ class Marshaller: if unicode and type(k) is UnicodeType: k = k.encode(self.encoding) else: - raise TypeError("dictionary key must be string") + raise TypeError, "dictionary key must be string" write("%s\n" % escape(k)) dump(v, write) write("\n") @@ -728,23 +742,10 @@ class Marshaller: if datetime: def dump_datetime(self, value, write): write("") - write(value.strftime("%Y%m%dT%H:%M:%S")) + write(_strftime(value)) write("\n") dispatch[datetime.datetime] = dump_datetime - def dump_date(self, value, write): - write("") - write(value.strftime("%Y%m%dT00:00:00")) - write("\n") - dispatch[datetime.date] = dump_date - - def dump_time(self, value, write): - write("") - write(datetime.datetime.now().date().strftime("%Y%m%dT")) - write(value.strftime("%H:%M:%S")) - write("\n") - dispatch[datetime.time] = dump_time - def dump_instance(self, value, write): # check for special wrappers if value.__class__ in WRAPPERS: @@ -783,7 +784,7 @@ class Unmarshaller: self.append = self._stack.append self._use_datetime = use_datetime if use_datetime and not datetime: - raise ValueError("the datetime module is not available") + raise ValueError, "the datetime module is not available" def close(self): # return response tuple and target method @@ -850,7 +851,7 @@ class Unmarshaller: elif data == "1": self.append(True) else: - raise TypeError("bad boolean value") + raise TypeError, "bad boolean value" self._value = 0 dispatch["boolean"] = end_boolean @@ -858,6 +859,7 @@ class Unmarshaller: self.append(int(data)) self._value = 0 dispatch["i4"] = end_int + dispatch["i8"] = end_int dispatch["int"] = end_int def end_double(self, data): @@ -886,7 +888,7 @@ class Unmarshaller: dict = {} items = self._stack[mark:] for i in range(0, len(items), 2): - dict[_stringify(items[i])] = items[i + 1] + dict[_stringify(items[i])] = items[i+1] self._stack[mark:] = [dict] self._value = 0 dispatch["struct"] = end_struct @@ -944,7 +946,7 @@ class _MultiCallMethod: class MultiCallIterator: """Iterates over the results of a multicall. Exceptions are - thrown in response to xmlrpc faults.""" + raised in response to xmlrpc faults.""" def __init__(self, results): self.results = results @@ -956,7 +958,8 @@ class MultiCallIterator: elif type(item) == type([]): return item[0] else: - raise ValueError("unexpected type in multicall result") + raise ValueError, \ + "unexpected type in multicall result" class MultiCall: """server -> a object used to boxcar method calls @@ -1010,7 +1013,7 @@ def getparser(use_datetime=0): to an unmarshalling object. Return both objects. """ if use_datetime and not datetime: - raise ValueError("the datetime module is not available") + raise ValueError, "the datetime module is not available" if FastParser and FastUnmarshaller: if use_datetime: mkdatetime = _datetime_type @@ -1022,8 +1025,6 @@ def getparser(use_datetime=0): target = Unmarshaller(use_datetime=use_datetime) if FastParser: parser = FastParser(target) - elif SgmlopParser: - parser = SgmlopParser(target) elif ExpatParser: parser = ExpatParser(target) else: @@ -1067,7 +1068,7 @@ def dumps(params, methodname=None, methodresponse=None, encoding=None, """ assert isinstance(params, TupleType) or isinstance(params, Fault), \ - "argument must be tuple or Fault instance" + "argument must be tuple or Fault instance" if isinstance(params, Fault): methodresponse = 1 @@ -1100,7 +1101,7 @@ def dumps(params, methodname=None, methodresponse=None, encoding=None, "", methodname, "\n", data, "\n" - ) + ) elif methodresponse: # a method response, or a fault structure data = ( @@ -1108,7 +1109,7 @@ def dumps(params, methodname=None, methodresponse=None, encoding=None, "\n", data, "\n" - ) + ) else: return data # return as is return string.join(data, "") @@ -1136,6 +1137,86 @@ def loads(data, use_datetime=0): p.close() return u.close(), u.getmethodname() +## +# Encode a string using the gzip content encoding such as specified by the +# Content-Encoding: gzip +# in the HTTP header, as described in RFC 1952 +# +# @param data the unencoded data +# @return the encoded data + +def gzip_encode(data): + """data -> gzip encoded data + + Encode data using the gzip content encoding as described in RFC 1952 + """ + if not gzip: + raise NotImplementedError + f = StringIO.StringIO() + gzf = gzip.GzipFile(mode="wb", fileobj=f, compresslevel=1) + gzf.write(data) + gzf.close() + encoded = f.getvalue() + f.close() + return encoded + +## +# Decode a string using the gzip content encoding such as specified by the +# Content-Encoding: gzip +# in the HTTP header, as described in RFC 1952 +# +# @param data The encoded data +# @keyparam max_decode Maximum bytes to decode (20MB default), use negative +# values for unlimited decoding +# @return the unencoded data +# @raises ValueError if data is not correctly coded. +# @raises ValueError if max gzipped payload length exceeded + +def gzip_decode(data, max_decode=20971520): + """gzip encoded data -> unencoded data + + Decode data using the gzip content encoding as described in RFC 1952 + """ + if not gzip: + raise NotImplementedError + f = StringIO.StringIO(data) + gzf = gzip.GzipFile(mode="rb", fileobj=f) + try: + if max_decode < 0: # no limit + decoded = gzf.read() + else: + decoded = gzf.read(max_decode + 1) + except IOError: + raise ValueError("invalid data") + f.close() + gzf.close() + if max_decode >= 0 and len(decoded) > max_decode: + raise ValueError("max gzipped payload length exceeded") + return decoded + +## +# Return a decoded file-like object for the gzip encoding +# as described in RFC 1952. +# +# @param response A stream supporting a read() method +# @return a file-like object that the decoded data can be read() from + +class GzipDecodedResponse(gzip.GzipFile if gzip else object): + """a file-like object to decode a response encoded with the gzip + method, as described in RFC 1952. + """ + def __init__(self, response): + #response doesn't support tell() and read(), required by + #GzipFile + if not gzip: + raise NotImplementedError + self.stringio = StringIO.StringIO(response.read()) + gzip.GzipFile.__init__(self, mode="rb", fileobj=self.stringio) + + def close(self): + gzip.GzipFile.close(self) + self.stringio.close() + # -------------------------------------------------------------------- # request dispatcher @@ -1163,8 +1244,39 @@ class Transport: # client identifier (may be overridden) user_agent = "xmlrpclib.py/%s (by www.pythonware.com)" % __version__ + #if true, we'll request gzip encoding + accept_gzip_encoding = True + + # if positive, encode request using gzip if it exceeds this threshold + # note that many server will get confused, so only use it if you know + # that they can decode such a request + encode_threshold = None #None = don't encode + def __init__(self, use_datetime=0): self._use_datetime = use_datetime + self._connection = (None, None) + self._extra_headers = [] + ## + # Send a complete request, and parse the response. + # Retry request if a cached connection has disconnected. + # + # @param host Target host. + # @param handler Target PRC handler. + # @param request_body XML-RPC request body. + # @param verbose Debugging flag. + # @return Parsed response. + + def request(self, host, handler, request_body, verbose=0): + #retry request once if cached connection has gone cold + for i in (0, 1): + try: + return self.single_request(host, handler, request_body, verbose) + except socket.error, e: + if i or e.errno not in (errno.ECONNRESET, errno.ECONNABORTED, errno.EPIPE): + raise + except httplib.BadStatusLine: #close after we sent request + if i: + raise ## # Send a complete request, and parse the response. @@ -1175,35 +1287,39 @@ class Transport: # @param verbose Debugging flag. # @return Parsed response. - def request(self, host, handler, request_body, verbose=0): + def single_request(self, host, handler, request_body, verbose=0): # issue XML-RPC request h = self.make_connection(host) if verbose: h.set_debuglevel(1) - self.send_request(h, handler, request_body) - self.send_host(h, host) - self.send_user_agent(h) - self.send_content(h, request_body) - - errcode, errmsg, headers = h.getreply() - - if errcode != 200: - raise ProtocolError( - host + handler, - errcode, errmsg, - headers - ) - - self.verbose = verbose - try: - sock = h._conn.sock - except AttributeError: - sock = None + self.send_request(h, handler, request_body) + self.send_host(h, host) + self.send_user_agent(h) + self.send_content(h, request_body) - return self._parse_response(h.getfile(), sock) + response = h.getresponse(buffering=True) + if response.status == 200: + self.verbose = verbose + return self.parse_response(response) + except Fault: + raise + except Exception: + # All unexpected errors leave connection in + # a strange state, so we clear it. + self.close() + raise + + #discard any response data and raise exception + if (response.getheader("content-length", 0)): + response.read() + raise ProtocolError( + host + handler, + response.status, response.reason, + response.msg, + ) ## # Create parser. @@ -1239,7 +1355,7 @@ class Transport: auth = string.join(string.split(auth), "") # get rid of whitespace extra_headers = [ ("Authorization", "Basic " + auth) - ] + ] else: extra_headers = None @@ -1252,10 +1368,25 @@ class Transport: # @return A connection handle. def make_connection(self, host): + #return an existing connection if possible. This allows + #HTTP/1.1 keep-alive. + if self._connection and host == self._connection[0]: + return self._connection[1] + # create a HTTP connection object from a host descriptor - import httplib - host, extra_headers, x509 = self.get_host_info(host) - return httplib.HTTP(host) + chost, self._extra_headers, x509 = self.get_host_info(host) + #store the host argument along with the connection object + self._connection = host, httplib.HTTPConnection(chost) + return self._connection[1] + + ## + # Clear any cached connection object. + # Used in the event of socket errors. + # + def close(self): + if self._connection[1]: + self._connection[1].close() + self._connection = (None, None) ## # Send request header. @@ -1265,17 +1396,24 @@ class Transport: # @param request_body XML-RPC body. def send_request(self, connection, handler, request_body): - connection.putrequest("POST", handler) + if (self.accept_gzip_encoding and gzip): + connection.putrequest("POST", handler, skip_accept_encoding=True) + connection.putheader("Accept-Encoding", "gzip") + else: + connection.putrequest("POST", handler) ## # Send host name. # # @param connection Connection handle. # @param host Host name. + # + # Note: This function doesn't actually add the "Host" + # header anymore, it is done as part of the connection.putrequest() in + # send_request() above. def send_host(self, connection, host): - host, extra_headers, x509 = self.get_host_info(host) - connection.putheader("Host", host) + extra_headers = self._extra_headers if extra_headers: if isinstance(extra_headers, DictType): extra_headers = extra_headers.items() @@ -1298,10 +1436,16 @@ class Transport: def send_content(self, connection, request_body): connection.putheader("Content-Type", "text/xml") + + #optionally encode the request + if (self.encode_threshold is not None and + self.encode_threshold < len(request_body) and + gzip): + connection.putheader("Content-Encoding", "gzip") + request_body = gzip_encode(request_body) + connection.putheader("Content-Length", str(len(request_body))) - connection.endheaders() - if request_body: - connection.send(request_body) + connection.endheaders(request_body) ## # Parse response. @@ -1309,37 +1453,30 @@ class Transport: # @param file Stream. # @return Response tuple and target method. - def parse_response(self, file): - # compatibility interface - return self._parse_response(file, None) + def parse_response(self, response): + # read response data from httpresponse, and parse it - ## - # Parse response (alternate interface). This is similar to the - # parse_response method, but also provides direct access to the - # underlying socket object (where available). - # - # @param file Stream. - # @param sock Socket handle (or None, if the socket object - # could not be accessed). - # @return Response tuple and target method. - - def _parse_response(self, file, sock): - # read response from input file/socket, and parse it + # Check for new http response object, else it is a file object + if hasattr(response,'getheader'): + if response.getheader("Content-Encoding", "") == "gzip": + stream = GzipDecodedResponse(response) + else: + stream = response + else: + stream = response p, u = self.getparser() while 1: - if sock: - response = sock.recv(1024) - else: - response = file.read(1024) - if not response: + data = stream.read(1024) + if not data: break if self.verbose: - sys.stdout.write("body: %s\n" % repr(response)) - p.feed(response) + print "body:", repr(data) + p.feed(data) - file.close() + if stream is not response: + stream.close() p.close() return u.close() @@ -1353,18 +1490,20 @@ class SafeTransport(Transport): # FIXME: mostly untested def make_connection(self, host): + if self._connection and host == self._connection[0]: + return self._connection[1] # create a HTTPS connection object from a host descriptor # host may be a string, or a (host, x509-dict) tuple - import httplib - host, extra_headers, x509 = self.get_host_info(host) try: - HTTPS = httplib.HTTPS + HTTPS = httplib.HTTPSConnection except AttributeError: raise NotImplementedError( "your version of httplib doesn't support HTTPS" - ) + ) else: - return HTTPS(host, None, **(x509 or {})) + chost, self._extra_headers, x509 = self.get_host_info(host) + self._connection = host, HTTPS(chost, None, **(x509 or {})) + return self._connection[1] ## # Standard server proxy. This class establishes a virtual connection @@ -1409,11 +1548,14 @@ class ServerProxy: allow_none=0, use_datetime=0): # establish a "logical" server connection + if isinstance(uri, unicode): + uri = uri.encode('ISO-8859-1') + # get the url import urllib type, uri = urllib.splittype(uri) if type not in ("http", "https"): - raise IOError("unsupported XML-RPC protocol") + raise IOError, "unsupported XML-RPC protocol" self.__host, self.__handler = urllib.splithost(uri) if not self.__handler: self.__handler = "/RPC2" @@ -1429,6 +1571,9 @@ class ServerProxy: self.__verbose = verbose self.__allow_none = allow_none + def __close(self): + self.__transport.close() + def __request(self, methodname, params): # call a method on the remote server @@ -1440,7 +1585,7 @@ class ServerProxy: self.__handler, request, verbose=self.__verbose - ) + ) if len(response) == 1: response = response[0] @@ -1449,9 +1594,9 @@ class ServerProxy: def __repr__(self): return ( - "" % - (self.__host, self.__handler) - ) + "" % + (self.__host, self.__handler) + ) __str__ = __repr__ @@ -1462,6 +1607,16 @@ class ServerProxy: # note: to call a remote object with an non-standard name, use # result getattr(server, "strange-python-name")(args) + def __call__(self, attr): + """A workaround to get special attributes on the ServerProxy + without interfering with the magic __getattr__ + """ + if attr == "close": + return self.__close + elif attr == "transport": + return self.__transport + raise AttributeError("Attribute %r not found" % (attr,)) + # compatibility Server = ServerProxy @@ -1471,23 +1626,16 @@ Server = ServerProxy if __name__ == "__main__": - # simple test program (from the XML-RPC specification) + server = ServerProxy("http://localhost:8000") - # server = ServerProxy("http://localhost:8000") # local server - server = ServerProxy("http://time.xmlrpc.com/RPC2") - - sys.stdout.write('%s\n' % server) - - try: - sys.stdout.write('%s\n' % (server.currentTime.getCurrentTime(),)) - except Error: - import traceback;traceback.print_exc() + print server multi = MultiCall(server) - multi.currentTime.getCurrentTime() - multi.currentTime.getCurrentTime() + multi.pow(2, 9) + multi.add(5, 1) + multi.add(24, 11) try: for response in multi(): - sys.stdout.write('%s\n' % (response,)) - except Error: - import traceback;traceback.print_exc() + print response + except Error, v: + print "ERROR", v diff --git a/python/helpers/pydev/_pydevd_bundle/pydevconsole_code_for_ironpython.py b/python/helpers/pydev/_pydevd_bundle/pydevconsole_code_for_ironpython.py index 71346ccd0f96..541e319f80a1 100644 --- a/python/helpers/pydev/_pydevd_bundle/pydevconsole_code_for_ironpython.py +++ b/python/helpers/pydev/_pydevd_bundle/pydevconsole_code_for_ironpython.py @@ -102,23 +102,23 @@ def _maybe_compile(compiler, source, filename, symbol): try: code = compiler(source, filename, symbol) - except SyntaxError, err: + except SyntaxError: pass try: code1 = compiler(source + "\n", filename, symbol) - except SyntaxError, err1: + except SyntaxError as err1: pass try: code2 = compiler(source + "\n\n", filename, symbol) - except SyntaxError, err2: + except SyntaxError as err2: pass if code: return code if not code1 and repr(err1) == repr(err2): - raise SyntaxError, err1 + raise SyntaxError(err1) def _compile(source, filename, symbol): return compile(source, filename, symbol, PyCF_DONT_IMPLY_DEDENT) diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_dont_trace_files.py b/python/helpers/pydev/_pydevd_bundle/pydevd_dont_trace_files.py index 33dd8c8b2252..8c192a70738d 100644 --- a/python/helpers/pydev/_pydevd_bundle/pydevd_dont_trace_files.py +++ b/python/helpers/pydev/_pydevd_bundle/pydevd_dont_trace_files.py @@ -37,7 +37,6 @@ DONT_TRACE = { '_pydev_saved_modules.py': PYDEV_FILE, '_pydev_sys_patch.py': PYDEV_FILE, '_pydev_tipper_common.py': PYDEV_FILE, - '_pydev_uuid_old.py': PYDEV_FILE, '_pydev_xmlrpclib.py': PYDEV_FILE, 'django_debug.py': PYDEV_FILE, 'fix_getpass.py': PYDEV_FILE, @@ -99,6 +98,7 @@ DONT_TRACE = { 'pydevd_plugin_utils.py': PYDEV_FILE, 'pydevd_plugins_django_form_str.py': PYDEV_FILE, 'pydevd_process_net_command.py': PYDEV_FILE, + 'pydevd_pycharm.py': PYDEV_FILE, 'pydevd_referrers.py': PYDEV_FILE, 'pydevd_reload.py': PYDEV_FILE, 'pydevd_resolver.py': PYDEV_FILE, @@ -106,6 +106,7 @@ DONT_TRACE = { 'pydevd_signature.py': PYDEV_FILE, 'pydevd_stackless.py': PYDEV_FILE, 'pydevd_thread_wrappers.py': PYDEV_FILE, + 'pydevd_thrift.py': PYDEV_FILE, 'pydevd_trace_api.py': PYDEV_FILE, 'pydevd_trace_dispatch.py': PYDEV_FILE, 'pydevd_trace_dispatch_regular.py': PYDEV_FILE, diff --git a/python/helpers/pydev/pydev_ipython/inputhookglut.py b/python/helpers/pydev/pydev_ipython/inputhookglut.py index bbd6882fe8ec..1ace8f73f083 100644 --- a/python/helpers/pydev/pydev_ipython/inputhookglut.py +++ b/python/helpers/pydev/pydev_ipython/inputhookglut.py @@ -95,7 +95,7 @@ def glut_close(): def glut_int_handler(signum, frame): # Catch sigint and print the defautl message signal.signal(signal.SIGINT, signal.default_int_handler) - print '\nKeyboardInterrupt' + print('\nKeyboardInterrupt') # Need to reprint the prompt at this stage diff --git a/python/helpers/pydev/pydevd_attach_to_process/_check.py b/python/helpers/pydev/pydevd_attach_to_process/_check.py index 82f8e12290ac..5baa4a1c4ce7 100644 --- a/python/helpers/pydev/pydevd_attach_to_process/_check.py +++ b/python/helpers/pydev/pydevd_attach_to_process/_check.py @@ -1,2 +1,2 @@ import add_code_to_python_process -print add_code_to_python_process.run_python_code(3736, "print(20)", connect_debugger_tracing=False) \ No newline at end of file +print(add_code_to_python_process.run_python_code(3736, "print(20)", connect_debugger_tracing=False)) \ No newline at end of file diff --git a/python/helpers/pydev/pydevd_attach_to_process/winappdbg/plugins/do_example.py b/python/helpers/pydev/pydevd_attach_to_process/winappdbg/plugins/do_example.py index 591ce68bcab8..47ded2fae923 100644 --- a/python/helpers/pydev/pydevd_attach_to_process/winappdbg/plugins/do_example.py +++ b/python/helpers/pydev/pydevd_attach_to_process/winappdbg/plugins/do_example.py @@ -34,8 +34,8 @@ __revision__ = "$Id$" def do(self, arg): ".example - This is an example plugin for the command line debugger" - print "This is an example command." - print "%s.do(%r, %r):" % (__name__, self, arg) - print " last event", self.lastEvent - print " prefix", self.cmdprefix - print " arguments", self.split_tokens(arg) + print("This is an example command.") + print("%s.do(%r, %r):" % (__name__, self, arg)) + print(" last event", self.lastEvent) + print(" prefix", self.cmdprefix) + print(" arguments", self.split_tokens(arg)) diff --git a/python/helpers/pydev/pydevd_attach_to_process/winappdbg/plugins/do_exchain.py b/python/helpers/pydev/pydevd_attach_to_process/winappdbg/plugins/do_exchain.py index aa97fec7037e..c38adf6cc05c 100644 --- a/python/helpers/pydev/pydevd_attach_to_process/winappdbg/plugins/do_exchain.py +++ b/python/helpers/pydev/pydevd_attach_to_process/winappdbg/plugins/do_exchain.py @@ -37,8 +37,7 @@ from winappdbg import HexDump, Table def do(self, arg): ".exchain - Show the SEH chain" thread = self.get_thread_from_prefix() - print "Exception handlers for thread %d" % thread.get_tid() - print + print("Exception handlers for thread %d" % thread.get_tid()) table = Table() table.addRow("Block", "Function") bits = thread.get_bits() @@ -48,4 +47,4 @@ def do(self, arg): if seh_func is not None: seh_func = HexDump.address(seh_func, bits) table.addRow(seh, seh_func) - print table.getOutput() + print(table.getOutput()) diff --git a/python/helpers/pydev/pydevd_attach_to_process/winappdbg/plugins/do_exploitable.py b/python/helpers/pydev/pydevd_attach_to_process/winappdbg/plugins/do_exploitable.py index 64e93f6faabf..3749556ea3a3 100644 --- a/python/helpers/pydev/pydevd_attach_to_process/winappdbg/plugins/do_exploitable.py +++ b/python/helpers/pydev/pydevd_attach_to_process/winappdbg/plugins/do_exploitable.py @@ -43,8 +43,8 @@ def do(self, arg): status, rule, description = crash.isExploitable() - print "-" * 79 - print "Exploitability: %s" % status - print "Matched rule: %s" % rule - print "Description: %s" % description - print "-" * 79 + print("-" * 79) + print("Exploitability: %s" % status) + print("Matched rule: %s" % rule) + print("Description: %s" % description) + print("-" * 79) diff --git a/python/helpers/pydev/pydevd_pycharm.py b/python/helpers/pydev/pydevd_pycharm.py new file mode 100644 index 000000000000..b93e39dc1424 --- /dev/null +++ b/python/helpers/pydev/pydevd_pycharm.py @@ -0,0 +1,3 @@ + +# make settrace() function available for `pydevd_pycharm` +from pydevd import settrace \ No newline at end of file diff --git a/python/helpers/pydev/setup.py b/python/helpers/pydev/setup.py index 6d64bf552d83..c46298a5f116 100644 --- a/python/helpers/pydev/setup.py +++ b/python/helpers/pydev/setup.py @@ -69,6 +69,7 @@ from setuptools import setup from setuptools.dist import Distribution from distutils.extension import Extension import os +import sys class BinaryDistribution(Distribution): def is_pure(self): @@ -84,21 +85,45 @@ def accept_file(f): return f in ['readme', 'makefile'] -data_files.append(('pydevd_attach_to_process', [os.path.join('pydevd_attach_to_process', f) for f in os.listdir('pydevd_attach_to_process') if accept_file(f)])) -for root, dirs, files in os.walk("pydevd_attach_to_process"): - for d in dirs: - data_files.append((os.path.join(root, d), [os.path.join(root, d, f) for f in os.listdir(os.path.join(root, d)) if accept_file(f)])) -import pydevd -version = pydevd.__version__ +def add_directory_to_datafiles(datafiles, dir): + datafiles.append((dir, [os.path.join(dir, f) for f in os.listdir(dir) if accept_file(f)])) + for root, dirs, files in os.walk(dir): + for d in dirs: + datafiles.append((os.path.join(root, d), [os.path.join(root, d, f) for f in os.listdir(os.path.join(root, d)) if accept_file(f)])) + + +def accept_extension(f): + f = f.lower() + for ext in '.pyd .so'.split(): + if f.endswith(ext): + return True + return False + + +def add_extensions_to_datafiles(datafiles, dir): + datafiles.append((dir, [os.path.join(dir, f) for f in os.listdir(dir) if accept_extension(f)])) + + +add_directory_to_datafiles(data_files, 'pydevd_attach_to_process') +add_extensions_to_datafiles(data_files, '_pydevd_bundle') +add_extensions_to_datafiles(data_files, '_pydevd_frame_eval') + + +def get_version_from_file(): + with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'VERSION')) as version_file: + version = version_file.read().strip() + return version + +version = get_version_from_file() args = dict( - name='pydevd', + name='pydevd-pycharm', version=version, - description = 'PyDev.Debugger (used in PyDev and PyCharm)', - author='Fabio Zadrozny and others', - url='https://github.com/fabioz/PyDev.Debugger/', - license='EPL (Eclipse Public License)', + description = 'PyCharm Debugger (used in PyCharm and PyDev)', + author='JetBrains, Fabio Zadrozny and others', + url='https://github.com/JetBrains/intellij-community', + license='Apache 2.0', packages=[ '_pydev_bundle', '_pydev_imps', @@ -106,11 +131,8 @@ args = dict( '_pydevd_bundle', '_pydevd_frame_eval', 'pydev_ipython', - # 'pydev_sitecustomize', -- Not actually a package (not added) - # 'pydevd_attach_to_process', -- Not actually a package (included in MANIFEST.in) - 'pydevd_concurrency_analyser', 'pydevd_plugins', 'pydevd_plugins.extensions', @@ -124,9 +146,10 @@ args = dict( 'pydevconsole', 'pydevd_file_utils', 'pydevd', + 'pydevd_pycharm', 'pydevd_tracing', # 'runfiles', -- Not needed for debugger - # 'setup_cython', -- Should not be included as a module + 'setup_cython', # Distributed to clients. See: https://github.com/fabioz/PyDev.Debugger/issues/102 # 'setup', -- Should not be included as a module ], classifiers=[ @@ -134,14 +157,19 @@ args = dict( 'Environment :: Console', 'Intended Audience :: Developers', - # It seems that the license is not recognized by Pypi, so, not categorizing it for now. - # https://bitbucket.org/pypa/pypi/issues/369/the-eclipse-public-license-superseeded - # 'License :: OSI Approved :: Eclipse Public License', + 'Apache Software License (Apache License 2.0)', 'Operating System :: MacOS :: MacOS X', 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX', 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', 'Topic :: Software Development :: Debuggers', ], entry_points={ @@ -150,26 +178,36 @@ args = dict( ], }, data_files=data_files, - keywords=['pydev', 'pydevd', 'pydev.debugger'], + keywords=['pydev', 'pydevd', 'pydev.debugger', 'pycharm'], include_package_data=True, zip_safe=False, ) +args_with_binaries = args.copy() -import sys -try: - args_with_binaries = args.copy() +if sys.platform not in ('darwin', 'win32'): args_with_binaries.update(dict( distclass=BinaryDistribution, ext_modules=[ # In this setup, don't even try to compile with cython, just go with the .c file which should've # been properly generated from a tested version. - Extension('_pydevd_bundle.pydevd_cython', ["_pydevd_bundle/pydevd_cython.c",]) + Extension('_pydevd_bundle.pydevd_cython', ['_pydevd_bundle/pydevd_cython.c',]) ] )) + if sys.version_info >= (3, 6): + args_with_binaries.update(dict( + distclass=BinaryDistribution, + ext_modules=[ + # In this setup, don't even try to compile with cython, just go with the .c file which should've + # been properly generated from a tested version. + Extension('_pydevd_frame_eval.pydevd_frame_evaluator', ['_pydevd_frame_eval/pydevd_frame_evaluator.c',]) + ] + )) + +try: setup(**args_with_binaries) except: # Compile failed: just setup without compiling cython deps. setup(**args) - sys.stdout.write('Plain-python version of pydevd installed (cython speedups not available).\n') + sys.stdout.write('Plain-python version of pydevd-pycharm installed (cython speedups not available).\n') diff --git a/python/helpers/pydev/stubs/_get_tips.py b/python/helpers/pydev/stubs/_get_tips.py index b98e1c536cea..71c6ef24cd5b 100644 --- a/python/helpers/pydev/stubs/_get_tips.py +++ b/python/helpers/pydev/stubs/_get_tips.py @@ -277,4 +277,4 @@ def %(method_name)s%(args)s: for line in doc.splitlines(): lines.append(' ' + line) doc = '\n'.join(lines) - print temp % dict(method_name=entry[0], args=entry[2] or '(self)', doc=doc) + print(temp % dict(method_name=entry[0], args=entry[2] or '(self)', doc=doc)) diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties index 40be18bc078d..a90aaf2d912b 100644 --- a/python/src/com/jetbrains/python/PyBundle.properties +++ b/python/src/com/jetbrains/python/PyBundle.properties @@ -902,10 +902,11 @@ debug.notification.group=Python Debugger debug.notification.title.connection.failed=Connection to Python debugger failed remote.debug.info=Info -remote.debug.server.hint=Launch this debug configuration to start the debug server. +remote.debug.server.hint=Launch this debug configuration to start the Debug Server. remote.debug.server.hint1.5=Update your script: -remote.debug.server.hint2=1. Add pycharm-debug.egg from the PyCharm installation to the Python path. -remote.debug.server.hint3=2. Add the following command to connect to the debug server: +remote.debug.server.hint2=1. Add pydevd-pycharm.egg from the PyCharm installation to the Python path or execute: +remote.debug.server.hint3=pip install pydevd-pycharm +remote.debug.server.hint4=2. Add the following command to connect to the Debug Server: remote.debug.settings=Settings remote.debug.remote.host=Remote host remote.debug.port=Port: