return directives
directives.append(self.try_to_parse_directive(optname, args, kwds, node.function.pos))
return directives
-
+ elif isinstance(node, (AttributeNode, NameNode)):
+ self.visit(node)
+ optname = node.as_cython_attribute()
+ if optname:
+ directivetype = Options.directive_types.get(optname)
+ if directivetype is bool:
+ return [(optname, True)]
+ elif directivetype is None:
+ return [(optname, None)]
+ else:
+ raise PostParseError(
+ node.pos, "The '%s' directive should be used as a function call." % optname)
return None
def try_to_parse_directive(self, optname, args, kwds, pos):
# Handle decorators
def visit_FuncDefNode(self, node):
- directives = []
- if node.decorators:
- # Split the decorators into two lists -- real decorators and directives
- realdecs = []
- for dec in node.decorators:
- new_directives = self.try_to_parse_directives(dec.decorator)
- if new_directives is not None:
- directives.extend(new_directives)
+ directives = self._extract_directives(node, 'function')
+ if not directives:
+ return self.visit_Node(node)
+ body = StatListNode(node.pos, stats=[node])
+ return self.visit_with_directives(body, directives)
+
+ def visit_CVarDefNode(self, node):
+ for dec in node.decorators:
+ for directive in self.try_to_parse_directives(dec.decorator) or ():
+ if directive is not None and directive[0] == u'locals':
+ node.directive_locals = directive[1]
else:
- realdecs.append(dec)
- if realdecs and isinstance(node, CFuncDefNode):
- raise PostParseError(realdecs[0].pos, "Cdef functions cannot take arbitrary decorators.")
+ self.context.nonfatal_error(PostParseError(dec.pos,
+ "Cdef functions can only take cython.locals() decorator."))
+ return node
+
+ def visit_CClassDefNode(self, node):
+ directives = self._extract_directives(node, 'cclass')
+ if not directives:
+ return self.visit_Node(node)
+ body = StatListNode(node.pos, stats=[node])
+ return self.visit_with_directives(body, directives)
+
+ def _extract_directives(self, node, scope_name):
+ if not node.decorators:
+ return {}
+ # Split the decorators into two lists -- real decorators and directives
+ directives = []
+ realdecs = []
+ for dec in node.decorators:
+ new_directives = self.try_to_parse_directives(dec.decorator)
+ if new_directives is not None:
+ for directive in new_directives:
+ if self.check_directive_scope(node.pos, directive[0], scope_name):
+ directives.append(directive)
else:
- node.decorators = realdecs
-
- if directives:
- optdict = {}
- directives.reverse() # Decorators coming first take precedence
- for directive in directives:
- name, value = directive
- legal_scopes = Options.directive_scopes.get(name, None)
- if not self.check_directive_scope(node.pos, name, 'function'):
- continue
- if name in optdict:
- old_value = optdict[name]
- # keywords and arg lists can be merged, everything
- # else overrides completely
- if isinstance(old_value, dict):
- old_value.update(value)
- elif isinstance(old_value, list):
- old_value.extend(value)
- else:
- optdict[name] = value
+ realdecs.append(dec)
+ if realdecs and isinstance(node, (CFuncDefNode, CClassDefNode)):
+ raise PostParseError(realdecs[0].pos, "Cdef functions/classes cannot take arbitrary decorators.")
+ else:
+ node.decorators = realdecs
+ # merge or override repeated directives
+ optdict = {}
+ directives.reverse() # Decorators coming first take precedence
+ for directive in directives:
+ name, value = directive
+ if name in optdict:
+ old_value = optdict[name]
+ # keywords and arg lists can be merged, everything
+ # else overrides completely
+ if isinstance(old_value, dict):
+ old_value.update(value)
+ elif isinstance(old_value, list):
+ old_value.extend(value)
else:
optdict[name] = value
- body = StatListNode(node.pos, stats=[node])
- return self.visit_with_directives(body, optdict)
- else:
- return self.visit_Node(node)
-
- def visit_CVarDefNode(self, node):
- if node.decorators:
- for dec in node.decorators:
- for directive in self.try_to_parse_directives(dec.decorator) or []:
- if directive is not None and directive[0] == u'locals':
- node.directive_locals = directive[1]
- else:
- self.context.nonfatal_error(PostParseError(dec.pos,
- "Cdef functions can only take cython.locals() decorator."))
- return node
-
+ else:
+ optdict[name] = value
+ return optdict
+
# Handle with statements
def visit_WithStatNode(self, node):
directive_dict = {}