diff --git a/docs/docs/features.rst b/docs/docs/features.rst index 65a85b9b..e7b89642 100644 --- a/docs/docs/features.rst +++ b/docs/docs/features.rst @@ -157,9 +157,9 @@ https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt Parameters ---------- var1 : array_like - Array_like means all those objects -- lists, nested lists, etc. -- - that can be converted to an array. We can also refer to - variables like `var1`. + Array_like means all those objects -- lists, nested lists, + etc. -- that can be converted to an array. We can also + refer to variables like `var1`. var2 : int The type above can either refer to an actual Python type (e.g. ``int``), or describe the type of the variable in more diff --git a/jedi/parser/__init__.py b/jedi/parser/__init__.py index 86a31249..022c1e88 100644 --- a/jedi/parser/__init__.py +++ b/jedi/parser/__init__.py @@ -174,7 +174,7 @@ class Parser(object): break return imports - def _parse_parentheses(self): + def _parse_parentheses(self, is_class): """ Functions and Classes have params (which means for classes super-classes). They are parsed here and returned as Statements. @@ -195,8 +195,9 @@ class Parser(object): if annotation: param.add_annotation(annotation) - # params without vars are usually syntax errors. - if param and (param.get_defined_names()): + # function params without vars are usually syntax errors. + # expressions are valid in superclass declarations. + if param and (param.get_defined_names() or is_class): param.position_nr = pos names.append(param) pos += 1 @@ -222,7 +223,7 @@ class Parser(object): tok = next(self._gen) if tok.string != '(': return None - params = self._parse_parentheses() + params = self._parse_parentheses(is_class=False) colon = next(self._gen) annotation = None @@ -259,17 +260,17 @@ class Parser(object): cname = pr.Name(self.module, [(cname.string, cname.start_pos)], cname.start_pos, cname.end_pos) - super = [] + superclasses = [] _next = next(self._gen) if _next.string == '(': - super = self._parse_parentheses() + superclasses = self._parse_parentheses(is_class=True) _next = next(self._gen) if _next.string != ':': debug.warning("class syntax: %s@%s", cname, _next.start_pos[0]) return None - return pr.Class(self.module, cname, super, first_pos) + return pr.Class(self.module, cname, superclasses, first_pos) def _parse_statement(self, pre_used_token=None, added_breaks=None, stmt_class=pr.Statement, names_are_set_vars=False): diff --git a/jedi/parser/representation.py b/jedi/parser/representation.py index b85f2fb3..4f730323 100644 --- a/jedi/parser/representation.py +++ b/jedi/parser/representation.py @@ -917,8 +917,8 @@ class Statement(Simple, DocstringMixin): def get_code(self, new_line=True): def assemble(command_list, assignment=None): - pieces = [c.get_code() if isinstance(c, Simple) else c.string if -isinstance(c, tokenize.Token) else unicode(c) + pieces = [c.get_code() if isinstance(c, Simple) else c.string + if isinstance(c, tokenize.Token) else unicode(c) for c in command_list] if assignment is None: return ''.join(pieces) diff --git a/test/completion/classes.py b/test/completion/classes.py index 7c6c4ff9..0aa4cf91 100644 --- a/test/completion/classes.py +++ b/test/completion/classes.py @@ -191,6 +191,22 @@ Base.upper #? ['upper'] Base().upper +# ----------------- +# dynamic inheritance +# ----------------- + +class Angry(object): + def shout(self): + return 'THIS IS MALARKEY!' + +def classgetter(): + return Angry + +class Dude(classgetter()): + def react(self): + #? ['shout'] + self.s + # ----------------- # __call__ # -----------------