file managment

This commit is contained in:
David Halter
2012-03-07 15:09:42 +01:00
parent 3fb2d50e93
commit e304f5f03b
2 changed files with 86 additions and 41 deletions

View File

@@ -1,5 +1,43 @@
import parsing import parsing
class File(object):
"""
Manages all files, that are parsed and caches them.
Important are the params source and module_name, one of them has to
be there.
:param source: The source code of the file.
:param module_name: The module name of the file.
:param row: The row, the user is currently in. Only important for the \
main file.
"""
def __init__(self, source=None, module_name=None, row=None):
self.source = source
self.module_name = module_name
self.row = row
self.line_cache = None
if not self.module_name and not self.source:
raise AttributeError("Submit a module name or the source code")
elif self.module_name:
self.load_module()
self.parser = parsing.PyFuzzyParser(source, row)
def load_module(self):
pass
def get_line(self, line):
if not self.line_cache:
self.line_cache = self.source.split('\n')
if 1 <= line <= len(self.line_cache):
return self.line_cache[line-1]
else:
return None
def complete(source, row, colum, file_callback=None): def complete(source, row, colum, file_callback=None):
""" """
An auto completer for python files. An auto completer for python files.
@@ -13,11 +51,12 @@ def complete(source, row, colum, file_callback=None):
:return: list :return: list
:rtype: list :rtype: list
""" """
row = 38 row = 89
p = parsing.PyFuzzyParser(source, row) f = File(source=source, row=row)
print print
print print
print p.user_scope print f.get_line(row)
print p.user_scope.get_simple_for_line(row) print f.parser.user_scope
return p.user_scope.get_set_vars() print f.parser.user_scope.get_simple_for_line(row)
return f.parser.user_scope.get_set_vars()

View File

@@ -50,7 +50,10 @@ def indent_block(text, indention=" "):
class Simple(object): class Simple(object):
""" The super class for Scope, Import and Statement. """ """
The super class for Scope, Import, Name and Statement. Every object in
the parser tree inherits from this class.
"""
def __init__(self, indent, line_nr, line_end=None): def __init__(self, indent, line_nr, line_end=None):
self.indent = indent self.indent = indent
self.line_nr = line_nr self.line_nr = line_nr
@@ -194,7 +197,7 @@ class Scope(Simple):
def get_simple_for_line(self, line): def get_simple_for_line(self, line):
""" Get the Simple objects, which are on the line. """ """ Get the Simple objects, which are on the line. """
simple = [] simple = []
for s in self.statements: for s in self.statements + self.imports:
if s.line_nr <= line <= s.line_end: if s.line_nr <= line <= s.line_end:
simple.append(s) simple.append(s)
return simple return simple
@@ -377,7 +380,7 @@ class Flow(Scope):
return next return next
class Import(object): class Import(Simple):
""" """
Stores the imports of any Scopes. Stores the imports of any Scopes.
@@ -396,8 +399,8 @@ class Import(object):
:param star: If a star is used -> from time import *. :param star: If a star is used -> from time import *.
:type star: bool :type star: bool
""" """
def __init__(self, line_nr, namespace, alias='', from_ns='', star=False): def __init__(self, indent, line_nr, line_end, namespace, alias='', from_ns='', star=False):
self.line_nr = line_nr super(Import, self).__init__(indent, line_nr, line_end)
self.namespace = namespace self.namespace = namespace
self.alias = alias self.alias = alias
self.from_ns = from_ns self.from_ns = from_ns
@@ -460,19 +463,16 @@ class Statement(Simple):
return self.set_vars return self.set_vars
class Name(object): class Name(Simple):
""" """
Used to define names in python. Used to define names in python.
Which means the whole namespace/class/function stuff. Which means the whole namespace/class/function stuff.
So a name like "module.class.function" So a name like "module.class.function"
would result in an array of [module, class, function] would result in an array of [module, class, function]
""" """
def __init__(self, names, indent, line_nr): def __init__(self, names, indent, line_nr, line_end):
super(Name, self).__init__() super(Name, self).__init__(indent, line_nr, line_end)
self.names = tuple(names) self.names = tuple(names)
self.indent = indent
self.line_nr = line_nr
self.parent = None
def get_code(self): def get_code(self):
""" Returns the names in a full string format """ """ Returns the names in a full string format """
@@ -523,16 +523,19 @@ class PyFuzzyParser(object):
The dot name parser parses a name, variable or function and returns The dot name parser parses a name, variable or function and returns
their names. their names.
:return: list of the names, token_type, nexttoken, start_indent. :return: list of the names, token_type, nexttoken, start_indent, \
:rtype: (Name, int, str, int) start_line.
:rtype: (Name, int, str, int, int)
""" """
names = [] names = []
if pre_used_token is None: if pre_used_token is None:
token_type, tok, indent = self.next() token_type, tok, indent = self.next()
start_line = self.line_nr
if token_type != tokenize.NAME and tok != '*': if token_type != tokenize.NAME and tok != '*':
return ([], tok) return ([], tok)
else: else:
token_type, tok, indent = pre_used_token token_type, tok, indent = pre_used_token
start_line = self.line_nr
names.append(tok) names.append(tok)
start_indent = indent start_indent = indent
while True: while True:
@@ -543,7 +546,7 @@ class PyFuzzyParser(object):
if token_type != tokenize.NAME: if token_type != tokenize.NAME:
break break
names.append(tok) names.append(tok)
return (names, token_type, tok, start_indent) return (names, token_type, tok, start_indent, start_line)
def _parse_value_list(self, pre_used_token=None): def _parse_value_list(self, pre_used_token=None):
""" """
@@ -553,15 +556,15 @@ class PyFuzzyParser(object):
value_list = [] value_list = []
if pre_used_token: if pre_used_token:
token_type, tok, indent = pre_used_token token_type, tok, indent = pre_used_token
n, token_type, tok, start_indent = self._parsedotname(tok) n, token_type, tok, start_indent, start_line = self._parsedotname(tok)
if n: if n:
value_list.append(Name(n, start_indent, self.line_nr)) value_list.append(Name(n, start_indent, start_line, self.line_nr))
token_type, tok, indent = self.next() token_type, tok, indent = self.next()
while tok != 'in' and token_type != tokenize.NEWLINE: while tok != 'in' and token_type != tokenize.NEWLINE:
n, token_type, tok, start_indent = self._parsedotname(self.current) n, token_type, tok, start_indent, start_line = self._parsedotname(self.current)
if n: if n:
value_list.append(Name(n, start_indent, self.line_nr)) value_list.append(Name(n, start_indent, start_line, self.line_nr))
if tok == 'in': if tok == 'in':
break break
@@ -586,14 +589,14 @@ class PyFuzzyParser(object):
""" """
imports = [] imports = []
while True: while True:
name, token_type, tok, start_indent = self._parsedotname() name, token_type, tok, start_indent, start_line = self._parsedotname()
if not name: if not name:
break break
name2 = None name2 = None
if tok == 'as': if tok == 'as':
name2, token_type, tok, start_indent2 = self._parsedotname() name2, token_type, tok, start_indent2, start_line = self._parsedotname()
name2 = Name(name2, start_indent2, self.line_nr) name2 = Name(name2, start_indent2, start_line, self.line_nr)
imports.append((Name(name, start_indent, self.line_nr), name2)) imports.append((Name(name, start_indent, start_line, self.line_nr), name2))
while tok != "," and "\n" not in tok: while tok != "," and "\n" not in tok:
token_type, tok, indent = self.next() token_type, tok, indent = self.next()
if tok != ",": if tok != ",":
@@ -625,11 +628,12 @@ class PyFuzzyParser(object):
:return: Return a Scope representation of the tokens. :return: Return a Scope representation of the tokens.
:rtype: Function :rtype: Function
""" """
start_line = self.line_nr
token_type, fname, ind = self.next() token_type, fname, ind = self.next()
if token_type != tokenize.NAME: if token_type != tokenize.NAME:
return None return None
fname = Name([fname], ind, self.line_nr) fname = Name([fname], ind, self.line_nr, self.line_nr)
token_type, open, ind = self.next() token_type, open, ind = self.next()
if open != '(': if open != '(':
@@ -640,7 +644,7 @@ class PyFuzzyParser(object):
if colon != ':': if colon != ':':
return None return None
return Function(fname, params, indent, self.line_nr) return Function(fname, params, indent, start_line)
def _parseclass(self, indent): def _parseclass(self, indent):
""" """
@@ -650,13 +654,14 @@ class PyFuzzyParser(object):
:return: Return a Scope representation of the tokens. :return: Return a Scope representation of the tokens.
:rtype: Class :rtype: Class
""" """
start_line = self.line_nr
token_type, cname, ind = self.next() token_type, cname, ind = self.next()
if token_type != tokenize.NAME: if token_type != tokenize.NAME:
print "class: syntax error - token is not a name@%s (%s: %s)" \ print "class: syntax error - token is not a name@%s (%s: %s)" \
% (self.line_nr, tokenize.tok_name[token_type], cname) % (self.line_nr, tokenize.tok_name[token_type], cname)
return None return None
cname = Name([cname], ind, self.line_nr) cname = Name([cname], ind, self.line_nr, self.line_nr)
super = [] super = []
token_type, next, ind = self.next() token_type, next, ind = self.next()
@@ -666,7 +671,7 @@ class PyFuzzyParser(object):
print "class: syntax error - %s@%s" % (cname, self.line_nr) print "class: syntax error - %s@%s" % (cname, self.line_nr)
return None return None
return Class(cname, super, indent, self.line_nr) return Class(cname, super, indent, start_line)
def _parseassignment(self): def _parseassignment(self):
""" TODO remove or replace, at the moment not used """ """ TODO remove or replace, at the moment not used """
@@ -749,9 +754,9 @@ class PyFuzzyParser(object):
string += " %s " % tok string += " %s " % tok
token_type, tok, indent_dummy = self.next() token_type, tok, indent_dummy = self.next()
if token_type == tokenize.NAME: if token_type == tokenize.NAME:
path, token_type, tok, start_indent = \ path, token_type, tok, start_indent, start_line = \
self._parsedotname(self.current) self._parsedotname(self.current)
n = Name(path, start_indent, self.line_nr) n = Name(path, start_indent, start_line, self.line_nr)
set_vars.append(n) set_vars.append(n)
string += ".".join(path) string += ".".join(path)
continue continue
@@ -763,9 +768,9 @@ class PyFuzzyParser(object):
# delete those statements, just let the rest stand there # delete those statements, just let the rest stand there
set_string = '' set_string = ''
else: else:
path, token_type, tok, start_indent = \ path, token_type, tok, start_indent, start_line = \
self._parsedotname(self.current) self._parsedotname(self.current)
n = Name(path, start_indent, self.line_nr) n = Name(path, start_indent, start_line, self.line_nr)
if tok == '(': if tok == '(':
# it must be a function # it must be a function
used_funcs.append(n) used_funcs.append(n)
@@ -856,6 +861,7 @@ class PyFuzzyParser(object):
self.scope.line_end = self.line_nr self.scope.line_end = self.line_nr
self.scope = self.scope.parent self.scope = self.scope.parent
start_line = self.line_nr
if tok == 'def': if tok == 'def':
func = self._parsefunction(indent) func = self._parsefunction(indent)
if func is None: if func is None:
@@ -877,20 +883,20 @@ class PyFuzzyParser(object):
elif tok == 'import': elif tok == 'import':
imports = self._parseimportlist() imports = self._parseimportlist()
for mod, alias in imports: for mod, alias in imports:
self.scope.add_import(Import(self.line_nr, mod, alias)) self.scope.add_import(Import(indent, start_line, self.line_nr, mod, alias))
freshscope = False freshscope = False
elif tok == 'from': elif tok == 'from':
mod, token_type, tok, start_indent = self._parsedotname() mod, token_type, tok, start_indent, start_line2 = self._parsedotname()
if not mod or tok != "import": if not mod or tok != "import":
print "from: syntax error..." print "from: syntax error..."
continue continue
mod = Name(mod, start_indent, self.line_nr) mod = Name(mod, start_indent, start_line2, self.line_nr)
names = self._parseimportlist() names = self._parseimportlist()
for name, alias in names: for name, alias in names:
star = name.names[0] == '*' star = name.names[0] == '*'
if star: if star:
name = None name = None
i = Import(self.line_nr, name, alias, mod, star) i = Import(indent, start_line, self.line_nr, name, alias, mod, star)
self.scope.add_import(i) self.scope.add_import(i)
freshscope = False freshscope = False
#loops #loops
@@ -914,9 +920,9 @@ class PyFuzzyParser(object):
if tok in added_breaks: if tok in added_breaks:
# the except statement defines a var # the except statement defines a var
# this is only true for python 2 # this is only true for python 2
path, token_type, tok, start_indent = \ path, token_type, tok, start_indent, start_line2= \
self._parsedotname() self._parsedotname()
n = Name(path, start_indent, self.line_nr) n = Name(path, start_indent, start_line2, self.line_nr)
statement.set_vars.append(n) statement.set_vars.append(n)
statement.code += ',' + n.get_code() statement.code += ',' + n.get_code()
if tok == ':': if tok == ':':