TextPlugin update: Converted try-except blocks to use try-catch-else to allow better error tracking. Commented the descriptor classes and improved variable support for basic types (string, list, etc.)

This commit is contained in:
Ian Thompson 2008-07-26 20:02:10 +00:00
parent 9f19d88a5d
commit 6531d859ba
6 changed files with 76 additions and 38 deletions

View File

@ -2,9 +2,15 @@ import bpy, sys
import __builtin__, tokenize
from Blender.sys import time
from tokenize import generate_tokens, TokenError, \
COMMENT, DEDENT, INDENT, NAME, NEWLINE, NL
COMMENT, DEDENT, INDENT, NAME, NEWLINE, NL, STRING
class ScriptDesc():
"""Describes a script through lists of further descriptor objects (classes,
defs, vars) and dictionaries to built-in types (imports). If a script has
not been fully parsed, its incomplete flag will be set. The time of the last
parse is held by the time field and the name of the text object from which
it was parsed, the name field.
"""
def __init__(self, name, imports, classes, defs, vars, incomplete=False):
self.name = name
@ -19,6 +25,10 @@ class ScriptDesc():
self.time = time()
class ClassDesc():
"""Describes a class through lists of further descriptor objects (defs and
vars). The name of the class is held by the name field and the line on
which it is defined is held in lineno.
"""
def __init__(self, name, defs, vars, lineno):
self.name = name
@ -27,6 +37,9 @@ class ClassDesc():
self.lineno = lineno
class FunctionDesc():
"""Describes a function through its name and list of parameters (name,
params) and the line on which it is defined (lineno).
"""
def __init__(self, name, params, lineno):
self.name = name
@ -34,6 +47,10 @@ class FunctionDesc():
self.lineno = lineno
class VarDesc():
"""Describes a variable through its name and type (if ascertainable) and the
line on which it is defined (lineno). If no type can be determined, type
will equal None.
"""
def __init__(self, name, type, lineno):
self.name = name
@ -47,7 +64,7 @@ CTX_SINGLE_QUOTE = 1
CTX_DOUBLE_QUOTE = 2
CTX_COMMENT = 3
# Special period constants
# Special time period constants
AUTO = -1
# Python keywords
@ -84,20 +101,15 @@ def get_cached_descriptor(txt, period=AUTO):
r = r << 1
period = r
key = hash(txt)
parse = True
key = hash(txt)
if _parse_cache.has_key(key):
desc = _parse_cache[key]
if desc.time >= time() - period:
parse = desc.incomplete
if parse:
try:
desc = parse_text(txt)
except:
if _parse_cache.has_key(key):
del _parse_cache[key]
desc = NoneScriptDesc
desc = parse_text(txt)
return desc
@ -138,8 +150,14 @@ def parse_text(txt):
prev_string = ''
incomplete = False
try:
for type, string, start, end, line in tokens:
while True:
try:
type, string, start, end, line = tokens.next()
except StopIteration:
break
except TokenError:
incomplete = True
break
# Skip all comments and line joining characters
if type == COMMENT or type == NL:
@ -215,14 +233,16 @@ def parse_text(txt):
module = get_module(imp_from +'.'+ imp_name)
else:
module = get_module(imp_name)
imports[imp_symb] = module
except (ImportError, ValueError, AttributeError, TypeError):
# Try importing name as an attribute of the parent
try:
module = __import__(imp_from, globals(), locals(), [imp_name])
imports[imp_symb] = getattr(module, imp_name)
except (ImportError, ValueError, AttributeError, TypeError):
pass
else:
imports[imp_symb] = getattr(module, imp_name)
else:
imports[imp_symb] = module
# More to import from the same module?
if string == ',':
@ -337,8 +357,8 @@ def parse_text(txt):
if string == '[':
close = line.find(']', end[1])
var_type = list
elif string == '"' or string == '"':
close = line.find(string, end[1])
elif type == STRING:
close = end[1]
var_type = str
elif string == '(':
close = line.find(')', end[1])
@ -389,9 +409,9 @@ def parse_text(txt):
var_name = var_accum.keys()[0]
var_type = None
if string == '[': var_type = list
elif string == '"' or string == '"': var_type = string
elif type == STRING: var_type = str
elif string == '(': var_type = tuple
elif string == 'dict': var_type = dict
elif string == '{': var_type = dict
vars[var_name] = VarDesc(var_name, var_type, start[0])
var3_step = 0
@ -402,12 +422,6 @@ def parse_text(txt):
prev_type = type
prev_string = string
# end:for
except TokenError:
incomplete = True
pass
desc = ScriptDesc(txt.name, imports, classes, defs, vars, incomplete)
desc.set_time()

View File

@ -11,9 +11,10 @@ Tooltip: 'Attempts to display documentation about the function preceding the cur
try:
import bpy
from BPyTextPlugin import *
OK = True
except ImportError:
OK = False
else:
OK = True
def main():
txt = bpy.data.texts.active

View File

@ -8,13 +8,13 @@ Tooltip: 'Lists modules when import or from is typed'
"""
# Only run if we have the required modules
OK = False
try:
import bpy, sys
from BPyTextPlugin import *
OK = True
except ImportError:
pass
OK = False
else:
OK = True
def main():
txt = bpy.data.texts.active

View File

@ -11,9 +11,10 @@ Tooltip: 'Lists members of the object preceding the cursor in the current text s
try:
import bpy
from BPyTextPlugin import *
OK = True
except ImportError:
OK = False
else:
OK = True
def main():
txt = bpy.data.texts.active
@ -36,7 +37,25 @@ def main():
# Identify the root (root.sub.sub.)
obj = None
if imports.has_key(pre[0]):
if pre[0] == '':
i = c - len('.'.join(pre)) - 1
if i >= 0:
if line[i] == '"' or line[i] == "'":
obj = str
elif line[i] == '}':
obj = dict
elif line[i] == ']': # Could be array elem x[y] or list [y]
i = line.rfind('[', 0, i) - 1
while i >= 0:
if line[i].isalnum() or line[i] == '_':
break
elif line[i] != ' ' and line[i] != '\t':
i = -1
break
i -= 1
if i < 0:
obj = list
elif imports.has_key(pre[0]):
obj = imports[pre[0]]
elif builtins.has_key(pre[0]):
obj = builtins[pre[0]]
@ -58,22 +77,24 @@ def main():
try:
attr = obj.__dict__.keys()
if not attr:
attr = dir(obj)
except AttributeError:
attr = dir(obj)
else:
if not attr:
attr = dir(obj)
list = []
items = []
for k in attr:
try:
v = getattr(obj, k)
list.append((k, type_char(v)))
except (AttributeError, TypeError): # Some attributes are not readable
pass
else:
items.append((k, type_char(v)))
if list != []:
list.sort(cmp = suggest_cmp)
txt.suggest(list, pre[-1])
if items != []:
items.sort(cmp = suggest_cmp)
txt.suggest(items, pre[-1])
# Check we are running as a script and not imported as a module
if __name__ == "__main__" and OK:

View File

@ -12,9 +12,10 @@ try:
import bpy
from BPyTextPlugin import *
from Blender import Draw
OK = True
except ImportError:
OK = False
else:
OK = True
def make_menu(items, eventoffs):
n = len(items)

View File

@ -11,9 +11,10 @@ Tooltip: 'Performs suggestions based on the context of the cursor'
try:
import bpy
from BPyTextPlugin import *
OK = True
except ImportError:
OK = False
else:
OK = True
def check_membersuggest(line, c):
pos = line.rfind('.', 0, c)