=== modified file 'completion/pycomplete.el'
--- completion/pycomplete.el	2012-07-03 18:33:58 +0000
+++ completion/pycomplete.el	2012-07-04 14:32:58 +0000
@@ -84,4 +84,81 @@
    (py-symbol-near-point)
    (py-find-global-imports)))
 
+(defun py-complete-python-dotexpr-begin nil
+  (re-search-backward "[^a-zA-Z_0-9\\.]")
+  (forward-char))
+
+(defun py-complete-python-dotexpr-end nil
+  (re-search-forward "[a-zA-Z_0-9\\.]*"))
+
+(put 'python-dotexpr 'beginning-op 'py-complete-python-dotexpr-begin)
+(put 'python-dotexpr 'end-op 'py-complete-python-dotexpr-end)
+
+(defun py-complete-show (string)
+  (display-message-or-buffer string "*PythonHelp*"))
+
+(defun py-complete-help (string)
+  "get help on a python expression"
+  (interactive "sHelp: ")
+  (let ((help-string
+         (pycomplete-pyhelp string (buffer-file-name) (py-find-global-imports))))
+    (if (and help-string (> (length help-string) 300))
+        (with-output-to-temp-buffer "*Python Help*"
+          (print help-string))
+      (py-complete-show help-string))))
+
+(defun py-complete-help-thing-at-point nil
+  (interactive)
+  (require 'thingatpt)
+  (let ((sym (thing-at-point 'python-dotexpr)))
+    (if sym
+        (py-complete-help sym))))
+
+(set 'py-complete-current-signature nil)
+
+(defun py-complete-signature (function)
+  "get signature of a python function or method"
+  (set 'py-complete-current-signature
+       (pycomplete-pysignature function (buffer-file-name))))
+
+(defun py-complete-signature-show nil
+  (require 'thingatpt)
+  (let ((sym (thing-at-point 'python-dotexpr)))
+    (if sym
+        (progn
+          (py-complete-show (py-complete-signature sym))))))
+
+(defun py-complete-signature-expr nil
+  (interactive)
+  (require 'thingatpt)
+  (let ((dotexpr (read-string "signature on: "
+                              (thing-at-point 'python-dotexpr))))
+    (if dotexpr
+        (py-complete-show
+         (py-complete-signature dotexpr)))))
+
+(defun py-complete-electric-lparen nil
+  "electricly insert '(', and try to get a signature for the stuff to the left"
+  (interactive)
+  (py-complete-signature-show)
+  (self-insert-command 1))
+
+(defun py-complete-electric-comma nil
+  "electricly insert ',', and redisplay latest signature"
+  (interactive)
+  (self-insert-command 1)
+  (if py-complete-current-signature
+      (py-complete-show (format "%s" py-complete-current-signature))))
+
+(defun py-complete-set-keymap ()
+  "Define key map with pycomplete functions."
+  (interactive)
+  (define-key python-mode-map "\M-\C-i" 'py-complete)
+  (define-key python-mode-map "\t" 'py-complete)
+  (define-key python-mode-map [f1] 'py-complete-help-thing-at-point)
+  (define-key python-mode-map "(" 'py-complete-electric-lparen)
+  (define-key python-mode-map "," 'py-complete-electric-comma)
+  (define-key python-mode-map [f2] 'py-complete-signature-expr)
+  (define-key python-mode-map [f3] 'py-complete-help))
+
 (provide 'pycomplete)

=== modified file 'completion/pycomplete.py'
--- completion/pycomplete.py	2012-07-02 12:01:27 +0000
+++ completion/pycomplete.py	2012-07-04 14:32:58 +0000
@@ -38,7 +38,13 @@
 # pdb.set_trace()
 
 import sys
-import os.path
+import types
+import inspect
+import StringIO
+import os
+
+_HELPOUT = StringIO.StringIO
+_STDOUT = sys.stdout
 
 try:
     x = set
@@ -47,20 +53,25 @@
 else:
     del x
 
+def _import_modules(imports, dglobals, dlocals):
+    """If given, execute import statements"""
+    if imports is not None:
+        for stmt in imports:
+            try:
+                exec stmt in dglobals, dlocals
+            except TypeError:
+                raise TypeError, 'invalid type: %s' % stmt
+            except Exception:
+                continue
+
 def get_all_completions(s, imports=None):
     """Return contextual completion of s (string of >= zero chars).
 
     If given, imports is a list of import statements to be executed first.
     """
     locald = {}
-    if imports is not None:
-        for stmt in imports:
-            try:
-                exec stmt in globals(), locald
-            except TypeError:
-                raise TypeError, "invalid type: %s" % stmt
-            except Exception:
-                continue
+
+    _import_modules(imports, globals(), locald)
 
     dots = s.split(".")
     if not s or len(dots) == 1:
@@ -118,6 +129,104 @@
 
         # return os.path.commonprefix([k[len(dots[-1]):] for k in completions])
 
+def pyhelp(s, fname=None, imports=None, debug=False):
+    """Return object description"""
+    if not s:
+        return ''
+    # changes to where the file is
+    if fname:
+        os.chdir(os.path.dirname(fname))
+    doc = ''
+    try:
+        doc = _gethelp(s, fname, imports)
+    except Exception, ex:
+        return '%s' % ex
+    return doc
+
+
+def pysignature(s, fname=None):
+    """Return info about function parameters"""
+
+    if not s:
+        return ''
+    # changes to where the file is
+    if fname:
+        os.chdir(os.path.dirname(fname))
+
+    obj = None
+    sig = ""
+
+    try:
+        obj = _load_symbol(s, globals(), locals())
+    except Exception, ex:
+        return '%s' % ex
+
+    if type(obj) in (types.ClassType, types.TypeType):
+        # Look for the highest __init__ in the class chain.
+        obj = _find_constructor(obj)
+    elif type(obj) == types.MethodType:
+        # bit of a hack for methods - turn it into a function
+        # but we drop the "self" param.
+        obj = obj.im_func
+
+    if type(obj) in [types.FunctionType, types.LambdaType]:
+        (args, varargs, varkw, defaults) = inspect.getargspec(obj)
+        sig = ('%s: %s' % (obj.__name__,
+                           inspect.formatargspec(args, varargs, varkw,
+                                                 defaults)))
+    doc = getattr(obj, '__doc__', '')
+    if doc and not sig:
+        doc = doc.lstrip()
+        pos = doc.find('\n')
+        if pos < 0 or pos > 70:
+            pos = 70
+        sig = doc[:pos]
+    return sig
+
+
+def _load_symbol(s, dglobals, dlocals):
+    sym = None
+    dots = s.split('.')
+    if not s or len(dots) == 1:
+        sym = eval(s, dglobals, dlocals)
+    else:
+        for i in range(1, len(dots)+1):
+            s = '.'.join(dots[:i])
+            if not s:
+                continue
+            try:
+                sym = eval(s, dglobals, dlocals)
+            except NameError:
+                try:
+                    sym = __import__(s, dglobals, dlocals, [])
+                    dglobals[s] = sym
+                except ImportError:
+                    pass
+            except AttributeError:
+                try:
+                    sym = __import__(s, dglobals, dlocals, [])
+                except ImportError:
+                    pass
+    return sym
+
+def _gethelp(s, fname=None, imports=None):
+    """Return string printed by `help` function"""
+    obj = None
+    try:
+        _import_modules(imports, globals(), locals())
+        obj = _load_symbol(s, globals(), locals())
+    except Exception, ex:
+        return '%s' % ex
+    if not obj:
+        obj = s
+    out = _HELPOUT()
+    try:
+        sys.stdout = out
+        help(obj)
+    finally:
+        sys.stdout = _STDOUT
+    return out.getvalue()
+
 if __name__ == "__main__":
     print "<empty> ->", pycomplete("")
     print "sys.get ->", pycomplete("sys.get")

