pylab imports work

This commit is contained in:
David Halter
2012-04-17 14:57:20 +02:00
parent dcf83069d9
commit 832a3cb2c0
5 changed files with 79 additions and 57 deletions

View File

@@ -1,10 +1,23 @@
import re import re
import sys
import os
import debug import debug
import parsing import parsing
class Parser(object): class Parser(object):
"""
This module is a parser for all builtin modules, which are programmed in
C/C++. It should also work on third party modules.
It can be instantiated with either a path or a name of the module. The path
is important for third party modules.
:param name: The name of the module.
:param path: The path of the module.
:param sys_path: The sys.path, which is can be customizable.
"""
map_types = { map_types = {
'floating point number': '0.0', 'floating point number': '0.0',
'string': '""', 'string': '""',
@@ -17,37 +30,55 @@ class Parser(object):
'object': '{}', 'object': '{}',
# TODO things like dbg: ('not working', 'tuple of integers') # TODO things like dbg: ('not working', 'tuple of integers')
} }
cache = {}
""" This module tries to imitate parsing.Scope """ def __init__(self, name=None, path=None, sys_path=sys.path):
def __init__(self, name): self.path = path
self.name = name print path
if name:
self.name = name
else:
name = os.path.basename(self.path)
self.name = name.rpartition('.')[0] # cut file type (normally .so)
self.path = os.path.dirname(self.path)
print self.name, self.path
self._content = {} self._content = {}
self._parser = None self._parser = None
self._module = None self._module = None
self.sys_path = sys_path
@property @property
def module(self): def module(self):
if not self._module: if not self._module:
print 'import', self.name self.sys_path.insert(0, self.path)
temp, sys.path = sys.path, self.sys_path
print 'sypa', sys.path
exec 'import %s as module' % self.name in self._content exec 'import %s as module' % self.name in self._content
print 'import2', self.name self.sys_path, sys.path = sys.path, temp
self.sys_path.pop(0)
self._module = self._content['module'] self._module = self._content['module']
print 'mod', self._content['module']
return self._module return self._module
@property @property
def parser(self): def parser(self):
""" get the parser lazy """ """ get the parser lazy """
if self._parser: if not self._parser:
return self._parser
else:
code = self._generate_code(self.module)
try: try:
self._parser = parsing.PyFuzzyParser(code) self._parser = Parser.cache[self.name, self.path].parser
except: except KeyError:
debug.warning('not possible to resolve', self.name, code) code = self._generate_code(self.module)
#open('builtin_fail', 'w').write(code) try:
raise self._parser = parsing.PyFuzzyParser(code)
return self._parser except:
debug.warning('not possible to resolve', self.name, code)
#open('builtin_fail', 'w').write(code)
raise
else:
Parser.cache[self.name, self.path] = self
return self._parser
def _generate_code(self, scope, depth=0): def _generate_code(self, scope, depth=0):
""" """
@@ -133,8 +164,8 @@ class Parser(object):
if depth == 0: if depth == 0:
#with open('writeout.py', 'w') as f: #with open('writeout.py', 'w') as f:
# f.write(code) # f.write(code)
import sys #import sys
sys.stdout.write(code) #sys.stdout.write(code)
#exit() #exit()
pass pass
return code return code
@@ -195,21 +226,9 @@ def parse_function_doc(func):
ret = 'return ' + ret ret = 'return ' + ret
return param_str, ret return param_str, ret
"""if current.arr_type == parsing.Array.EMPTY:
# the normal case - no array type
debug.dbg('length', len(current))
elif current.arr_type == parsing.Array.LIST:
result.append(__builtin__.list())
elif current.arr_type == parsing.Array.SET:
result.append(__builtin__.set())
elif current.arr_type == parsing.Array.TUPLE:
result.append(__builtin__.tuple())
elif current.arr_type == parsing.Array.DICT:
result.append(__builtin__.dict())
"""
class _Builtin(object): class _Builtin(object):
_builtins = Parser('__builtin__') _builtins = Parser(name='__builtin__')
@property @property
def scope(self): def scope(self):

View File

@@ -270,22 +270,17 @@ def get_scopes_for_name(scope, name, search_global=False):
def strip_imports(scopes): def strip_imports(scopes):
""" """
Here we strip the imports - they don't get resolved necessarily, but star Here we strip the imports - they don't get resolved necessarily.
imports are looked at here. Really used anymore?
""" """
result = [] result = []
for s in scopes: for s in scopes:
if isinstance(s, parsing.Import): if isinstance(s, parsing.Import):
print 'dini mueter, steile griech!' print 'dini mueter, steile griech!'
try: try:
new_scopes = follow_import(s) result += follow_import(s)
except modules.ModuleNotFound: except modules.ModuleNotFound:
debug.dbg('Module not found: ' + str(s)) debug.warning('Module not found: ' + str(s))
else:
result += new_scopes
for n in new_scopes:
result += strip_imports(i for i in n.get_imports()
if i.star)
else: else:
result.append(s) result.append(s)
return result return result
@@ -415,5 +410,10 @@ def follow_import(_import):
else: else:
scopes = [scope] scopes = [scope]
for s in scopes:
scopes += strip_imports(i for i in s.get_imports() if i.star)
debug.dbg('after import', scopes, rest) debug.dbg('after import', scopes, rest)
return scopes
# filter duplicate modules
return list(set(scopes))

View File

@@ -2,9 +2,9 @@
import functions import functions
functions.debug.debug_function = functions.debug.print_to_stdout #functions.debug.debug_function = functions.debug.print_to_stdout
functions.debug.ignored_modules = ['parsing', 'builtin'] functions.debug.ignored_modules = ['parsing', 'builtin']
#functions.debug.ignored_modules = ['parsing', 'builtin', 'evaluate', 'modules'] functions.debug.ignored_modules = ['parsing', 'builtin', 'evaluate', 'modules']
functions.modules.module_find_path.insert(0, '.') functions.modules.module_find_path.insert(0, '.')
f_name = 'parsetest.py' f_name = 'parsetest.py'
@@ -16,4 +16,5 @@ code = f.read()
for i in range(1): for i in range(1):
completions = functions.complete(code, 150, 200, path) completions = functions.complete(code, 150, 200, path)
print '\n', ', '.join(str(c) for c in completions) #print '\n', ', '.join(sorted(str(c) for c in completions))
print '#', len(completions)

View File

@@ -11,7 +11,6 @@ load_module_cb = None
module_find_path = sys.path[1:] module_find_path = sys.path[1:]
class ModuleNotFound(Exception): class ModuleNotFound(Exception):
pass pass
@@ -42,7 +41,7 @@ class File(object):
try: try:
timestamp, _parser = File.module_cache[self.module_path] timestamp, _parser = File.module_cache[self.module_path]
if timestamp == os.path.getmtime(self.module_path): if timestamp == os.path.getmtime(self.module_path):
debug.dbg('hit cache') debug.dbg('hit module cache')
return _parser return _parser
except: except:
pass pass
@@ -81,15 +80,12 @@ def find_module(current_module, point_path):
i = imp.find_module(string, path) i = imp.find_module(string, path)
except ImportError: except ImportError:
# find builtins (ommit path): # find builtins (ommit path):
i = imp.find_module(string) i = imp.find_module(string, module_find_path)
if i[0]:
# if the import has a file descriptor, it cannot be a builtin.
raise
return i return i
# TODO handle relative paths - they are included in the import object # TODO handle relative paths - they are included in the import object
current_namespace = None current_namespace = None
sys.path.insert(0, os.path.dirname(current_module.module_path)) module_find_path.insert(0, os.path.dirname(current_module.module_path))
# now execute those paths # now execute those paths
rest = [] rest = []
for i, s in enumerate(point_path): for i, s in enumerate(point_path):
@@ -102,7 +98,7 @@ def find_module(current_module, point_path):
raise ModuleNotFound( raise ModuleNotFound(
'The module you searched has not been found') 'The module you searched has not been found')
sys.path.pop(0) module_find_path.pop(0)
path = current_namespace[1] path = current_namespace[1]
is_package_directory = current_namespace[2][2] == imp.PKG_DIRECTORY is_package_directory = current_namespace[2][2] == imp.PKG_DIRECTORY
@@ -119,9 +115,9 @@ def find_module(current_module, point_path):
source = current_namespace[0].read() source = current_namespace[0].read()
if path.endswith('.py'): if path.endswith('.py'):
f = File(path, source) f = File(path, source)
if not f: else:
print 'lala' f = builtin.Parser(path=path)
f = builtin.Parser(path) else:
print 'lala2' f = builtin.Parser(name=path)
return f.parser.top, rest return f.parser.top, rest

View File

@@ -145,7 +145,7 @@ class Scope(Simple):
def get_imports(self): def get_imports(self):
""" Gets also the imports within flow statements """ """ Gets also the imports within flow statements """
i = self.imports i = [] + self.imports
for s in self.statements: for s in self.statements:
if isinstance(s, Scope): if isinstance(s, Scope):
i += s.get_imports() i += s.get_imports()
@@ -404,6 +404,12 @@ class Flow(Scope):
else: else:
return self.get_parent_until(Class, Function).get_set_vars() return self.get_parent_until(Class, Function).get_set_vars()
def get_imports(self):
i = super(Flow, self).get_imports()
if self.next:
i += self.next.get_imports()
return i
def set_next(self, next): def set_next(self, next):
""" Set the next element in the flow, those are else, except, etc. """ """ Set the next element in the flow, those are else, except, etc. """
if self.next: if self.next:
@@ -1199,7 +1205,7 @@ class PyFuzzyParser(object):
while indent <= self.scope.indent \ while indent <= self.scope.indent \
and (token_type == tokenize.NAME or tok in ['(', '['])\ and (token_type == tokenize.NAME or tok in ['(', '['])\
and self.scope != self.top: and self.scope != self.top:
debug.warning('syntax error: dedent @%s - %s<=%s', \ debug.dbg('syntax: dedent @%s - %s<=%s', \
(self.line_nr, indent, self.scope.indent)) (self.line_nr, indent, self.scope.indent))
self.scope.line_end = self.line_nr self.scope.line_end = self.line_nr
self.scope = self.scope.parent self.scope = self.scope.parent