summaryrefslogtreecommitdiff
path: root/emacs.d/elpa/python-mode-20200508.1756/completion/pycomplete.py
diff options
context:
space:
mode:
Diffstat (limited to 'emacs.d/elpa/python-mode-20200508.1756/completion/pycomplete.py')
-rw-r--r--emacs.d/elpa/python-mode-20200508.1756/completion/pycomplete.py798
1 files changed, 798 insertions, 0 deletions
diff --git a/emacs.d/elpa/python-mode-20200508.1756/completion/pycomplete.py b/emacs.d/elpa/python-mode-20200508.1756/completion/pycomplete.py
new file mode 100644
index 0000000..be381c7
--- /dev/null
+++ b/emacs.d/elpa/python-mode-20200508.1756/completion/pycomplete.py
@@ -0,0 +1,798 @@
+"""
+Python dot expression completion using Pymacs.
+
+This almost certainly needs work, but if you add
+
+ (require 'pycomplete)
+
+to your init.el file and have Pymacs installed, when you hit M-TAB it will
+try to complete the dot expression before point. For example, given this
+import at the top of the file:
+
+ import time
+
+typing "time.cl" then hitting M-TAB should complete "time.clock".
+
+This is unlikely to be done the way Emacs completion ought to be done, but
+it's a start. Perhaps someone with more Emacs mojo can take this stuff and
+do it right.
+
+See pycomplete.el for the Emacs Lisp side of things.
+
+Most of the public functions in this module have the signature
+
+(s, fname=None, imports=None)
+
+where s is the symbol to complete, fname is the file path and imports
+the list of import statements to use. The fname parameter is used as a
+key to cache the global and local context and the symbols imported or
+evaluated so far. The cache for an fname is cleared when its imports
+are changed. When not passing a list of imports (or None), the currently
+used imports are preserved. The caching should make subsequent operations
+(e.g. another completion or signature lookup after a completion) less
+expensive.
+"""
+
+# Original Author: Skip Montanaro <skip@pobox.com>
+# Maintainer: Urs Fleisch <ufleisch@users.sourceforge.net>
+# Created: Oct 2004
+# Keywords: python pymacs emacs
+
+# This software is provided as-is, without express or implied warranty.
+# Permission to use, copy, modify, distribute or sell this software, without
+# fee, for any purpose and by any individual or organization, is hereby
+# granted, provided that the above copyright notice and this paragraph
+# appear in all copies.
+
+# Along with pycomplete.el this file allows programmers to complete Python
+# symbols within the current buffer.
+
+import sys
+import types
+import inspect
+import keyword
+import os
+import pydoc
+import ast
+import re
+
+if sys.version_info[0] >= 3: # Python 3
+ import io
+else: # Python 2
+ import StringIO
+
+try:
+ x = set
+except NameError:
+ from sets import Set as set
+else:
+ del x
+
+
+class _PyCompleteDocument(object):
+ """Completion data for Python source file."""
+
+ if sys.version_info[0] >= 3: # Python 3
+ _helpout = io.StringIO
+ @staticmethod
+ def is_num_or_str(obj):
+ return isinstance(obj, (int, float, str))
+ @staticmethod
+ def is_class_type(obj):
+ return type(obj) == type
+ @staticmethod
+ def get_unbound_function(unbound):
+ return unbound
+ @staticmethod
+ def get_method_function(meth):
+ return meth.__func__
+ @staticmethod
+ def get_function_code(func):
+ return func.__code__
+ @staticmethod
+ def update_with_builtins(keys):
+ import builtins
+ keys.update(dir(builtins))
+ else: # Python 2
+ _helpout = StringIO.StringIO
+ @staticmethod
+ def is_num_or_str(obj):
+ return isinstance(obj, (int, long, float, basestring))
+ @staticmethod
+ def is_class_type(obj):
+ return type(obj) in (types.ClassType, types.TypeType)
+ @staticmethod
+ def get_unbound_function(unbound):
+ return unbound.im_func
+ @staticmethod
+ def get_method_function(meth):
+ return meth.im_func
+ @staticmethod
+ def get_function_code(func):
+ return func.func_code
+ @staticmethod
+ def update_with_builtins(keys):
+ import __builtin__
+ keys.update(dir(__builtin__))
+
+ _sre_SRE_Pattern = type(re.compile(''))
+ _sre_SRE_Match = type(re.match('', ''))
+
+ # Class name in CapCase, as suggested by PEP8 Python style guide
+ _class_name_re = re.compile(r'(?:^|\.)_?[A-Z][A-Za-z0-9]+$')
+
+ _return_type_of_func = {
+ 'bin': 'str',
+ 'bytearray': 'bytearray',
+ 'bytes': 'bytes',
+ 'compile': 'types.CodeType',
+ 'complex': 'complex',
+ 'dict': 'dict',
+ 'frozenset': 'frozenset',
+ 'oct': 'str',
+ 'open': 'io.BufferedIOBase' if sys.version_info[0] >= 3 else 'file',
+ 'list': 'list',
+ 'repr': 'str',
+ 'set': 'set',
+ 'sorted': 'list',
+ 'str': 'str',
+ 'tuple': 'tuple',
+ 'vars': 'dict',
+ 're.compile': '_PyCompleteDocument._sre_SRE_Pattern',
+ 're.escape': 'str',
+ 're.findall': 'list',
+ 're.match': '_PyCompleteDocument._sre_SRE_Match',
+ 're.search': '_PyCompleteDocument._sre_SRE_Match',
+ 're.split': 'list',
+ 're.sub': 'str',
+ 're.subn': 'tuple',
+ 'datetime.datetime': 'datetime.datetime',
+ 'datetime.date': 'datetime.date',
+ 'datetime.time': 'datetime.time',
+ 'datetime.timedelta': 'datetime.timedelta',
+ 'sys.exc_info': 'tuple',
+ 'os.getcwd': 'str',
+ 'os.getenv': 'str',
+ 'os.urandom': 'bytes',
+ 'os.path.abspath': 'str',
+ 'os.path.basename': 'str',
+ 'os.path.commonprefix': 'str',
+ 'os.path.dirname': 'str',
+ 'os.path.expanduser': 'str',
+ 'os.path.expandvars': 'str',
+ 'os.path.join': 'str',
+ 'os.path.normcase': 'str',
+ 'os.path.normpath': 'str',
+ 'os.path.realpath': 'str',
+ 'os.path.relpath': 'str',
+ 'os.path.split': 'tuple',
+ 'os.path.splitdrive': 'tuple',
+ 'os.path.splitext': 'tuple',
+ 'collections.defaultdict': 'collections.defaultdict',
+ 'collections.deque': 'collections.deque',
+ 'collections.namedtuple': 'collections.namedtuple',
+ 'socket.socket': 'socket.socket',
+ 'csv.excel': 'csv.excel',
+ 'csv.excel_tab': 'csv.excel_tab'
+ }
+
+ @staticmethod
+ def _get_type_for_function(funcname):
+ typename = _PyCompleteDocument._return_type_of_func.get(funcname)
+ if not typename and \
+ _PyCompleteDocument._class_name_re.search(funcname):
+ typename = funcname
+ return typename
+
+ @staticmethod
+ def _replace_pycfrt_with_typename(s):
+ """Replace _PYCFRT(..) expressions with function return type.
+
+ The names of variables assigned from function calls can be replaced by
+ _PYCFRT(name.of.function). This function tries to replace such expressions
+ with the corresponding function return type (PYCFRT = pycomplete function
+ return type). If no such expression can be found, s is returned unchanged.
+ If the type cannot be deduced, None is returned, else the substituted
+ string."""
+ pycfrt_re = re.compile(r'_PYCFRT\(([^()]+)\)')
+ return pycfrt_re.sub(lambda m: _PyCompleteDocument._get_type_for_function(m.group(1)), s)
+
+ class ImportExtractor(ast.NodeVisitor):
+ """NodeVisitor to extract the top-level import statements from an AST.
+
+ To generate code containing all imports in try-except statements,
+ call get_import_code(node), where node is a parsed AST.
+ """
+ def visit_FunctionDef(self, node):
+ # Ignore imports inside functions or methods.
+ pass
+
+ def visit_ClassDef(self, node):
+ # Ignore imports inside classes.
+ pass
+
+ def generic_visit(self, node):
+ # Store import statement nodes.
+ if isinstance(node, (ast.Import, ast.ImportFrom)):
+ self._import_nodes.append(node)
+ ast.NodeVisitor.generic_visit(self, node)
+
+ def get_import_code(self, node, fname='<string>'):
+ """Get compiled code of all top-level import statements found in the
+ AST of node."""
+ self._import_nodes = []
+ self.visit(node)
+ body = []
+ for imp_node in self._import_nodes:
+ if isinstance(imp_node, ast.ImportFrom) and \
+ imp_node.module == '__future__':
+ # 'SyntaxError: from __future__ imports must occur at the
+ # beginning of the file' is raised if a 'from __future__ import'
+ # is wrapped in try-except, so use only the import statement.
+ body.append(imp_node)
+ else:
+ if sys.version_info[0] >= 3: # Python 3
+ body.append(ast.Try(body=[imp_node], handlers=[
+ ast.ExceptHandler(type=None, name=None, body=[ast.Pass()])],
+ orelse=[], finalbody=[]))
+ else:
+ body.append(ast.TryExcept(body=[imp_node], handlers=[
+ ast.ExceptHandler(type=None, name=None, body=[ast.Pass()])],
+ orelse=[]))
+ node = ast.Module(body=body)
+ ast.fix_missing_locations(node)
+ code = compile(node, fname, 'exec')
+ return code
+
+
+ class CodeRemover(ast.NodeTransformer):
+ """NodeTransformer which replaces function statements with 'pass'
+ and keeps only safe assignments, so that the resulting code can
+ be used for code completion.
+
+ To reduce the code from the node of a parsed AST, call
+ get_transformed_code(node).
+ """
+ def visit_FunctionDef(self, node):
+ # Replace all function statements except doc string by 'pass'.
+ if node.body:
+ if isinstance(node.body[0], ast.Expr) and \
+ isinstance(node.body[0].value, ast.Str):
+ # Keep doc string.
+ first_stmt = node.body[1] if len(node.body) > 1 else node.body[0]
+ node.body = [node.body[0]]
+ else:
+ first_stmt = node.body[0]
+ node.body = []
+ node.body.append(ast.copy_location(ast.Pass(), first_stmt))
+ return node
+ return None
+
+ def visit_Expr(self, node):
+ # Remove all expressions except strings to keep doc strings.
+ if isinstance(node.value, ast.Str):
+ return node
+ return None
+
+ @staticmethod
+ def _get_type_node_for_function_node(node):
+ # Convert node to dot expression
+ attrs = []
+ while isinstance(node, ast.Attribute):
+ attrs.insert(0, node.attr)
+ node = node.value
+ if isinstance(node, ast.Name):
+ attrs.insert(0, node.id)
+ funcname = '.'.join(attrs)
+ typename = _PyCompleteDocument._get_type_for_function(funcname)
+ if typename:
+ # Convert dot expression to node
+ attrs = typename.split('.')
+ node = None
+ if attrs:
+ node = ast.Name(id=attrs.pop(0), ctx=ast.Load())
+ while attrs:
+ node = ast.Attribute(value=node, attr=attrs.pop(0),
+ ctx=ast.Load())
+ return node
+ return None
+
+ @staticmethod
+ def replace_unsafe_value(node, replace_self=None):
+ """Modify value from assignment if unsafe.
+
+ If replace_self is given, only assignments starting with 'self.' are
+ processed, the assignment node is returned with 'self.' replaced by
+ the value of replace_self (typically the class name).
+ For other assignments, None is returned."""
+ for i, target in enumerate(node.targets):
+ if not isinstance(target, (ast.Name, ast.Attribute)):
+ # Only process assignments to names and attributes,
+ # not tuples.
+ return None
+ if replace_self:
+ if isinstance(target, ast.Attribute) and \
+ isinstance(target.value, ast.Name) and \
+ target.value.id == 'self' and \
+ isinstance(target.value.ctx, ast.Load):
+ node.targets[i].value.id = replace_self
+ if target.attr == '__name__':
+ node.value = ast.copy_location(ast.Str(s=''),
+ node.value)
+ elif target.attr in ('__dict__', '__class__', '__bases__',
+ '__doc__'):
+ return None
+ else:
+ return None
+ elif isinstance(target, ast.Name) and \
+ isinstance(target.ctx, ast.Store):
+ if target.id == '__metaclass__':
+ # Do not modify __metaclass__ assignments
+ return node
+ elif target.id == '__slots__':
+ node.value = ast.copy_location(
+ ast.List(elts=[], ctx=ast.Load()), node.value)
+ if isinstance(node.value, (ast.Str, ast.Num)):
+ pass
+ elif isinstance(node.value, (ast.List, ast.Tuple)):
+ node.value.elts = []
+ elif isinstance(node.value, ast.Dict):
+ node.value.keys = []
+ node.value.values = []
+ elif isinstance(node.value, ast.ListComp):
+ node.value = ast.copy_location(ast.List(elts=[], ctx=ast.Load()), node.value)
+ elif isinstance(node.value, ast.Call):
+ type_node = _PyCompleteDocument.CodeRemover._get_type_node_for_function_node(node.value.func)
+ if type_node:
+ # Wrap class lookup in try-except because it is not fail-safe.
+ node.value = ast.copy_location(type_node, node.value)
+ if sys.version_info[0] >= 3: # Python 3
+ node = ast.copy_location(ast.Try(body=[node], handlers=[
+ ast.ExceptHandler(type=None, name=None, body=[ast.Pass()])],
+ orelse=[], finalbody=[]), node)
+ else:
+ node = ast.copy_location(ast.TryExcept(body=[node], handlers=[
+ ast.ExceptHandler(type=None, name=None, body=[ast.Pass()])],
+ orelse=[]), node)
+ ast.fix_missing_locations(node)
+ else:
+ node.value = ast.copy_location(
+ ast.Name(id='None', ctx=ast.Load()), node.value)
+ else:
+ node.value = ast.copy_location(ast.Name(id='None', ctx=ast.Load()), node.value)
+ return node
+
+ def visit_Assign(self, node):
+ # Replace unsafe values of assignements by None.
+ return self.replace_unsafe_value(node)
+
+ def visit_Name(self, node):
+ # Pass names for bases in ClassDef.
+ return node
+
+ def visit_Attribute(self, node):
+ # Pass attributes for bases in ClassDef.
+ return node
+
+ def visit_ClassDef(self, node):
+ # Visit nodes of class.
+ # Store instance member assignments to be added later to generated code.
+ self_assignments = {}
+ for child in ast.walk(node):
+ if isinstance(child, ast.Assign):
+ new_child = self.replace_unsafe_value(child,
+ replace_self=node.name)
+ if new_child:
+ new_var = child.targets[0].attr
+ old_assign = self_assignments.get(new_var)
+ if not old_assign or (
+ isinstance(old_assign, ast.Assign) and
+ isinstance(old_assign.value, ast.Name) and
+ old_assign.value.id == 'None'):
+ self_assignments[new_var] = new_child
+ self._class_assignments.extend(list(self_assignments.values()))
+ return ast.NodeTransformer.generic_visit(self, node)
+
+ def visit_Module(self, node):
+ # Visit nodes of module
+ return ast.NodeTransformer.generic_visit(self, node)
+
+ def generic_visit(self, node):
+ # Remove everything which is not handled by the methods above
+ return None
+
+ def get_transformed_code(self, node, fname='<string>'):
+ """Get compiled code containing only empty functions and methods
+ and safe assignments found in the AST of node."""
+ self._class_assignments = []
+ node = self.visit(node)
+ # The self members are added as attributes to the class objects
+ # rather than included as class variables inside the class definition
+ # so that names starting with '__' are not mangled.
+ node.body.extend(self._class_assignments)
+ code = compile(node, fname, 'exec')
+ return code
+
+ _stdout = sys.stdout
+
+ _instances = {}
+
+ def __init__(self, fname=None):
+ """Constructor for internal use.
+ The factory method instance() shall be used instead.
+ """
+ self._fname = fname
+ self._imports = None
+ self._globald = globals().copy()
+ self._symnames = []
+ self._symobjs = {}
+ self._parse_source_called = False
+
+ @classmethod
+ def instance(cls, fname):
+ """Get _PyCompleteDocument object for fname.
+ If no object for this file name exists, a new object is created and
+ registered.
+ """
+ obj = cls._instances.get(fname)
+ if obj is None:
+ obj = _PyCompleteDocument(fname)
+ cls._instances[fname] = obj
+ return obj
+
+ def _import_modules(self, imports):
+ """Import modules using the statements in imports.
+ If the imports are the same as in the last call, the methods
+ immediately returns, also if imports is None.
+ """
+ if imports is None and not self._parse_source_called:
+ self.parse_source()
+ if imports is None or imports == self._imports:
+ return
+ # changes to where the file is
+ if self._fname:
+ os.chdir(os.path.dirname(self._fname))
+ self._globald = globals().copy()
+ self._symnames = []
+ self._symobjs = {}
+ for stmt in imports:
+ try:
+ exec(stmt, self._globald)
+ except TypeError:
+ raise TypeError('invalid type: %s' % stmt)
+ except Exception:
+ continue
+ self._imports = imports
+
+ def _collect_symbol_names(self):
+ """Collect the global, local, builtin symbols in _symnames.
+ If _symnames is already set, the method immediately returns.
+ """
+ if not self._symnames:
+ keys = set(keyword.kwlist)
+ keys.update(list(self._globald.keys()))
+ self.update_with_builtins(keys)
+ self._symnames = list(keys)
+ self._symnames.sort()
+
+ def _get_symbol_object(self, s):
+ """Get a symbol by evaluating its name or importing a module
+ or submodule with the name s.
+ """
+ sym = self._symobjs.get(s)
+ if sym is not None:
+ return sym
+ # changes to where the file is
+ if self._fname:
+ os.chdir(os.path.dirname(self._fname))
+ try:
+ sym = eval(s, self._globald)
+ except NameError:
+ try:
+ sym = __import__(s, self._globald)
+ self._globald[s] = sym
+ except ImportError:
+ pass
+ except AttributeError:
+ try:
+ sym = __import__(s, self._globald)
+ except ImportError:
+ pass
+ except SyntaxError:
+ pass
+ if sym is not None:
+ self._symobjs[s] = sym
+ return sym
+
+ def _load_symbol(self, s, strict=False):
+ """Get a symbol for a dotted expression.
+
+ Returns the last successfully found symbol object in the
+ dotted chain. If strict is set True, it returns True as
+ soon as a symbol is not found. Therefore strict=True can
+ be used to find exactly the symbol for s, otherwise a
+ symbol for a parent can be returned, which may be enough
+ if searching for help on symbol.
+ """
+ s = self._replace_pycfrt_with_typename(s)
+ sym = self._symobjs.get(s)
+ if sym is not None:
+ return sym
+ dots = s.split('.')
+ if not s or len(dots) == 1:
+ sym = self._get_symbol_object(s)
+ else:
+ for i in range(1, len(dots) + 1):
+ s = '.'.join(dots[:i])
+ if not s:
+ continue
+ sym_i = self._get_symbol_object(s)
+ if sym_i is not None:
+ sym = sym_i
+ elif strict:
+ return None
+ return sym
+
+ def _get_help(self, s, imports=None):
+ """Return string printed by help function."""
+ if not s:
+ return ''
+ if s == 'pydoc.help':
+ # Prevent pydoc from going into interactive mode
+ s = 'pydoc.Helper'
+ obj = None
+ if not keyword.iskeyword(s):
+ try:
+ self._import_modules(imports)
+ obj = self._load_symbol(s, strict=False)
+ except Exception as ex:
+ return '%s' % ex
+ if not obj:
+ obj = str(s)
+ out = self._helpout()
+ try:
+ sys.stdout = out
+ pydoc.help(obj)
+ finally:
+ sys.stdout = self._stdout
+ return out.getvalue()
+
+ @staticmethod
+ def _find_constructor(class_ob):
+ """Given a class object, return a function object used for the
+ constructor (ie, __init__() ) or None if we can't find one."""
+ try:
+ return _PyCompleteDocument.get_unbound_function(class_ob.__init__)
+ except AttributeError:
+ for base in class_ob.__bases__:
+ rc = _PyCompleteDocument._find_constructor(base)
+ if rc is not None:
+ return rc
+ return None
+
+ def get_all_completions(self, 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.
+ """
+ self._import_modules(imports)
+
+ s = self._replace_pycfrt_with_typename(s)
+ last_dot_pos = s.rfind('.')
+ if last_dot_pos == -1:
+ self._collect_symbol_names()
+ if s:
+ return [k for k in self._symnames if k.startswith(s)]
+ else:
+ return self._symnames
+
+ sym = self._load_symbol(s[:last_dot_pos], strict=True)
+ if sym is not None:
+ s = s[last_dot_pos + 1:]
+ return [k for k in dir(sym) if k.startswith(s)]
+ return []
+
+ def complete(self, s, imports=None):
+ """Complete symbol if unique, else return list of completions."""
+ if not s:
+ return ''
+
+ completions = self.get_all_completions(s, imports)
+ if len(completions) == 0:
+ return None
+ else:
+ dots = s.split(".")
+ prefix = os.path.commonprefix([k for k in completions])
+ if len(completions) == 1 or len(prefix) > len(dots[-1]):
+ return [prefix[len(dots[-1]):]]
+ return completions
+
+ def help(self, s, imports=None):
+ """Return help on object."""
+ try:
+ return self._get_help(s, imports)
+ except Exception as ex:
+ return '%s' % ex
+
+ def get_docstring(self, s, imports=None):
+ """Return docstring for symbol s."""
+ if s and not keyword.iskeyword(s):
+ try:
+ self._import_modules(imports)
+ obj = self._load_symbol(s, strict=True)
+ if obj and not self.is_num_or_str(obj):
+ doc = inspect.getdoc(obj)
+ if doc:
+ return doc
+ except:
+ pass
+ return ''
+
+ def get_signature(self, s, imports=None):
+ """Return info about function parameters."""
+ if not s or keyword.iskeyword(s):
+ return ''
+ obj = None
+ sig = ""
+
+ try:
+ self._import_modules(imports)
+ obj = self._load_symbol(s, strict=False)
+ except Exception as ex:
+ return '%s' % ex
+
+ if self.is_class_type(obj):
+ # Look for the highest __init__ in the class chain.
+ ctr = self._find_constructor(obj)
+ if ctr is not None and type(ctr) in (
+ types.MethodType, types.FunctionType, types.LambdaType):
+ obj = ctr
+ elif type(obj) == types.MethodType:
+ # bit of a hack for methods - turn it into a function
+ # but we drop the "self" param.
+ obj = self.get_method_function(obj)
+
+ if type(obj) in [types.FunctionType, types.LambdaType]:
+ try:
+ (args, varargs, varkw, defaults) = inspect.getargspec(obj)
+ sig = ('%s: %s' % (obj.__name__,
+ inspect.formatargspec(args, varargs, varkw,
+ defaults)))
+ except ValueError:
+ try:
+ (args, varargs, varkw, defaults, kwonlyargs,
+ kwonlydefaults, annotations) = inspect.getfullargspec(obj)
+ sig = ('%s: %s' % (
+ obj.__name__, inspect.formatargspec(
+ args, varargs, varkw, defaults, kwonlyargs,
+ kwonlydefaults, annotations)))
+ except AttributeError:
+ pass
+
+ 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 get_location(self, s, imports=None):
+ """Return file path and line number of symbol, None if not found."""
+ if not s or keyword.iskeyword(s):
+ return None
+ try:
+ self._import_modules(imports)
+ obj = self._load_symbol(s, strict=False)
+ if obj is not None:
+ if self.is_class_type(obj):
+ obj = obj.__init__
+ if type(obj) == types.MethodType:
+ obj = self.get_method_function(obj)
+ if type(obj) in [types.FunctionType, types.LambdaType]:
+ code = self.get_function_code(obj)
+ return (os.path.abspath(code.co_filename), code.co_firstlineno)
+ # If not found, try using inspect.
+ return (inspect.getsourcefile(obj), inspect.getsourcelines(obj)[1])
+ except:
+ pass
+ return None
+
+ def parse_source(self, only_reload=False):
+ """Parse source code to get imports and completions.
+
+ If this method is called, the imports parameter for the other methods
+ must be omitted (or None), so that the imports are taken from the
+ parsed source code. If only_reload is True, the source is only parsed
+ if it has been parsed before.
+ None is returned if OK, else a string describing the error.
+ """
+ if only_reload and not self._parse_source_called:
+ return None
+ self._parse_source_called = True
+ if not self._fname:
+ return None
+
+ try:
+ with open(self._fname) as fh:
+ src = fh.read()
+ except IOError as ex:
+ return '%s' % ex
+
+ # changes to where the file is
+ os.chdir(os.path.dirname(self._fname))
+
+ try:
+ node = ast.parse(src, self._fname)
+ import_code = self.ImportExtractor().get_import_code(node, self._fname)
+ except (SyntaxError, TypeError) as ex:
+ return '%s' % ex
+
+ old_globald = self._globald.copy()
+ self._globald = globals().copy()
+ try:
+ exec(import_code, self._globald)
+ except Exception as ex:
+ self._globald = old_globald
+ return '%s' % ex
+
+ self._symnames = []
+ self._symobjs = {}
+
+ reduced_code = self.CodeRemover().get_transformed_code(node, self._fname)
+ try:
+ exec(reduced_code, self._globald)
+ except Exception as ex:
+ return '%s' % ex
+ return None
+
+def pycompletions(s, fname=None, imports=None):
+ """Get a list of possible completions for s.
+
+ The completions extend the expression s after the last dot.
+ """
+ return _PyCompleteDocument.instance(fname).get_all_completions(
+ s, imports)
+
+def pycomplete(s, fname=None, imports=None):
+ """Complete the Python expression s.
+
+ If multiple completions are found, a list of possible completions
+ (names after the last dot) is returned.
+ If one completion is found, a list with a string containing the
+ remaining characters is returned.
+ If no completion is found, None is returned.
+ """
+ return _PyCompleteDocument.instance(fname).complete(s, imports)
+
+def pyhelp(s, fname=None, imports=None):
+ """Return help on object s."""
+ return _PyCompleteDocument.instance(fname).help(s, imports)
+
+def pydocstring(s, fname=None, imports=None):
+ """Return docstring of symbol."""
+ return _PyCompleteDocument.instance(fname).get_docstring(s, imports)
+
+def pysignature(s, fname=None, imports=None):
+ """Return info about function parameters."""
+ return _PyCompleteDocument.instance(fname).get_signature(s, imports)
+
+def pylocation(s, fname=None, imports=None):
+ """Return file path and line number of symbol, None if not found."""
+ return _PyCompleteDocument.instance(fname).get_location(s, imports)
+
+def pyparse(fname, only_reload=False):
+ """Parse source code to get imports and completions.
+
+ If this function is called, the imports parameter for the other functions
+ must be omitted (or None), so that the imports are taken from the
+ parsed source code. If only_reload is True, the source is only parsed if
+ it has been parsed before.
+ """
+ return _PyCompleteDocument.instance(fname).parse_source(only_reload)
+
+# Local Variables :
+# pymacs-auto-reload : t
+# End :