Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: sourcepole/qgis-remote-debug
base: 9b13262ae7
...
head fork: sourcepole/qgis-remote-debug
compare: 0c5b8ae3d0
Checking mergeability… Don't worry, you can still create the pull request.
  • 2 commits
  • 58 files changed
  • 0 commit comments
  • 1 contributor
Showing with 13,861 additions and 71 deletions.
  1. +117 −0 RemoteDebug/Makefile
  2. BIN  RemoteDebug/icon.png
  3. 0  RemoteDebug/pysrc/__init__.py
  4. +610 −0 RemoteDebug/pysrc/_pydev_SimpleXMLRPCServer.py
  5. +193 −0 RemoteDebug/pysrc/_pydev_completer.py
  6. +38 −0 RemoteDebug/pysrc/_pydev_execfile.py
  7. +130 −0 RemoteDebug/pysrc/_pydev_getopt.py
  8. +347 −0 RemoteDebug/pysrc/_pydev_imports_tipper.py
  9. +788 −0 RemoteDebug/pysrc/_pydev_inspect.py
  10. +479 −0 RemoteDebug/pysrc/_pydev_jy_imports_tipper.py
  11. +28 −0 RemoteDebug/pysrc/_pydev_log.py
  12. +66 −0 RemoteDebug/pysrc/_pydev_tipper_common.py
  13. +1,493 −0 RemoteDebug/pysrc/_pydev_xmlrpclib.py
  14. +11 −0 RemoteDebug/pysrc/_pydevd_re.py
  15. +196 −0 RemoteDebug/pysrc/interpreterInfo.py
  16. +41 −0 RemoteDebug/pysrc/pycompletion.py
  17. +389 −0 RemoteDebug/pysrc/pycompletionserver.py
  18. +338 −0 RemoteDebug/pysrc/pydev_console_utils.py
  19. +54 −0 RemoteDebug/pysrc/pydev_coverage.py
  20. +34 −0 RemoteDebug/pysrc/pydev_imports.py
  21. +70 −0 RemoteDebug/pysrc/pydev_ipython_console.py
  22. +87 −0 RemoteDebug/pysrc/pydev_ipython_console_010.py
  23. +132 −0 RemoteDebug/pysrc/pydev_ipython_console_011.py
  24. +29 −0 RemoteDebug/pysrc/pydev_localhost.py
  25. +49 −0 RemoteDebug/pysrc/pydev_override.py
  26. +761 −0 RemoteDebug/pysrc/pydev_runfiles.py
  27. +76 −0 RemoteDebug/pysrc/pydev_runfiles_coverage.py
  28. +180 −0 RemoteDebug/pysrc/pydev_runfiles_nose.py
  29. +298 −0 RemoteDebug/pysrc/pydev_runfiles_parallel.py
  30. +219 −0 RemoteDebug/pysrc/pydev_runfiles_parallel_client.py
  31. +189 −0 RemoteDebug/pysrc/pydev_runfiles_pytest.py
  32. +159 −0 RemoteDebug/pysrc/pydev_runfiles_unittest.py
  33. +231 −0 RemoteDebug/pysrc/pydev_runfiles_xml_rpc.py
  34. +1 −0  RemoteDebug/pysrc/pydev_sitecustomize/__not_in_default_pythonpath.txt
  35. +262 −0 RemoteDebug/pysrc/pydev_sitecustomize/sitecustomize.py
  36. +275 −0 RemoteDebug/pysrc/pydevconsole.py
  37. +513 −0 RemoteDebug/pysrc/pydevconsole_code_for_ironpython.py
  38. +1,393 −0 RemoteDebug/pysrc/pydevd.py
  39. +140 −0 RemoteDebug/pysrc/pydevd_additional_thread_info.py
  40. +895 −0 RemoteDebug/pysrc/pydevd_comm.py
  41. +218 −0 RemoteDebug/pysrc/pydevd_console.py
  42. +211 −0 RemoteDebug/pysrc/pydevd_constants.py
  43. +2 −0  RemoteDebug/pysrc/pydevd_exec.py
  44. +2 −0  RemoteDebug/pysrc/pydevd_exec2.py
  45. +229 −0 RemoteDebug/pysrc/pydevd_file_utils.py
  46. +232 −0 RemoteDebug/pysrc/pydevd_frame.py
  47. +68 −0 RemoteDebug/pysrc/pydevd_import_class.py
  48. +88 −0 RemoteDebug/pysrc/pydevd_io.py
  49. +36 −0 RemoteDebug/pysrc/pydevd_psyco_stub.py
  50. +208 −0 RemoteDebug/pysrc/pydevd_reload.py
  51. +352 −0 RemoteDebug/pysrc/pydevd_resolver.py
  52. +108 −0 RemoteDebug/pysrc/pydevd_traceproperty.py
  53. +78 −0 RemoteDebug/pysrc/pydevd_tracing.py
  54. +445 −0 RemoteDebug/pysrc/pydevd_vars.py
  55. +41 −0 RemoteDebug/pysrc/pydevd_vm_type.py
  56. +170 −0 RemoteDebug/pysrc/runfiles.py
  57. +11 −4 RemoteDebug/remotedebug.py
  58. +51 −67 RemoteDebug/resources_rc.py
View
117 RemoteDebug/Makefile
@@ -0,0 +1,117 @@
+#/***************************************************************************
+# RemoteDebug
+#
+# RemoteDebug
+# -------------------
+# begin : 2012-07-30
+# copyright : (C) 2012 by RemoteDebug
+# email : RemoteDebug
+# ***************************************************************************/
+#
+#/***************************************************************************
+# * *
+# * This program is free software; you can redistribute it and/or modify *
+# * it under the terms of the GNU General Public License as published by *
+# * the Free Software Foundation; either version 2 of the License, or *
+# * (at your option) any later version. *
+# * *
+# ***************************************************************************/
+
+# CONFIGURATION
+PLUGIN_UPLOAD = $(CURDIR)/plugin_upload.py
+
+# Makefile for a PyQGIS plugin
+
+# translation
+SOURCES = remotedebug.py __init__.py
+#TRANSLATIONS = i18n/remotedebug_en.ts
+TRANSLATIONS =
+
+# global
+
+PLUGINNAME = remotedebug
+
+PY_FILES = remotedebug.py __init__.py
+
+EXTRAS = icon.png
+
+#UI_FILES = ui_remotedebug.py
+
+RESOURCE_FILES = resources_rc.py
+
+HELP = help/build/html
+
+default: compile
+
+compile: $(UI_FILES) $(RESOURCE_FILES)
+
+%_rc.py : %.qrc
+ pyrcc4 -o $*_rc.py $<
+
+%.py : %.ui
+ pyuic4 -o $@ $<
+
+%.qm : %.ts
+ lrelease $<
+
+# The deploy target only works on unix like operating system where
+# the Python plugin directory is located at:
+# $HOME/.qgis/python/plugins
+deploy: compile doc transcompile
+ mkdir -p $(HOME)/.qgis/python/plugins/$(PLUGINNAME)
+ cp -vf $(PY_FILES) $(HOME)/.qgis/python/plugins/$(PLUGINNAME)
+ cp -vf $(UI_FILES) $(HOME)/.qgis/python/plugins/$(PLUGINNAME)
+ cp -vf $(RESOURCE_FILES) $(HOME)/.qgis/python/plugins/$(PLUGINNAME)
+ cp -vf $(EXTRAS) $(HOME)/.qgis/python/plugins/$(PLUGINNAME)
+ cp -vfr i18n $(HOME)/.qgis/python/plugins/$(PLUGINNAME)
+ cp -vfr $(HELP) $(HOME)/.qgis/python/plugins/$(PLUGINNAME)/help
+
+# The dclean target removes compiled python files from plugin directory
+# also delets any .svn entry
+dclean:
+ find $(HOME)/.qgis/python/plugins/$(PLUGINNAME) -iname "*.pyc" -delete
+ find $(HOME)/.qgis/python/plugins/$(PLUGINNAME) -iname ".svn" -prune -exec rm -Rf {} \;
+
+# The derase deletes deployed plugin
+derase:
+ rm -Rf $(HOME)/.qgis/python/plugins/$(PLUGINNAME)
+
+# The zip target deploys the plugin and creates a zip file with the deployed
+# content. You can then upload the zip file on http://plugins.qgis.org
+zip: deploy dclean
+ rm -f $(PLUGINNAME).zip
+ cd $(HOME)/.qgis/python/plugins; zip -9r $(CURDIR)/$(PLUGINNAME).zip $(PLUGINNAME)
+
+# Create a zip package of the plugin named $(PLUGINNAME).zip.
+# This requires use of git (your plugin development directory must be a
+# git repository).
+# To use, pass a valid commit or tag as follows:
+# make package VERSION=Version_0.3.2
+package: compile
+ rm -f $(PLUGINNAME).zip
+ git archive --prefix=$(PLUGINNAME)/ -o $(PLUGINNAME).zip $(VERSION)
+ echo "Created package: $(PLUGINNAME).zip"
+
+upload: zip
+ $(PLUGIN_UPLOAD) $(PLUGINNAME).zip
+
+# transup
+# update .ts translation files
+transup:
+ pylupdate4 Makefile
+
+# transcompile
+# compile translation files into .qm binary format
+transcompile: $(TRANSLATIONS:.ts=.qm)
+
+# transclean
+# deletes all .qm files
+transclean:
+ rm -f i18n/*.qm
+
+clean:
+ rm $(UI_FILES) $(RESOURCE_FILES)
+
+# build documentation with sphinx
+doc:
+ cd help; make html
View
BIN  RemoteDebug/icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
0  RemoteDebug/pysrc/__init__.py
No changes.
View
610 RemoteDebug/pysrc/_pydev_SimpleXMLRPCServer.py
@@ -0,0 +1,610 @@
+#Just a copy of the version in python 2.5 to be used if it's not available in jython 2.1
+
+"""Simple XML-RPC Server.
+
+This module can be used to create simple XML-RPC servers
+by creating a server and either installing functions, a
+class instance, or by extending the SimpleXMLRPCServer
+class.
+
+It can also be used to handle XML-RPC requests in a CGI
+environment using CGIXMLRPCRequestHandler.
+
+A list of possible usage patterns follows:
+
+1. Install functions:
+
+server = SimpleXMLRPCServer(("localhost", 8000))
+server.register_function(pow)
+server.register_function(lambda x,y: x+y, 'add')
+server.serve_forever()
+
+2. Install an instance:
+
+class MyFuncs:
+ def __init__(self):
+ # make all of the string functions available through
+ # string.func_name
+ import string
+ self.string = string
+ def _listMethods(self):
+ # implement this method so that system.listMethods
+ # knows to advertise the strings methods
+ return list_public_methods(self) + \
+ ['string.' + method for method in list_public_methods(self.string)]
+ def pow(self, x, y): return pow(x, y)
+ def add(self, x, y) : return x + y
+
+server = SimpleXMLRPCServer(("localhost", 8000))
+server.register_introspection_functions()
+server.register_instance(MyFuncs())
+server.serve_forever()
+
+3. Install an instance with custom dispatch method:
+
+class Math:
+ def _listMethods(self):
+ # this method must be present for system.listMethods
+ # to work
+ return ['add', 'pow']
+ def _methodHelp(self, method):
+ # this method must be present for system.methodHelp
+ # to work
+ if method == 'add':
+ return "add(2,3) => 5"
+ elif method == 'pow':
+ return "pow(x, y[, z]) => number"
+ else:
+ # By convention, return empty
+ # string if no help is available
+ return ""
+ def _dispatch(self, method, params):
+ if method == 'pow':
+ return pow(*params)
+ elif method == 'add':
+ return params[0] + params[1]
+ else:
+ raise 'bad method'
+
+server = SimpleXMLRPCServer(("localhost", 8000))
+server.register_introspection_functions()
+server.register_instance(Math())
+server.serve_forever()
+
+4. Subclass SimpleXMLRPCServer:
+
+class MathServer(SimpleXMLRPCServer):
+ def _dispatch(self, method, params):
+ try:
+ # We are forcing the 'export_' prefix on methods that are
+ # callable through XML-RPC to prevent potential security
+ # problems
+ func = getattr(self, 'export_' + method)
+ except AttributeError:
+ raise Exception('method "%s" is not supported' % method)
+ else:
+ return func(*params)
+
+ def export_add(self, x, y):
+ return x + y
+
+server = MathServer(("localhost", 8000))
+server.serve_forever()
+
+5. CGI script:
+
+server = CGIXMLRPCRequestHandler()
+server.register_function(pow)
+server.handle_request()
+"""
+
+# Written by Brian Quinlan (brian@sweetapp.com).
+# Based on code written by Fredrik Lundh.
+
+try:
+ True
+ False
+except:
+ import __builtin__
+ setattr(__builtin__, 'True', 1) #Python 3.0 does not accept __builtin__.True = 1 in its syntax
+ setattr(__builtin__, 'False', 0)
+
+
+import _pydev_xmlrpclib as xmlrpclib
+from _pydev_xmlrpclib import Fault
+import SocketServer
+import BaseHTTPServer
+import sys
+import os
+try:
+ import fcntl
+except ImportError:
+ fcntl = None
+
+def resolve_dotted_attribute(obj, attr, allow_dotted_names=True):
+ """resolve_dotted_attribute(a, 'b.c.d') => a.b.c.d
+
+ Resolves a dotted attribute name to an object. Raises
+ an AttributeError if any attribute in the chain starts with a '_'.
+
+ If the optional allow_dotted_names argument is false, dots are not
+ supported and this function operates similar to getattr(obj, attr).
+ """
+
+ if allow_dotted_names:
+ attrs = attr.split('.')
+ else:
+ attrs = [attr]
+
+ for i in attrs:
+ if i.startswith('_'):
+ raise AttributeError(
+ 'attempt to access private attribute "%s"' % i
+ )
+ else:
+ obj = getattr(obj, i)
+ return obj
+
+def list_public_methods(obj):
+ """Returns a list of attribute strings, found in the specified
+ object, which represent callable attributes"""
+
+ return [member for member in dir(obj)
+ if not member.startswith('_') and
+ callable(getattr(obj, member))]
+
+def remove_duplicates(lst):
+ """remove_duplicates([2,2,2,1,3,3]) => [3,1,2]
+
+ Returns a copy of a list without duplicates. Every list
+ item must be hashable and the order of the items in the
+ resulting list is not defined.
+ """
+ u = {}
+ for x in lst:
+ u[x] = 1
+
+ return u.keys()
+
+class SimpleXMLRPCDispatcher:
+ """Mix-in class that dispatches XML-RPC requests.
+
+ This class is used to register XML-RPC method handlers
+ and then to dispatch them. There should never be any
+ reason to instantiate this class directly.
+ """
+
+ def __init__(self, allow_none, encoding):
+ self.funcs = {}
+ self.instance = None
+ self.allow_none = allow_none
+ self.encoding = encoding
+
+ def register_instance(self, instance, allow_dotted_names=False):
+ """Registers an instance to respond to XML-RPC requests.
+
+ Only one instance can be installed at a time.
+
+ If the registered instance has a _dispatch method then that
+ method will be called with the name of the XML-RPC method and
+ its parameters as a tuple
+ e.g. instance._dispatch('add',(2,3))
+
+ If the registered instance does not have a _dispatch method
+ then the instance will be searched to find a matching method
+ and, if found, will be called. Methods beginning with an '_'
+ are considered private and will not be called by
+ SimpleXMLRPCServer.
+
+ If a registered function matches a XML-RPC request, then it
+ will be called instead of the registered instance.
+
+ If the optional allow_dotted_names argument is true and the
+ instance does not have a _dispatch method, method names
+ containing dots are supported and resolved, as long as none of
+ the name segments start with an '_'.
+
+ *** SECURITY WARNING: ***
+
+ Enabling the allow_dotted_names options allows intruders
+ to access your module's global variables and may allow
+ intruders to execute arbitrary code on your machine. Only
+ use this option on a secure, closed network.
+
+ """
+
+ self.instance = instance
+ self.allow_dotted_names = allow_dotted_names
+
+ def register_function(self, function, name=None):
+ """Registers a function to respond to XML-RPC requests.
+
+ The optional name argument can be used to set a Unicode name
+ for the function.
+ """
+
+ if name is None:
+ name = function.__name__
+ self.funcs[name] = function
+
+ def register_introspection_functions(self):
+ """Registers the XML-RPC introspection methods in the system
+ namespace.
+
+ see http://xmlrpc.usefulinc.com/doc/reserved.html
+ """
+
+ self.funcs.update({'system.listMethods' : self.system_listMethods,
+ 'system.methodSignature' : self.system_methodSignature,
+ 'system.methodHelp' : self.system_methodHelp})
+
+ def register_multicall_functions(self):
+ """Registers the XML-RPC multicall method in the system
+ namespace.
+
+ see http://www.xmlrpc.com/discuss/msgReader$1208"""
+
+ self.funcs.update({'system.multicall' : self.system_multicall})
+
+ def _marshaled_dispatch(self, data, dispatch_method=None):
+ """Dispatches an XML-RPC method from marshalled (XML) data.
+
+ XML-RPC methods are dispatched from the marshalled (XML) data
+ using the _dispatch method and the result is returned as
+ marshalled data. For backwards compatibility, a dispatch
+ function can be provided as an argument (see comment in
+ SimpleXMLRPCRequestHandler.do_POST) but overriding the
+ existing method through subclassing is the prefered means
+ of changing method dispatch behavior.
+ """
+ try:
+ params, method = xmlrpclib.loads(data)
+
+ # generate response
+ if dispatch_method is not None:
+ response = dispatch_method(method, params)
+ else:
+ response = self._dispatch(method, params)
+ # wrap response in a singleton tuple
+ response = (response,)
+ response = xmlrpclib.dumps(response, methodresponse=1,
+ allow_none=self.allow_none, encoding=self.encoding)
+ except Fault, fault:
+ response = xmlrpclib.dumps(fault, allow_none=self.allow_none,
+ encoding=self.encoding)
+ except:
+ # report exception back to server
+ response = xmlrpclib.dumps(
+ xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value)), #@UndefinedVariable exc_value only available when we actually have an exception
+ encoding=self.encoding, allow_none=self.allow_none,
+ )
+
+ return response
+
+ def system_listMethods(self):
+ """system.listMethods() => ['add', 'subtract', 'multiple']
+
+ Returns a list of the methods supported by the server."""
+
+ methods = self.funcs.keys()
+ if self.instance is not None:
+ # Instance can implement _listMethod to return a list of
+ # methods
+ if hasattr(self.instance, '_listMethods'):
+ methods = remove_duplicates(
+ methods + self.instance._listMethods()
+ )
+ # if the instance has a _dispatch method then we
+ # don't have enough information to provide a list
+ # of methods
+ elif not hasattr(self.instance, '_dispatch'):
+ methods = remove_duplicates(
+ methods + list_public_methods(self.instance)
+ )
+ methods.sort()
+ return methods
+
+ def system_methodSignature(self, method_name):
+ """system.methodSignature('add') => [double, int, int]
+
+ Returns a list describing the signature of the method. In the
+ above example, the add method takes two integers as arguments
+ and returns a double result.
+
+ This server does NOT support system.methodSignature."""
+
+ # See http://xmlrpc.usefulinc.com/doc/sysmethodsig.html
+
+ return 'signatures not supported'
+
+ def system_methodHelp(self, method_name):
+ """system.methodHelp('add') => "Adds two integers together"
+
+ Returns a string containing documentation for the specified method."""
+
+ method = None
+ if self.funcs.has_key(method_name):
+ method = self.funcs[method_name]
+ elif self.instance is not None:
+ # Instance can implement _methodHelp to return help for a method
+ if hasattr(self.instance, '_methodHelp'):
+ return self.instance._methodHelp(method_name)
+ # if the instance has a _dispatch method then we
+ # don't have enough information to provide help
+ elif not hasattr(self.instance, '_dispatch'):
+ try:
+ method = resolve_dotted_attribute(
+ self.instance,
+ method_name,
+ self.allow_dotted_names
+ )
+ except AttributeError:
+ pass
+
+ # Note that we aren't checking that the method actually
+ # be a callable object of some kind
+ if method is None:
+ return ""
+ else:
+ try:
+ import pydoc
+ except ImportError:
+ return "" #not there for jython
+ else:
+ return pydoc.getdoc(method)
+
+ def system_multicall(self, call_list):
+ """system.multicall([{'methodName': 'add', 'params': [2, 2]}, ...]) => \
+[[4], ...]
+
+ Allows the caller to package multiple XML-RPC calls into a single
+ request.
+
+ See http://www.xmlrpc.com/discuss/msgReader$1208
+ """
+
+ results = []
+ for call in call_list:
+ method_name = call['methodName']
+ params = call['params']
+
+ try:
+ # 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:
+ results.append(
+ {'faultCode' : fault.faultCode,
+ 'faultString' : fault.faultString}
+ )
+ except:
+ results.append(
+ {'faultCode' : 1,
+ 'faultString' : "%s:%s" % (sys.exc_type, sys.exc_value)} #@UndefinedVariable exc_value only available when we actually have an exception
+ )
+ return results
+
+ def _dispatch(self, method, params):
+ """Dispatches the XML-RPC method.
+
+ XML-RPC calls are forwarded to a registered function that
+ matches the called XML-RPC method name. If no such function
+ exists then the call is forwarded to the registered instance,
+ if available.
+
+ If the registered instance has a _dispatch method then that
+ method will be called with the name of the XML-RPC method and
+ its parameters as a tuple
+ e.g. instance._dispatch('add',(2,3))
+
+ If the registered instance does not have a _dispatch method
+ then the instance will be searched to find a matching method
+ and, if found, will be called.
+
+ Methods beginning with an '_' are considered private and will
+ not be called.
+ """
+
+ func = None
+ try:
+ # check to see if a matching function has been registered
+ func = self.funcs[method]
+ except KeyError:
+ if self.instance is not None:
+ # check for a _dispatch method
+ if hasattr(self.instance, '_dispatch'):
+ return self.instance._dispatch(method, params)
+ else:
+ # call instance method directly
+ try:
+ func = resolve_dotted_attribute(
+ self.instance,
+ method,
+ self.allow_dotted_names
+ )
+ except AttributeError:
+ pass
+
+ if func is not None:
+ return func(*params)
+ else:
+ raise Exception('method "%s" is not supported' % method)
+
+class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+ """Simple XML-RPC request handler class.
+
+ Handles all HTTP POST requests and attempts to decode them as
+ XML-RPC requests.
+ """
+
+ # Class attribute listing the accessible path components;
+ # paths not on this list will result in a 404 error.
+ rpc_paths = ('/', '/RPC2')
+
+ def is_rpc_path_valid(self):
+ if self.rpc_paths:
+ return self.path in self.rpc_paths
+ else:
+ # If .rpc_paths is empty, just assume all paths are legal
+ return True
+
+ def do_POST(self):
+ """Handles the HTTP POST request.
+
+ Attempts to interpret all HTTP POST requests as XML-RPC calls,
+ which are forwarded to the server's _dispatch method for handling.
+ """
+
+ # Check that the path is legal
+ if not self.is_rpc_path_valid():
+ self.report_404()
+ return
+
+ try:
+ # Get arguments by reading body of request.
+ # We read this in chunks to avoid straining
+ # socket.read(); around the 10 or 15Mb mark, some platforms
+ # begin to have problems (bug #792570).
+ max_chunk_size = 10 * 1024 * 1024
+ size_remaining = int(self.headers["content-length"])
+ L = []
+ while size_remaining:
+ chunk_size = min(size_remaining, max_chunk_size)
+ L.append(self.rfile.read(chunk_size))
+ size_remaining -= len(L[-1])
+ data = ''.join(L)
+
+ # In previous versions of SimpleXMLRPCServer, _dispatch
+ # could be overridden in this class, instead of in
+ # SimpleXMLRPCDispatcher. To maintain backwards compatibility,
+ # check to see if a subclass implements _dispatch and dispatch
+ # using that method if present.
+ response = self.server._marshaled_dispatch(
+ data, getattr(self, '_dispatch', None)
+ )
+ except: # This should only happen if the module is buggy
+ # internal error, report as HTTP server error
+ self.send_response(500)
+ self.end_headers()
+ else:
+ # got a valid XML RPC response
+ self.send_response(200)
+ self.send_header("Content-type", "text/xml")
+ self.send_header("Content-length", str(len(response)))
+ self.end_headers()
+ self.wfile.write(response)
+
+ # shut down the connection
+ self.wfile.flush()
+ self.connection.shutdown(1)
+
+ def report_404 (self):
+ # Report a 404 error
+ self.send_response(404)
+ response = 'No such page'
+ self.send_header("Content-type", "text/plain")
+ self.send_header("Content-length", str(len(response)))
+ self.end_headers()
+ self.wfile.write(response)
+ # shut down the connection
+ self.wfile.flush()
+ self.connection.shutdown(1)
+
+ def log_request(self, code='-', size='-'):
+ """Selectively log an accepted request."""
+
+ if self.server.logRequests:
+ BaseHTTPServer.BaseHTTPRequestHandler.log_request(self, code, size)
+
+class SimpleXMLRPCServer(SocketServer.TCPServer,
+ SimpleXMLRPCDispatcher):
+ """Simple XML-RPC server.
+
+ Simple XML-RPC server that allows functions and a single instance
+ to be installed to handle requests. The default implementation
+ attempts to dispatch XML-RPC calls to the functions or instance
+ installed in the server. Override the _dispatch method inhereted
+ from SimpleXMLRPCDispatcher to change this behavior.
+ """
+
+ allow_reuse_address = True
+
+ def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler,
+ logRequests=True, allow_none=False, encoding=None):
+ self.logRequests = logRequests
+
+ SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)
+ SocketServer.TCPServer.__init__(self, addr, requestHandler)
+
+ # [Bug #1222790] If possible, set close-on-exec flag; if a
+ # method spawns a subprocess, the subprocess shouldn't have
+ # the listening socket open.
+ if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'):
+ flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD)
+ flags |= fcntl.FD_CLOEXEC
+ fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags)
+
+class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher):
+ """Simple handler for XML-RPC data passed through CGI."""
+
+ def __init__(self, allow_none=False, encoding=None):
+ SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)
+
+ def handle_xmlrpc(self, request_text):
+ """Handle a single XML-RPC request"""
+
+ response = self._marshaled_dispatch(request_text)
+
+ sys.stdout.write('Content-Type: text/xml\n')
+ sys.stdout.write('Content-Length: %d\n' % len(response))
+ sys.stdout.write('\n')
+
+ sys.stdout.write(response)
+
+ def handle_get(self):
+ """Handle a single HTTP GET request.
+
+ Default implementation indicates an error because
+ XML-RPC uses the POST method.
+ """
+
+ code = 400
+ message, explain = \
+ BaseHTTPServer.BaseHTTPRequestHandler.responses[code]
+
+ response = BaseHTTPServer.DEFAULT_ERROR_MESSAGE % { #@UndefinedVariable
+ 'code' : code,
+ 'message' : message,
+ 'explain' : explain
+ }
+ sys.stdout.write('Status: %d %s\n' % (code, message))
+ sys.stdout.write('Content-Type: text/html\n')
+ sys.stdout.write('Content-Length: %d\n' % len(response))
+ sys.stdout.write('\n')
+
+ sys.stdout.write(response)
+
+ def handle_request(self, request_text=None):
+ """Handle a single XML-RPC request passed through a CGI post method.
+
+ If no XML data is given then it is read from stdin. The resulting
+ XML-RPC response is printed to stdout along with the correct HTTP
+ headers.
+ """
+
+ if request_text is None and \
+ os.environ.get('REQUEST_METHOD', None) == 'GET':
+ self.handle_get()
+ else:
+ # POST data is normally available through stdin
+ if request_text is None:
+ request_text = sys.stdin.read()
+
+ self.handle_xmlrpc(request_text)
+
+if __name__ == '__main__':
+ sys.stdout.write('Running XML-RPC server on port 8000\n')
+ server = SimpleXMLRPCServer(("localhost", 8000))
+ server.register_function(pow)
+ server.register_function(lambda x, y: x + y, 'add')
+ server.serve_forever()
View
193 RemoteDebug/pysrc/_pydev_completer.py
@@ -0,0 +1,193 @@
+
+try:
+ import __builtin__
+except ImportError:
+ import builtins as __builtin__
+
+try:
+ False
+ True
+except NameError: # version < 2.3 -- didn't have the True/False builtins
+ setattr(__builtin__, 'True', 1)
+ setattr(__builtin__, 'False', 0)
+
+try:
+ import java.lang #@UnusedImport
+ import _pydev_jy_imports_tipper #as _pydev_imports_tipper #changed to be backward compatible with 1.5
+ _pydev_imports_tipper = _pydev_jy_imports_tipper
+except ImportError:
+ IS_JYTHON = False
+ import _pydev_imports_tipper
+
+import pydevd_vars
+dir2 = _pydev_imports_tipper.GenerateImportsTipForModule
+
+
+#=======================================================================================================================
+# _StartsWithFilter
+#=======================================================================================================================
+class _StartsWithFilter:
+ '''
+ Used because we can't create a lambda that'll use an outer scope in jython 2.1
+ '''
+
+
+ def __init__(self, start_with):
+ self.start_with = start_with.lower()
+
+ def __call__(self, name):
+ return name.lower().startswith(self.start_with)
+
+#=======================================================================================================================
+# Completer
+#
+# This class was gotten from IPython.completer (dir2 was replaced with the completer already in pydev)
+#=======================================================================================================================
+class Completer:
+
+ def __init__(self, namespace=None, global_namespace=None):
+ """Create a new completer for the command line.
+
+ Completer([namespace,global_namespace]) -> completer instance.
+
+ If unspecified, the default namespace where completions are performed
+ is __main__ (technically, __main__.__dict__). Namespaces should be
+ given as dictionaries.
+
+ An optional second namespace can be given. This allows the completer
+ to handle cases where both the local and global scopes need to be
+ distinguished.
+
+ Completer instances should be used as the completion mechanism of
+ readline via the set_completer() call:
+
+ readline.set_completer(Completer(my_namespace).complete)
+ """
+
+ # Don't bind to namespace quite yet, but flag whether the user wants a
+ # specific namespace or to use __main__.__dict__. This will allow us
+ # to bind to __main__.__dict__ at completion time, not now.
+ if namespace is None:
+ self.use_main_ns = 1
+ else:
+ self.use_main_ns = 0
+ self.namespace = namespace
+
+ # The global namespace, if given, can be bound directly
+ if global_namespace is None:
+ self.global_namespace = {}
+ else:
+ self.global_namespace = global_namespace
+
+ def complete(self, text):
+ """Return the next possible completion for 'text'.
+
+ This is called successively with state == 0, 1, 2, ... until it
+ returns None. The completion should begin with 'text'.
+
+ """
+ if self.use_main_ns:
+ #In pydev this option should never be used
+ raise RuntimeError('Namespace must be provided!')
+ self.namespace = __main__.__dict__ #@UndefinedVariable
+
+ if "." in text:
+ return self.attr_matches(text)
+ else:
+ return self.global_matches(text)
+
+ def global_matches(self, text):
+ """Compute matches when text is a simple name.
+
+ Return a list of all keywords, built-in functions and names currently
+ defined in self.namespace or self.global_namespace that match.
+
+ """
+
+
+ def get_item(obj, attr):
+ return obj[attr]
+
+ a = {}
+
+ for dict_with_comps in [__builtin__.__dict__, self.namespace, self.global_namespace]: #@UndefinedVariable
+ a.update(dict_with_comps)
+
+ filter = _StartsWithFilter(text)
+
+ return dir2(a, a.keys(), get_item, filter)
+
+ def attr_matches(self, text):
+ """Compute matches when text contains a dot.
+
+ Assuming the text is of the form NAME.NAME....[NAME], and is
+ evaluatable in self.namespace or self.global_namespace, it will be
+ evaluated and its attributes (as revealed by dir()) are used as
+ possible completions. (For class instances, class members are are
+ also considered.)
+
+ WARNING: this can still invoke arbitrary C code, if an object
+ with a __getattr__ hook is evaluated.
+
+ """
+ import re
+
+ # Another option, seems to work great. Catches things like ''.<tab>
+ m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text) #@UndefinedVariable
+
+ if not m:
+ return []
+
+ expr, attr = m.group(1, 3)
+ try:
+ obj = eval(expr, self.namespace)
+ except:
+ try:
+ obj = eval(expr, self.global_namespace)
+ except:
+ return []
+
+ filter = _StartsWithFilter(attr)
+
+ words = dir2(obj, filter=filter)
+
+ return words
+
+
+#=======================================================================================================================
+# GenerateCompletionsAsXML
+#=======================================================================================================================
+def GenerateCompletionsAsXML(frame, act_tok):
+ if frame is None:
+ return '<xml></xml>'
+
+ #Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329
+ #(Names not resolved in generator expression in method)
+ #See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html
+ updated_globals = {}
+ updated_globals.update(frame.f_globals)
+ updated_globals.update(frame.f_locals) #locals later because it has precedence over the actual globals
+
+ completer = Completer(updated_globals, None)
+ #list(tuple(name, descr, parameters, type))
+ completions = completer.complete(act_tok)
+
+ valid_xml = pydevd_vars.makeValidXmlValue
+ quote = pydevd_vars.quote
+
+ msg = ["<xml>"]
+
+ for comp in completions:
+ msg.append('<comp p0="')
+ msg.append(valid_xml(quote(comp[0], '/>_= \t')))
+ msg.append('" p1="')
+ msg.append(valid_xml(quote(comp[1], '/>_= \t')))
+ msg.append('" p2="')
+ msg.append(valid_xml(quote(comp[2], '/>_= \t')))
+ msg.append('" p3="')
+ msg.append(valid_xml(quote(comp[3], '/>_= \t')))
+ msg.append('"/>')
+ msg.append("</xml>")
+
+ return ''.join(msg)
+
View
38 RemoteDebug/pysrc/_pydev_execfile.py
@@ -0,0 +1,38 @@
+#We must redefine it in Py3k if it's not already there
+def execfile(file, glob=None, loc=None):
+ if glob is None:
+ import sys
+ glob = sys._getframe().f_back.f_globals
+ if loc is None:
+ loc = glob
+ stream = open(file, 'rb')
+ try:
+ encoding = None
+ #Get encoding!
+ for _i in range(2):
+ line = stream.readline() #Should not raise an exception even if there are no more contents
+ #Must be a comment line
+ if line.strip().startswith(b'#'):
+ #Don't import re if there's no chance that there's an encoding in the line
+ if b'coding' in line:
+ import re
+ p = re.search(br"coding[:=]\s*([-\w.]+)", line)
+ if p:
+ try:
+ encoding = p.group(1).decode('ascii')
+ break
+ except:
+ encoding = None
+ finally:
+ stream.close()
+
+ if encoding:
+ stream = open(file, encoding=encoding)
+ else:
+ stream = open(file)
+ try:
+ contents = stream.read()
+ finally:
+ stream.close()
+
+ exec(compile(contents+"\n", file, 'exec'), glob, loc) #execute the script
View
130 RemoteDebug/pysrc/_pydev_getopt.py
@@ -0,0 +1,130 @@
+
+#=======================================================================================================================
+# getopt code copied since gnu_getopt is not available on jython 2.1
+#=======================================================================================================================
+class GetoptError(Exception):
+ opt = ''
+ msg = ''
+ def __init__(self, msg, opt=''):
+ self.msg = msg
+ self.opt = opt
+ Exception.__init__(self, msg, opt)
+
+ def __str__(self):
+ return self.msg
+
+
+def gnu_getopt(args, shortopts, longopts=[]):
+ """getopt(args, options[, long_options]) -> opts, args
+
+ This function works like getopt(), except that GNU style scanning
+ mode is used by default. This means that option and non-option
+ arguments may be intermixed. The getopt() function stops
+ processing options as soon as a non-option argument is
+ encountered.
+
+ If the first character of the option string is `+', or if the
+ environment variable POSIXLY_CORRECT is set, then option
+ processing stops as soon as a non-option argument is encountered.
+ """
+
+ opts = []
+ prog_args = []
+ if type('') == type(longopts):
+ longopts = [longopts]
+ else:
+ longopts = list(longopts)
+
+ # Allow options after non-option arguments?
+ all_options_first = False
+ if shortopts.startswith('+'):
+ shortopts = shortopts[1:]
+ all_options_first = True
+
+ while args:
+ if args[0] == '--':
+ prog_args += args[1:]
+ break
+
+ if args[0][:2] == '--':
+ opts, args = do_longs(opts, args[0][2:], longopts, args[1:])
+ elif args[0][:1] == '-':
+ opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:])
+ else:
+ if all_options_first:
+ prog_args += args
+ break
+ else:
+ prog_args.append(args[0])
+ args = args[1:]
+
+ return opts, prog_args
+
+def do_longs(opts, opt, longopts, args):
+ try:
+ i = opt.index('=')
+ except ValueError:
+ optarg = None
+ else:
+ opt, optarg = opt[:i], opt[i + 1:]
+
+ has_arg, opt = long_has_args(opt, longopts)
+ if has_arg:
+ if optarg is None:
+ if not args:
+ raise GetoptError('option --%s requires argument' % opt, opt)
+ optarg, args = args[0], args[1:]
+ elif optarg:
+ raise GetoptError('option --%s must not have an argument' % opt, opt)
+ opts.append(('--' + opt, optarg or ''))
+ return opts, args
+
+# Return:
+# has_arg?
+# full option name
+def long_has_args(opt, longopts):
+ possibilities = [o for o in longopts if o.startswith(opt)]
+ if not possibilities:
+ raise GetoptError('option --%s not recognized' % opt, opt)
+ # Is there an exact match?
+ if opt in possibilities:
+ return False, opt
+ elif opt + '=' in possibilities:
+ return True, opt
+ # No exact match, so better be unique.
+ if len(possibilities) > 1:
+ # XXX since possibilities contains all valid continuations, might be
+ # nice to work them into the error msg
+ raise GetoptError('option --%s not a unique prefix' % opt, opt)
+ assert len(possibilities) == 1
+ unique_match = possibilities[0]
+ has_arg = unique_match.endswith('=')
+ if has_arg:
+ unique_match = unique_match[:-1]
+ return has_arg, unique_match
+
+def do_shorts(opts, optstring, shortopts, args):
+ while optstring != '':
+ opt, optstring = optstring[0], optstring[1:]
+ if short_has_arg(opt, shortopts):
+ if optstring == '':
+ if not args:
+ raise GetoptError('option -%s requires argument' % opt,
+ opt)
+ optstring, args = args[0], args[1:]
+ optarg, optstring = optstring, ''
+ else:
+ optarg = ''
+ opts.append(('-' + opt, optarg))
+ return opts, args
+
+def short_has_arg(opt, shortopts):
+ for i in range(len(shortopts)):
+ if opt == shortopts[i] != ':':
+ return shortopts.startswith(':', i + 1)
+ raise GetoptError('option -%s not recognized' % opt, opt)
+
+
+#=======================================================================================================================
+# End getopt code
+#=======================================================================================================================
View
347 RemoteDebug/pysrc/_pydev_imports_tipper.py
@@ -0,0 +1,347 @@
+import os.path
+import inspect
+import sys
+from _pydev_tipper_common import DoFind
+
+#completion types.
+TYPE_IMPORT = '0'
+TYPE_CLASS = '1'
+TYPE_FUNCTION = '2'
+TYPE_ATTR = '3'
+TYPE_BUILTIN = '4'
+TYPE_PARAM = '5'
+
+def _imp(name, log=None):
+ try:
+ return __import__(name)
+ except:
+ if '.' in name:
+ sub = name[0:name.rfind('.')]
+
+ if log is not None:
+ log.AddContent('Unable to import', name, 'trying with', sub)
+ #log.AddContent('PYTHONPATH:')
+ #log.AddContent('\n'.join(sorted(sys.path)))
+ log.AddException()
+
+ return _imp(sub, log)
+ else:
+ s = 'Unable to import module: %s - sys.path: %s' % (str(name), sys.path)
+ if log is not None:
+ log.AddContent(s)
+ log.AddException()
+
+ raise ImportError(s)
+
+
+IS_IPY = False
+if sys.platform == 'cli':
+ IS_IPY = True
+ _old_imp = _imp
+ def _imp(name, log=None):
+ #We must add a reference in clr for .Net
+ import clr #@UnresolvedImport
+ initial_name = name
+ while '.' in name:
+ try:
+ clr.AddReference(name)
+ break #If it worked, that's OK.
+ except:
+ name = name[0:name.rfind('.')]
+ else:
+ try:
+ clr.AddReference(name)
+ except:
+ pass #That's OK (not dot net module).
+
+ return _old_imp(initial_name, log)
+
+
+
+def GetFile(mod):
+ f = None
+ try:
+ f = inspect.getsourcefile(mod) or inspect.getfile(mod)
+ except:
+ if hasattr(mod, '__file__'):
+ f = mod.__file__
+ if f.lower(f[-4:]) in ['.pyc', '.pyo']:
+ filename = f[:-4] + '.py'
+ if os.path.exists(filename):
+ f = filename
+
+ return f
+
+def Find(name, log=None):
+ f = None
+
+ mod = _imp(name, log)
+ parent = mod
+ foundAs = ''
+
+ if inspect.ismodule(mod):
+ f = GetFile(mod)
+
+ components = name.split('.')
+
+ old_comp = None
+ for comp in components[1:]:
+ try:
+ #this happens in the following case:
+ #we have mx.DateTime.mxDateTime.mxDateTime.pyd
+ #but after importing it, mx.DateTime.mxDateTime shadows access to mxDateTime.pyd
+ mod = getattr(mod, comp)
+ except AttributeError:
+ if old_comp != comp:
+ raise
+
+ if inspect.ismodule(mod):
+ f = GetFile(mod)
+ else:
+ if len(foundAs) > 0:
+ foundAs = foundAs + '.'
+ foundAs = foundAs + comp
+
+ old_comp = comp
+
+ return f, mod, parent, foundAs
+
+def Search(data):
+ '''@return file, line, col
+ '''
+
+ data = data.replace('\n', '')
+ if data.endswith('.'):
+ data = data.rstrip('.')
+ f, mod, parent, foundAs = Find(data)
+ try:
+ return DoFind(f, mod), foundAs
+ except:
+ return DoFind(f, parent), foundAs
+
+
+def GenerateTip(data, log=None):
+ data = data.replace('\n', '')
+ if data.endswith('.'):
+ data = data.rstrip('.')
+
+ f, mod, parent, foundAs = Find(data, log)
+ #print_ >> open('temp.txt', 'w'), f
+ tips = GenerateImportsTipForModule(mod)
+ return f, tips
+
+
+def CheckChar(c):
+ if c == '-' or c == '.':
+ return '_'
+ return c
+
+def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr, filter=lambda name:True):
+ '''
+ @param obj_to_complete: the object from where we should get the completions
+ @param dirComps: if passed, we should not 'dir' the object and should just iterate those passed as a parameter
+ @param getattr: the way to get a given object from the obj_to_complete (used for the completer)
+ @param filter: a callable that receives the name and decides if it should be appended or not to the results
+ @return: list of tuples, so that each tuple represents a completion with:
+ name, doc, args, type (from the TYPE_* constants)
+ '''
+ ret = []
+
+ if dirComps is None:
+ dirComps = dir(obj_to_complete)
+ if hasattr(obj_to_complete, '__dict__'):
+ dirComps.append('__dict__')
+ if hasattr(obj_to_complete, '__class__'):
+ dirComps.append('__class__')
+
+ getCompleteInfo = True
+
+ if len(dirComps) > 1000:
+ #ok, we don't want to let our users wait forever...
+ #no complete info for you...
+
+ getCompleteInfo = False
+
+ dontGetDocsOn = (float, int, str, tuple, list)
+ for d in dirComps:
+
+ if d is None:
+ continue
+
+ if not filter(d):
+ continue
+
+ args = ''
+
+ try:
+ obj = getattr(obj_to_complete, d)
+ except: #just ignore and get it without aditional info
+ ret.append((d, '', args, TYPE_BUILTIN))
+ else:
+
+ if getCompleteInfo:
+ try:
+ retType = TYPE_BUILTIN
+
+ #check if we have to get docs
+ getDoc = True
+ for class_ in dontGetDocsOn:
+
+ if isinstance(obj, class_):
+ getDoc = False
+ break
+
+ doc = ''
+ if getDoc:
+ #no need to get this info... too many constants are defined and
+ #makes things much slower (passing all that through sockets takes quite some time)
+ try:
+ doc = inspect.getdoc(obj)
+ if doc is None:
+ doc = ''
+ except: #may happen on jython when checking java classes (so, just ignore it)
+ doc = ''
+
+
+ if inspect.ismethod(obj) or inspect.isbuiltin(obj) or inspect.isfunction(obj) or inspect.isroutine(obj):
+ try:
+ args, vargs, kwargs, defaults = inspect.getargspec(obj)
+
+ r = ''
+ for a in (args):
+ if len(r) > 0:
+ r = r + ', '
+ r = r + str(a)
+ args = '(%s)' % (r)
+ except TypeError:
+ #ok, let's see if we can get the arguments from the doc
+ args = '()'
+ try:
+ found = False
+ if len(doc) > 0:
+ if IS_IPY:
+ #Handle case where we have the situation below
+ #sort(self, object cmp, object key)
+ #sort(self, object cmp, object key, bool reverse)
+ #sort(self)
+ #sort(self, object cmp)
+
+ #Or: sort(self: list, cmp: object, key: object)
+ #sort(self: list, cmp: object, key: object, reverse: bool)
+ #sort(self: list)
+ #sort(self: list, cmp: object)
+ if hasattr(obj, '__name__'):
+ name = obj.__name__+'('
+
+
+ #Fix issue where it was appearing sort(aa)sort(bb)sort(cc) in the same line.
+ lines = doc.splitlines()
+ if len(lines) == 1:
+ c = doc.count(name)
+ if c > 1:
+ doc = ('\n'+name).join(doc.split(name))
+
+
+ major = ''
+ for line in doc.splitlines():
+ if line.startswith(name) and line.endswith(')'):
+ if len(line) > len(major):
+ major = line
+ if major:
+ args = major[major.index('('):]
+ found = True
+
+
+ if not found:
+ i = doc.find('->')
+ if i < 0:
+ i = doc.find('--')
+ if i < 0:
+ i = doc.find('\n')
+ if i < 0:
+ i = doc.find('\r')
+
+
+ if i > 0:
+ s = doc[0:i]
+ s = s.strip()
+
+ #let's see if we have a docstring in the first line
+ if s[-1] == ')':
+ start = s.find('(')
+ if start >= 0:
+ end = s.find('[')
+ if end <= 0:
+ end = s.find(')')
+ if end <= 0:
+ end = len(s)
+
+ args = s[start:end]
+ if not args[-1] == ')':
+ args = args + ')'
+
+
+ #now, get rid of unwanted chars
+ l = len(args) - 1
+ r = []
+ for i in range(len(args)):
+ if i == 0 or i == l:
+ r.append(args[i])
+ else:
+ r.append(CheckChar(args[i]))
+
+ args = ''.join(r)
+
+ if IS_IPY:
+ if args.startswith('(self:'):
+ i = args.find(',')
+ if i >= 0:
+ args = '(self'+args[i:]
+ else:
+ args = '(self)'
+ i = args.find(')')
+ if i > 0:
+ args = args[:i+1]
+
+ except:
+ pass
+
+ retType = TYPE_FUNCTION
+
+ elif inspect.isclass(obj):
+ retType = TYPE_CLASS
+
+ elif inspect.ismodule(obj):
+ retType = TYPE_IMPORT
+
+ else:
+ retType = TYPE_ATTR
+
+
+ #add token and doc to return - assure only strings.
+ ret.append((d, doc, args, retType))
+
+ except: #just ignore and get it without aditional info
+ ret.append((d, '', args, TYPE_BUILTIN))
+
+ else: #getCompleteInfo == False
+ if inspect.ismethod(obj) or inspect.isbuiltin(obj) or inspect.isfunction(obj) or inspect.isroutine(obj):
+ retType = TYPE_FUNCTION
+
+ elif inspect.isclass(obj):
+ retType = TYPE_CLASS
+
+ elif inspect.ismodule(obj):
+ retType = TYPE_IMPORT
+
+ else:
+ retType = TYPE_ATTR
+ #ok, no complete info, let's try to do this as fast and clean as possible
+ #so, no docs for this kind of information, only the signatures
+ ret.append((d, '', str(args), retType))
+
+ return ret
+
+
+
+
View
788 RemoteDebug/pysrc/_pydev_inspect.py
@@ -0,0 +1,788 @@
+"""Get useful information from live Python objects.
+
+This module encapsulates the interface provided by the internal special
+attributes (func_*, co_*, im_*, tb_*, etc.) in a friendlier fashion.
+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
+ getmembers() - get members of an object that satisfy a given condition
+
+ getfile(), getsourcefile(), getsource() - find an object's source code
+ getdoc(), getcomments() - get documentation on an object
+ 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
+ formatargspec(), formatargvalues() - format an argument spec
+ getouterframes(), getinnerframes() - get info about frames
+ currentframe() - get the current stack frame
+ stack(), trace() - get info about frames on the stack or in a traceback
+"""
+
+# This module is in the public domain. No warranties.
+
+__author__ = 'Ka-Ping Yee <ping@lfw.org>'
+__date__ = '1 Jan 2001'
+
+import sys, os, types, string, re, imp, tokenize
+
+# ----------------------------------------------------------- type-checking
+def ismodule(object):
+ """Return true if the object is a module.
+
+ Module objects provide these attributes:
+ __doc__ documentation string
+ __file__ filename (missing for built-in modules)"""
+ return isinstance(object, types.ModuleType)
+
+def isclass(object):
+ """Return true if the object is a class.
+
+ 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__')
+
+def ismethod(object):
+ """Return true if the object is an instance method.
+
+ Instance method objects provide these attributes:
+ __doc__ documentation string
+ __name__ name with which this method was defined
+ im_class class object in which this method belongs
+ im_func function object containing implementation of method
+ im_self instance to which this method is bound, or None"""
+ return isinstance(object, types.MethodType)
+
+def ismethoddescriptor(object):
+ """Return true if the object is a method descriptor.
+
+ But not if ismethod() or isclass() or isfunction() are true.
+
+ This is new in Python 2.2, and, for example, is true of int.__add__.
+ An object passing this test has a __get__ attribute but not a __set__
+ attribute, but beyond that the set of attributes varies. __name__ is
+ usually sensible, and __doc__ often is.
+
+ Methods implemented via descriptors that also pass one of the other
+ tests return false from the ismethoddescriptor() test, simply because
+ the other tests promise more -- you can, e.g., count on having the
+ im_func attribute (etc) when an object passes ismethod()."""
+ return (hasattr(object, "__get__")
+ and not hasattr(object, "__set__") # else it's a data descriptor
+ and not ismethod(object) # mutual exclusion
+ and not isfunction(object)
+ and not isclass(object))
+
+def isfunction(object):
+ """Return true if the object is a user-defined function.
+
+ Function objects provide these attributes:
+ __doc__ documentation string
+ __name__ name with which this function was defined
+ func_code code object containing compiled function bytecode
+ func_defaults tuple of any default values for arguments
+ func_doc (same as __doc__)
+ func_globals global namespace in which this function was defined
+ func_name (same as __name__)"""
+ return isinstance(object, types.FunctionType)
+
+def istraceback(object):
+ """Return true if the object is a traceback.
+
+ Traceback objects provide these attributes:
+ tb_frame frame object at this level
+ tb_lasti index of last attempted instruction in bytecode
+ tb_lineno current line number in Python source code
+ tb_next next inner traceback object (called by this level)"""
+ return isinstance(object, types.TracebackType)
+
+def isframe(object):
+ """Return true if the object is a frame object.
+
+ Frame objects provide these attributes:
+ f_back next outer frame object (this frame's caller)
+ f_builtins built-in namespace seen by this frame
+ f_code code object being executed in this frame
+ f_exc_traceback traceback if raised in this frame, or None
+ f_exc_type exception type if raised in this frame, or None
+ f_exc_value exception value if raised in this frame, or None
+ f_globals global namespace seen by this frame
+ f_lasti index of last attempted instruction in bytecode
+ f_lineno current line number in Python source code
+ f_locals local namespace seen by this frame
+ f_restricted 0 or 1 if frame is in restricted execution mode
+ f_trace tracing function for this frame, or None"""
+ return isinstance(object, types.FrameType)
+
+def iscode(object):
+ """Return true if the object is a code object.
+
+ Code objects provide these attributes:
+ co_argcount number of arguments (not including * or ** args)
+ co_code string of raw compiled bytecode
+ co_consts tuple of constants used in the bytecode
+ co_filename name of file in which this code object was created
+ co_firstlineno number of first line in Python source code
+ co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg
+ co_lnotab encoded mapping of line numbers to bytecode indices
+ co_name name with which this code object was defined
+ co_names tuple of names of local variables
+ co_nlocals number of local variables
+ co_stacksize virtual machine stack space required
+ co_varnames tuple of names of arguments and local variables"""
+ return isinstance(object, types.CodeType)
+
+def isbuiltin(object):
+ """Return true if the object is a built-in function or method.
+
+ Built-in functions and methods provide these attributes:
+ __doc__ documentation string
+ __name__ original name of this function or method
+ __self__ instance to which a method is bound, or None"""
+ return isinstance(object, types.BuiltinFunctionType)
+
+def isroutine(object):
+ """Return true if the object is any kind of function or method."""
+ return (isbuiltin(object)
+ or isfunction(object)
+ or ismethod(object)
+ or ismethoddescriptor(object))
+
+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)
+ if not predicate or predicate(value):
+ results.append((key, value))
+ results.sort()
+ return results
+
+def classify_class_attrs(cls):
+ """Return list of attribute-descriptor tuples.
+
+ For each name in dir(cls), the return list contains a 4-tuple
+ with these elements:
+
+ 0. The name (a string).
+
+ 1. The kind of attribute this is, one of these strings:
+ 'class method' created via classmethod()
+ 'static method' created via staticmethod()
+ 'property' created via property()
+ 'method' any other flavor of method
+ 'data' not a method
+
+ 2. The class which defined this attribute (a class).
+
+ 3. The object as obtained directly from the defining class's
+ __dict__, not via getattr. This is especially important for
+ data attributes: C.data is just a data object, but
+ C.__dict__['data'] may be a data descriptor with additional
+ info, like a __doc__ string.
+ """
+
+ mro = getmro(cls)
+ names = dir(cls)
+ result = []
+ for name in names:
+ # Get the object associated with the name.
+ # 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]
+ 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)
+
+ # Classify the object.
+ if isinstance(obj, staticmethod):
+ kind = "static method"
+ elif isinstance(obj, classmethod):
+ kind = "class method"
+ elif isinstance(obj, property):
+ kind = "property"
+ elif (ismethod(obj_via_getattr) or
+ ismethoddescriptor(obj_via_getattr)):
+ kind = "method"
+ else:
+ kind = "data"
+
+ result.append((name, kind, homecls, obj))
+
+ return result
+
+# ----------------------------------------------------------- class helpers
+def _searchbases(cls, accum):
+ # Simulate the "classic class" search order.
+ if cls in accum:
+ return
+ accum.append(cls)
+ for base in cls.__bases__:
+ _searchbases(base, accum)
+
+def getmro(cls):
+ "Return tuple of base classes (including cls) in method resolution order."
+ if hasattr(cls, "__mro__"):
+ return cls.__mro__
+ else:
+ result = []
+ _searchbases(cls, result)
+ return tuple(result)
+
+# -------------------------------------------------- source code extraction
+def indentsize(line):
+ """Return the indent size, in spaces, at the start of a line of text."""
+ expline = string.expandtabs(line)
+ return len(expline) - len(string.lstrip(expline))
+
+def getdoc(object):
+ """Get the documentation string for an object.
+
+ All tabs are expanded to spaces. To clean up docstrings that are
+ indented to line up with blocks of code, any whitespace than can be
+ uniformly removed from the second line onwards is removed."""
+ try:
+ doc = object.__doc__
+ except AttributeError:
+ return None
+ if not isinstance(doc, (str, unicode)):
+ return None
+ try:
+ lines = string.split(string.expandtabs(doc), '\n')
+ except UnicodeError:
+ return None
+ else:
+ margin = None
+ 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:
+ for i in range(1, len(lines)): lines[i] = lines[i][margin:]
+ return string.join(lines, '\n')
+
+def getfile(object):
+ """Work out which source or compiled file an object was defined in."""
+ if ismodule(object):
+ if hasattr(object, '__file__'):
+ return object.__file__
+ raise TypeError, 'arg is a built-in module'
+ if isclass(object):
+ object = sys.modules.get(object.__module__)
+ if hasattr(object, '__file__'):
+ return object.__file__
+ raise TypeError, 'arg is a built-in class'
+ if ismethod(object):
+ object = object.im_func
+ if isfunction(object):
+ object = object.func_code
+ if istraceback(object):
+ object = object.tb_frame
+ if isframe(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'
+
+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.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
+
+def getmodulename(path):
+ """Return the module name for a given file, or None."""
+ info = getmoduleinfo(path)
+ if info: return info[0]
+
+def getsourcefile(object):
+ """Return the Python source file an object was defined in, if it exists."""
+ filename = getfile(object)
+ 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:
+ # Looks like a binary file. We want to only return a text file.
+ return None
+ if os.path.exists(filename):
+ return filename
+
+def getabsfile(object):
+ """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)))
+
+modulesbyfile = {}
+
+def getmodule(object):
+ """Return the module an object was defined in, or None if not found."""
+ if ismodule(object):
+ return object
+ if isclass(object):
+ return sys.modules.get(object.__module__)
+ try:
+ file = getabsfile(object)
+ 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]]
+ main = sys.modules['__main__']
+ if hasattr(main, object.__name__):
+ mainobject = getattr(main, object.__name__)
+ if mainobject is object:
+ return main
+ builtin = sys.modules['__builtin__']
+ if hasattr(builtin, object.__name__):
+ builtinobject = getattr(builtin, object.__name__)
+ if builtinobject is object:
+ return builtin
+
+def findsource(object):
+ """Return the entire source file and starting line number for an object.
+
+ The argument may be a module, class, method, function, traceback, frame,
+ 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()
+
+ if ismodule(object):
+ return lines, 0
+
+ if isclass(object):
+ name = object.__name__
+ pat = re.compile(r'^\s*class\s*' + name + r'\b')
+ for i in range(len(lines)):
+ if pat.match(lines[i]): return lines, i
+ else: raise IOError, 'could not find class definition'
+
+ if ismethod(object):
+ object = object.im_func
+ if isfunction(object):
+ object = object.func_code
+ if istraceback(object):
+ object = object.tb_frame
+ if isframe(object):
+ object = object.f_code
+ if iscode(object):
+ if not hasattr(object, 'co_firstlineno'):
+ raise IOError, 'could not find function definition'
+ lnum = object.co_firstlineno - 1
+ pat = re.compile(r'^(\s*def\s)|(.*\slambda(:|\s))')
+ while lnum > 0:
+ if pat.match(lines[lnum]): break
+ lnum = lnum - 1
+ return lines, lnum
+ 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
+
+ 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 ['', '#']:
+ start = start + 1
+ if start < len(lines) and lines[start][:1] == '#':
+ comments = []
+ end = start
+ while end < len(lines) and lines[end][:1] == '#':
+ comments.append(string.expandtabs(lines[end]))
+ end = end + 1
+ return string.join(comments, '')
+
+ # Look for a preceding block of comments at the same indentation.
+ elif lnum > 0:
+ indent = indentsize(lines[lnum])
+ end = lnum - 1
+ if end >= 0 and string.lstrip(lines[end])[:1] == '#' and \
+ indentsize(lines[end]) == indent:
+ comments = [string.lstrip(string.expandtabs(lines[end]))]
+ if end > 0:
+ end = end - 1
+ comment = string.lstrip(string.expandtabs(lines[end]))
+ while comment[:1] == '#' and indentsize(lines[end]) == indent:
+ comments[:0] = [comment]
+ end = end - 1
+ if end < 0: break
+ comment = string.lstrip(string.expandtabs(lines[end]))
+ while comments and string.strip(comments[0]) == '#':
+ comments[:1] = []
+ while comments and string.strip(comments[-1]) == '#':
+ 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
+
+ def tokeneater(self, type, token, (srow, scol), (erow, ecol), line):
+ if not self.started:
+ if type == tokenize.NAME: self.started = 1
+ elif type == tokenize.NEWLINE:
+ self.last = srow
+ elif type == tokenize.INDENT:
+ self.indent = self.indent + 1
+ 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
+
+def getblock(lines):
+ """Extract the block of code at the top of the given list of lines."""
+ 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]
+
+def getsourcelines(object):
+ """Return a list of source lines and starting line number for an object.
+
+ The argument may be a module, class, method, function, traceback, frame,
+ or code object. The source code is returned as a list of the lines
+ corresponding to the object and the line number indicates where in the
+ original source file the first line of code was found. An IOError is
+ raised if the source code cannot be retrieved."""
+ lines, lnum = findsource(object)
+
+ if ismodule(object): return lines, 0
+ else: return getblock(lines[lnum:]), lnum + 1
+
+def getsource(object):
+ """Return the text of the source code for an object.
+
+ The argument may be a module, class, method, function, traceback, frame,
+ or code object. The source code is returned as a single string. An
+ IOError is raised if the source code cannot be retrieved."""
+ lines, lnum = getsourcelines(object)
+ return string.join(lines, '')
+
+# --------------------------------------------------- class tree extraction
+def walktree(classes, children, parent):
+ """Recursive helper function for getclasstree()."""
+ results = []
+ classes.sort(lambda a, b: cmp(a.__name__, b.__name__))
+ for c in classes:
+ results.append((c, c.__bases__))
+ if children.has_key(c):
+ results.append(walktree(children[c], children, c))
+ return results
+
+def getclasstree(classes, unique=0):
+ """Arrange the given list of classes into a hierarchy of nested lists.
+
+ Where a nested list appears, it contains classes derived from the class
+ whose entry immediately precedes the list. Each entry is a 2-tuple
+ containing a class and a tuple of its base classes. If the 'unique'
+ argument is true, exactly one entry appears in the returned structure
+ for each class in the given list. Otherwise, classes using multiple
+ inheritance and their descendants will appear multiple times."""
+ children = {}
+ roots = []
+ for c in classes:
+ if c.__bases__:
+ for parent in c.__bases__:
+ if not children.has_key(parent):
+ 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():
+ 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
+
+def getargs(co):
+ """Get information about the arguments accepted by a code object.
+
+ 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'
+
+ nargs = co.co_argcount
+ names = co.co_varnames
+ args = list(names[:nargs])
+ 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])
+ remain[-1] = remain[-1] - 1
+ while remain[-1] == 0:
+ remain.pop()
+ size = count.pop()
+ stack[-size:] = [stack[-size:]]
+ if not remain: break
+ remain[-1] = remain[-1] - 1
+ if not remain: break
+ args[i] = stack[0]
+
+ varargs = None
+ if co.co_flags & CO_VARARGS:
+ varargs = co.co_varnames[nargs]
+ nargs = nargs + 1
+ varkw = None
+ if co.co_flags & CO_VARKEYWORDS:
+ varkw = co.co_varnames[nargs]
+ return args, varargs, varkw
+
+def getargspec(func):
+ """Get the names and default values of a function's arguments.
+
+ 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."""
+ if ismethod(func):
+ func = func.im_func
+ if not isfunction(func): raise TypeError, 'arg is not a Python function'
+ args, varargs, varkw = getargs(func.func_code)
+ return args, varargs, varkw, func.func_defaults
+
+def getargvalues(frame):
+ """Get information about arguments passed into a particular frame.
+
+ A tuple of four things is returned: (args, varargs, varkw, locals).
+ '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.
+ 'locals' is the locals dictionary of the given frame."""
+ args, varargs, varkw = getargs(frame.f_code)
+ return args, varargs, varkw, frame.f_locals
+
+def joinseq(seq):
+ if len(seq) == 1:
+ return '(' + seq[0] + ',)'
+ else:
+ return '(' + string.join(seq, ', ') + ')'
+
+def strseq(object, convert, join=joinseq):
+ """Recursively walk a sequence, stringifying each element."""
+ if type(object) in [types.ListType, types.TupleType]:
+ return join(map(lambda o, c=convert, j=join: strseq(o, c, j), object))
+ else:
+ return convert(object)
+
+def formatargspec(args, varargs=None, varkw=None, defaults=None,
+ formatarg=str,
+ formatvarargs=lambda name: '*' + name,
+ formatvarkw=lambda name: '**' + name,
+ formatvalue=lambda value: '=' + repr(value),
+ join=joinseq):
+ """Format an argument spec from the 4 values returned by getargspec.
+
+ The first four arguments are (args, varargs, varkw, defaults). The
+ other four arguments are the corresponding optional formatting functions
+ that are called to turn names and values into strings. The ninth
+ argument is an optional function to format the sequence of arguments."""
+ specs = []
+ if defaults:
+ firstdefault = len(args) - len(defaults)
+ for i in range(len(args)):
+ spec = strseq(args[i], formatarg, join)
+ if defaults and i >= firstdefault:
+ spec = spec + formatvalue(defaults[i - firstdefault])
+ specs.append(spec)
+ if varargs:
+ specs.append(formatvarargs(varargs))
+ if varkw:
+ specs.append(formatvarkw(varkw))
+ return '(' + string.join(specs, ', ') + ')'
+
+def formatargvalues(args, varargs, varkw, locals,
+ formatarg=str,
+ formatvarargs=lambda name: '*' + name,
+ formatvarkw=lambda name: '**' + name,
+ formatvalue=lambda value: '=' + repr(value),
+ join=joinseq):
+ """Format an argument spec from the 4 values returned by getargvalues.
+
+ The first four arguments are (args, varargs, varkw, locals). The
+ next four arguments are the corresponding optional formatting functions
+ that are called to turn names and values into strings. The ninth
+ argument is an optional function to format the sequence of arguments."""
+ def convert(name, locals=locals,
+ formatarg=formatarg, formatvalue=formatvalue):
+ return formatarg(name) + formatvalue(locals[name])
+ specs = []
+ for i in range(len(args)):
+ specs.append(strseq(args[i], convert, join))
+ if varargs:
+ specs.append(formatvarargs(varargs) + formatvalue(locals[varargs]))
+ if varkw:
+ specs.append(formatvarkw(varkw) + formatvalue(locals[varkw]))
+ return '(' + string.join(specs, ', ') + ')'
+
+# -------------------------------------------------- stack frame extraction
+def getframeinfo(frame, context=1):
+ """Get information about a frame or traceback object.
+
+ A tuple of five things is returned: the filename, the line number of
+ the current line, the function name, a list of lines of context from
+ 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)
+
+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
+
+def getouterframes(frame, context=1):
+ """Get a list of records for a frame and all higher (calling) frames.
+
+ Each record contains a frame object, filename, line number, function
+ name, a list of lines of context, and index within the context."""
+ framelist = []
+ while frame:
+ framelist.append((frame,) + getframeinfo(frame, context))
+ frame = frame.f_back
+ return framelist
+
+def getinnerframes(tb, context=1):
+ """Get a list of records for a traceback's frame and all lower frames.
+
+ Each record contains a frame object, filename, line number, function
+ name, a list of lines of context, and index within the context."""
+ framelist = []
+ while tb:
+ framelist.append((tb.tb_frame,) + getframeinfo(tb, context))
+ 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
+
+def stack(context=1):
+ """Return a list of records for the stack above the caller's frame."""
+ return getouterframes(currentframe().f_back, context)
+
+def trace(context=1):
+ """Return a list of records for the stack below the current exception."""
+ return getinnerframes(sys.exc_traceback, context) #@UndefinedVariable
View
479 RemoteDebug/pysrc/_pydev_jy_imports_tipper.py
@@ -0,0 +1,479 @@
+import StringIO
+import traceback
+from java.lang import StringBuffer #@UnresolvedImport
+from java.lang import String #@UnresolvedImport
+import java.lang #@UnresolvedImport
+import sys
+from _pydev_tipper_common import DoFind
+
+
+try:
+ False
+ True
+except NameError: # version < 2.3 -- didn't have the True/False builtins
+ import __builtin__
+ setattr(__builtin__, 'True', 1)
+ setattr(__builtin__, 'False', 0)
+
+
+from org.python.core import PyReflectedFunction #@UnresolvedImport
+
+from org.python import core #@UnresolvedImport
+from org.python.core import PyClass #@UnresolvedImport
+
+
+#completion types.
+TYPE_IMPORT = '0'
+TYPE_CLASS = '1'
+TYPE_FUNCTION = '2'
+TYPE_ATTR = '3'
+TYPE_BUILTIN = '4'
+TYPE_PARAM = '5'
+
+def _imp(name):
+ try:
+ return __import__(name)
+ except:
+ if '.' in name:
+