From 6531d859ba4f61d6741b0e06bff07d07b3231910 Mon Sep 17 00:00:00 2001 From: Ian Thompson Date: Sat, 26 Jul 2008 20:02:10 +0000 Subject: [PATCH] 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.) --- release/scripts/bpymodules/BPyTextPlugin.py | 60 +++++++++++++-------- release/scripts/textplugin_functiondocs.py | 3 +- release/scripts/textplugin_imports.py | 6 +-- release/scripts/textplugin_membersuggest.py | 39 ++++++++++---- release/scripts/textplugin_outliner.py | 3 +- release/scripts/textplugin_suggest.py | 3 +- 6 files changed, 76 insertions(+), 38 deletions(-) diff --git a/release/scripts/bpymodules/BPyTextPlugin.py b/release/scripts/bpymodules/BPyTextPlugin.py index e39d67aacee..5143229f829 100644 --- a/release/scripts/bpymodules/BPyTextPlugin.py +++ b/release/scripts/bpymodules/BPyTextPlugin.py @@ -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() diff --git a/release/scripts/textplugin_functiondocs.py b/release/scripts/textplugin_functiondocs.py index acb1fdd6141..7456f7236da 100644 --- a/release/scripts/textplugin_functiondocs.py +++ b/release/scripts/textplugin_functiondocs.py @@ -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 diff --git a/release/scripts/textplugin_imports.py b/release/scripts/textplugin_imports.py index dd98ab7a26e..16d27ac1004 100644 --- a/release/scripts/textplugin_imports.py +++ b/release/scripts/textplugin_imports.py @@ -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 diff --git a/release/scripts/textplugin_membersuggest.py b/release/scripts/textplugin_membersuggest.py index a1cb510826f..63ade4b660b 100644 --- a/release/scripts/textplugin_membersuggest.py +++ b/release/scripts/textplugin_membersuggest.py @@ -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: diff --git a/release/scripts/textplugin_outliner.py b/release/scripts/textplugin_outliner.py index 6dbb86e3b67..0dbdb624dc5 100644 --- a/release/scripts/textplugin_outliner.py +++ b/release/scripts/textplugin_outliner.py @@ -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) diff --git a/release/scripts/textplugin_suggest.py b/release/scripts/textplugin_suggest.py index f39e2db1f7f..c2a12ac15f5 100644 --- a/release/scripts/textplugin_suggest.py +++ b/release/scripts/textplugin_suggest.py @@ -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)