Index: Doc/lib/asttable.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/asttable.tex,v retrieving revision 1.1 diff -c -r1.1 asttable.tex *** Doc/lib/asttable.tex 27 Sep 2001 20:06:07 -0000 1.1 --- Doc/lib/asttable.tex 1 Aug 2004 12:55:07 -0000 *************** *** 73,78 **** --- 73,81 ---- \lineiii{Continue}{}{} \hline + \lineiii{Decorators}{\member{nodes}}{List of function decorator expressions} + \hline + \lineiii{Dict}{\member{items}}{} \hline *************** *** 101,107 **** \lineiii{}{\member{names}}{} \hline ! \lineiii{Function}{\member{name}}{name used in def, a string} \lineiii{}{\member{argnames}}{list of argument names, as strings} \lineiii{}{\member{defaults}}{list of default values} \lineiii{}{\member{flags}}{xxx} --- 104,111 ---- \lineiii{}{\member{names}}{} \hline ! \lineiii{Function}{\member{decorators}}{\class{Decorators} or \code{None}} ! \lineiii{}{\member{name}}{name used in def, a string} \lineiii{}{\member{argnames}}{list of argument names, as strings} \lineiii{}{\member{defaults}}{list of default values} \lineiii{}{\member{flags}}{xxx} Index: Doc/lib/libfuncs.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libfuncs.tex,v retrieving revision 1.167 diff -c -r1.167 libfuncs.tex *** Doc/lib/libfuncs.tex 29 Jul 2004 06:06:34 -0000 1.167 --- Doc/lib/libfuncs.tex 1 Aug 2004 12:55:07 -0000 *************** *** 109,118 **** \begin{verbatim} class C: def f(cls, arg1, arg2, ...): ... - f = classmethod(f) \end{verbatim} It can be called either on the class (such as \code{C.f()}) or on an instance (such as \code{C().f()}). The instance is ignored except for its class. --- 109,122 ---- \begin{verbatim} class C: + @classmethod def f(cls, arg1, arg2, ...): ... \end{verbatim} + The \code{@classmethod} form is a function decorator -- see the description + of function definitions in chapter 7 of the + \citetitle[../ref/ref.html]{Python Reference Manual} for details. + It can be called either on the class (such as \code{C.f()}) or on an instance (such as \code{C().f()}). The instance is ignored except for its class. *************** *** 122,127 **** --- 126,132 ---- Class methods are different than \Cpp{} or Java static methods. If you want those, see \function{staticmethod()} in this section. \versionadded{2.2} + Function decorator syntax added in version 2.4. \end{funcdesc} \begin{funcdesc}{cmp}{x, y} *************** *** 936,945 **** \begin{verbatim} class C: def f(arg1, arg2, ...): ... - f = staticmethod(f) \end{verbatim} It can be called either on the class (such as \code{C.f()}) or on an instance (such as \code{C().f()}). The instance is ignored except for its class. --- 941,954 ---- \begin{verbatim} class C: + @staticmethod def f(arg1, arg2, ...): ... \end{verbatim} + The \code{@staticmethod} form is a function decorator -- see the description + of function definitions in chapter 7 of the + \citetitle[../ref/ref.html]{Python Reference Manual} for details. + It can be called either on the class (such as \code{C.f()}) or on an instance (such as \code{C().f()}). The instance is ignored except for its class. Index: Doc/ref/ref7.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref7.tex,v retrieving revision 1.38 diff -c -r1.38 ref7.tex *** Doc/ref/ref7.tex 2 Jun 2004 12:59:59 -0000 1.38 --- Doc/ref/ref7.tex 1 Aug 2004 12:55:07 -0000 *************** *** 315,322 **** \begin{productionlist} \production{funcdef} ! {"def" \token{funcname} "(" [\token{parameter_list}] ")" ":" \token{suite}} \production{parameter_list} {(\token{defparameter} ",")*} \productioncont{("*" \token{identifier} [, "**" \token{identifier}]} --- 315,326 ---- \begin{productionlist} \production{funcdef} ! {[\token{decorators}] "def" \token{funcname} "(" [\token{parameter_list}] ")" ":" \token{suite}} + \production{decorators} + {\token{decorator} ([NEWLINE] \token{decorator})* NEWLINE} + \production{decorator} + {"@" \token{dotted_name} ["(" [\token{argument_list} [","]] ")"]} \production{parameter_list} {(\token{defparameter} ",")*} \productioncont{("*" \token{identifier} [, "**" \token{identifier}]} *************** *** 343,348 **** --- 347,373 ---- The function definition does not execute the function body; this gets executed only when the function is called. + A function definition may be wrapped by one or more decorator expressions. + Decorator expressions are evaluated when the function is defined, in the scope + that contains the function definition. The result must be a callable, + which is invoked with the function object as the only argument. + The returned value is bound to the function name instead of the function + object. If there are multiple decorators, they are applied in reverse + order. For example, the following code: + + \begin{verbatim} + @f1 + @f2 + def func(): pass + \end{verbatim} + + is equivalent to: + + \begin{verbatim} + def func(): pass + func = f2(f1(func)) + \end{verbatim} + When one or more top-level parameters have the form \var{parameter} \code{=} \var{expression}, the function is said to have ``default parameter values.'' For a parameter with a Index: Grammar/Grammar =================================================================== RCS file: /cvsroot/python/python/dist/src/Grammar/Grammar,v retrieving revision 1.49 diff -c -r1.49 Grammar *** Grammar/Grammar 19 May 2004 08:20:04 -0000 1.49 --- Grammar/Grammar 1 Aug 2004 12:55:07 -0000 *************** *** 28,34 **** file_input: (NEWLINE | stmt)* ENDMARKER eval_input: testlist NEWLINE* ENDMARKER ! funcdef: 'def' NAME parameters ':' suite parameters: '(' [varargslist] ')' varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME) | fpdef ['=' test] (',' fpdef ['=' test])* [','] fpdef: NAME | '(' fplist ')' --- 28,36 ---- file_input: (NEWLINE | stmt)* ENDMARKER eval_input: testlist NEWLINE* ENDMARKER ! decorator: '@' dotted_name [ '(' [arglist] ')' ] ! decorators: decorator ([NEWLINE] decorator)* NEWLINE ! funcdef: [decorators] 'def' NAME parameters ':' suite parameters: '(' [varargslist] ')' varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME) | fpdef ['=' test] (',' fpdef ['=' test])* [','] fpdef: NAME | '(' fplist ')' Index: Include/node.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/node.h,v retrieving revision 2.22 diff -c -r2.22 node.h *** Include/node.h 17 Sep 2002 03:27:02 -0000 2.22 --- Include/node.h 1 Aug 2004 12:55:07 -0000 *************** *** 22,28 **** --- 22,30 ---- /* Node access functions */ #define NCH(n) ((n)->n_nchildren) + #define CHILD(n, i) (&(n)->n_child[i]) + #define RCHILD(n, i) (CHILD(n, NCH(n) + i)) #define TYPE(n) ((n)->n_type) #define STR(n) ((n)->n_str) Index: Include/token.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/token.h,v retrieving revision 2.20 diff -c -r2.20 token.h *** Include/token.h 12 Aug 2002 07:21:57 -0000 2.20 --- Include/token.h 1 Aug 2004 12:55:08 -0000 *************** *** 57,66 **** #define DOUBLESTAREQUAL 47 #define DOUBLESLASH 48 #define DOUBLESLASHEQUAL 49 /* Don't forget to update the table _PyParser_TokenNames in tokenizer.c! */ ! #define OP 50 ! #define ERRORTOKEN 51 ! #define N_TOKENS 52 /* Special definitions for cooperation with parser */ --- 57,67 ---- #define DOUBLESTAREQUAL 47 #define DOUBLESLASH 48 #define DOUBLESLASHEQUAL 49 + #define AT 50 /* Don't forget to update the table _PyParser_TokenNames in tokenizer.c! */ ! #define OP 51 ! #define ERRORTOKEN 52 ! #define N_TOKENS 53 /* Special definitions for cooperation with parser */ Index: Lib/pyclbr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/pyclbr.py,v retrieving revision 1.32 diff -c -r1.32 pyclbr.py *** Lib/pyclbr.py 17 Dec 2003 20:43:32 -0000 1.32 --- Lib/pyclbr.py 1 Aug 2004 12:55:08 -0000 *************** *** 222,228 **** else: super.append(token) inherit = names ! cur_class = Class(module, class_name, inherit, file, lineno) if not stack: dict[class_name] = cur_class stack.append((cur_class, thisindent)) --- 222,228 ---- else: super.append(token) inherit = names ! cur_class = Class(fullmodule, class_name, inherit, file, lineno) if not stack: dict[class_name] = cur_class stack.append((cur_class, thisindent)) Index: Lib/tokenize.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/tokenize.py,v retrieving revision 1.35 diff -c -r1.35 tokenize.py *** Lib/tokenize.py 27 Feb 2003 20:14:42 -0000 1.35 --- Lib/tokenize.py 1 Aug 2004 12:55:08 -0000 *************** *** 83,89 **** r"~") Bracket = '[][(){}]' ! Special = group(r'\r?\n', r'[:;.,`]') Funny = group(Operator, Bracket, Special) PlainToken = group(Number, Funny, String, Name) --- 83,89 ---- r"~") Bracket = '[][(){}]' ! Special = group(r'\r?\n', r'[:;.,`@]') Funny = group(Operator, Bracket, Special) PlainToken = group(Number, Funny, String, Name) Index: Lib/compiler/ast.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/compiler/ast.py,v retrieving revision 1.23 diff -c -r1.23 ast.py *** Lib/compiler/ast.py 19 May 2004 08:20:06 -0000 1.23 --- Lib/compiler/ast.py 1 Aug 2004 12:55:08 -0000 *************** *** 48,146 **** class EmptyNode(Node): pass ! class Slice(Node): ! nodes["slice"] = "Slice" ! def __init__(self, expr, flags, lower, upper): ! self.expr = expr ! self.flags = flags ! self.lower = lower ! self.upper = upper def getChildren(self): ! children = [] ! children.append(self.expr) ! children.append(self.flags) ! children.append(self.lower) ! children.append(self.upper) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.append(self.expr) ! if self.lower is not None: nodelist.append(self.lower) ! if self.upper is not None: nodelist.append(self.upper) ! return tuple(nodelist) def __repr__(self): ! return "Slice(%s, %s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.lower), repr(self.upper)) ! class Const(Node): ! nodes["const"] = "Const" ! def __init__(self, value): ! self.value = value def getChildren(self): ! return self.value, def getChildNodes(self): ! return () def __repr__(self): ! return "Const(%s)" % (repr(self.value),) ! class Raise(Node): ! nodes["raise"] = "Raise" ! def __init__(self, expr1, expr2, expr3): ! self.expr1 = expr1 ! self.expr2 = expr2 ! self.expr3 = expr3 def getChildren(self): children = [] ! children.append(self.expr1) ! children.append(self.expr2) ! children.append(self.expr3) return tuple(children) def getChildNodes(self): nodelist = [] ! if self.expr1 is not None: nodelist.append(self.expr1) ! if self.expr2 is not None: nodelist.append(self.expr2) ! if self.expr3 is not None: nodelist.append(self.expr3) return tuple(nodelist) def __repr__(self): ! return "Raise(%s, %s, %s)" % (repr(self.expr1), repr(self.expr2), repr(self.expr3)) ! class For(Node): ! nodes["for"] = "For" ! def __init__(self, assign, list, body, else_): ! self.assign = assign ! self.list = list ! self.body = body ! self.else_ = else_ def getChildren(self): ! children = [] ! children.append(self.assign) ! children.append(self.list) ! children.append(self.body) ! children.append(self.else_) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.append(self.assign) ! nodelist.append(self.list) ! nodelist.append(self.body) ! if self.else_ is not None: nodelist.append(self.else_) ! return tuple(nodelist) def __repr__(self): ! return "For(%s, %s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.body), repr(self.else_)) ! class AssTuple(Node): ! nodes["asstuple"] = "AssTuple" def __init__(self, nodes): self.nodes = nodes --- 48,119 ---- class EmptyNode(Node): pass ! class Expression(Node): ! # Expression is an artificial node class to support "eval" ! nodes["expression"] = "Expression" ! def __init__(self, node): ! self.node = node def getChildren(self): ! return self.node, def getChildNodes(self): ! return self.node, def __repr__(self): ! return "Expression(%s)" % (repr(self.node)) ! class Add(Node): ! nodes["add"] = "Add" ! def __init__(self, (left, right)): ! self.left = left ! self.right = right def getChildren(self): ! return self.left, self.right def getChildNodes(self): ! return self.left, self.right def __repr__(self): ! return "Add((%s, %s))" % (repr(self.left), repr(self.right)) ! class And(Node): ! nodes["and"] = "And" ! def __init__(self, nodes): ! self.nodes = nodes def getChildren(self): children = [] ! children.extend(flatten(self.nodes)) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) return tuple(nodelist) def __repr__(self): ! return "And(%s)" % (repr(self.nodes),) ! class AssAttr(Node): ! nodes["assattr"] = "AssAttr" ! def __init__(self, expr, attrname, flags): ! self.expr = expr ! self.attrname = attrname ! self.flags = flags def getChildren(self): ! return self.expr, self.attrname, self.flags def getChildNodes(self): ! return self.expr, def __repr__(self): ! return "AssAttr(%s, %s, %s)" % (repr(self.expr), repr(self.attrname), repr(self.flags)) ! class AssList(Node): ! nodes["asslist"] = "AssList" def __init__(self, nodes): self.nodes = nodes *************** *** 155,517 **** return tuple(nodelist) def __repr__(self): ! return "AssTuple(%s)" % (repr(self.nodes),) ! class Mul(Node): ! nodes["mul"] = "Mul" ! def __init__(self, (left, right)): ! self.left = left ! self.right = right def getChildren(self): ! return self.left, self.right def getChildNodes(self): ! return self.left, self.right def __repr__(self): ! return "Mul((%s, %s))" % (repr(self.left), repr(self.right)) ! class Invert(Node): ! nodes["invert"] = "Invert" ! def __init__(self, expr): ! self.expr = expr def getChildren(self): ! return self.expr, def getChildNodes(self): ! return self.expr, def __repr__(self): ! return "Invert(%s)" % (repr(self.expr),) ! class RightShift(Node): ! nodes["rightshift"] = "RightShift" ! def __init__(self, (left, right)): ! self.left = left ! self.right = right def getChildren(self): ! return self.left, self.right def getChildNodes(self): ! return self.left, self.right def __repr__(self): ! return "RightShift((%s, %s))" % (repr(self.left), repr(self.right)) ! class AssList(Node): ! nodes["asslist"] = "AssList" ! def __init__(self, nodes): self.nodes = nodes def getChildren(self): children = [] children.extend(flatten(self.nodes)) return tuple(children) def getChildNodes(self): nodelist = [] nodelist.extend(flatten_nodes(self.nodes)) return tuple(nodelist) def __repr__(self): ! return "AssList(%s)" % (repr(self.nodes),) ! class From(Node): ! nodes["from"] = "From" ! def __init__(self, modname, names): ! self.modname = modname ! self.names = names def getChildren(self): ! return self.modname, self.names def getChildNodes(self): ! return () def __repr__(self): ! return "From(%s, %s)" % (repr(self.modname), repr(self.names)) ! class Getattr(Node): ! nodes["getattr"] = "Getattr" ! def __init__(self, expr, attrname): self.expr = expr - self.attrname = attrname def getChildren(self): ! return self.expr, self.attrname def getChildNodes(self): return self.expr, def __repr__(self): ! return "Getattr(%s, %s)" % (repr(self.expr), repr(self.attrname)) ! class Dict(Node): ! nodes["dict"] = "Dict" ! def __init__(self, items): ! self.items = items def getChildren(self): children = [] ! children.extend(flatten(self.items)) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.items)) return tuple(nodelist) def __repr__(self): ! return "Dict(%s)" % (repr(self.items),) ! class Module(Node): ! nodes["module"] = "Module" ! def __init__(self, doc, node): ! self.doc = doc ! self.node = node def getChildren(self): ! return self.doc, self.node def getChildNodes(self): ! return self.node, def __repr__(self): ! return "Module(%s, %s)" % (repr(self.doc), repr(self.node)) ! class Expression(Node): ! # Expression is an artificial node class to support "eval" ! nodes["expression"] = "Expression" ! def __init__(self, node): ! self.node = node def getChildren(self): ! return self.node, def getChildNodes(self): ! return self.node, def __repr__(self): ! return "Expression(%s)" % (repr(self.node)) ! class UnaryAdd(Node): ! nodes["unaryadd"] = "UnaryAdd" ! def __init__(self, expr): ! self.expr = expr def getChildren(self): ! return self.expr, def getChildNodes(self): ! return self.expr, def __repr__(self): ! return "UnaryAdd(%s)" % (repr(self.expr),) ! ! class Ellipsis(Node): ! nodes["ellipsis"] = "Ellipsis" ! def __init__(self, ): ! pass ! ! def getChildren(self): ! return () ! ! def getChildNodes(self): ! return () ! ! def __repr__(self): ! return "Ellipsis()" ! class Print(Node): ! nodes["print"] = "Print" ! def __init__(self, nodes, dest): ! self.nodes = nodes ! self.dest = dest def getChildren(self): children = [] ! children.extend(flatten(self.nodes)) ! children.append(self.dest) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) ! if self.dest is not None: nodelist.append(self.dest) return tuple(nodelist) def __repr__(self): ! return "Print(%s, %s)" % (repr(self.nodes), repr(self.dest)) ! ! class Import(Node): ! nodes["import"] = "Import" ! def __init__(self, names): ! self.names = names ! ! def getChildren(self): ! return self.names, ! ! def getChildNodes(self): ! return () ! ! def __repr__(self): ! return "Import(%s)" % (repr(self.names),) ! class Subscript(Node): ! nodes["subscript"] = "Subscript" ! def __init__(self, expr, flags, subs): ! self.expr = expr ! self.flags = flags ! self.subs = subs def getChildren(self): children = [] ! children.append(self.expr) ! children.append(self.flags) ! children.extend(flatten(self.subs)) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.append(self.expr) ! nodelist.extend(flatten_nodes(self.subs)) return tuple(nodelist) def __repr__(self): ! return "Subscript(%s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.subs)) ! class TryExcept(Node): ! nodes["tryexcept"] = "TryExcept" ! def __init__(self, body, handlers, else_): ! self.body = body ! self.handlers = handlers ! self.else_ = else_ def getChildren(self): children = [] ! children.append(self.body) ! children.extend(flatten(self.handlers)) ! children.append(self.else_) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.append(self.body) ! nodelist.extend(flatten_nodes(self.handlers)) ! if self.else_ is not None: nodelist.append(self.else_) return tuple(nodelist) def __repr__(self): ! return "TryExcept(%s, %s, %s)" % (repr(self.body), repr(self.handlers), repr(self.else_)) ! class Or(Node): ! nodes["or"] = "Or" ! def __init__(self, nodes): ! self.nodes = nodes def getChildren(self): ! children = [] ! children.extend(flatten(self.nodes)) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) ! return tuple(nodelist) def __repr__(self): ! return "Or(%s)" % (repr(self.nodes),) ! class Name(Node): ! nodes["name"] = "Name" ! def __init__(self, name): ! self.name = name def getChildren(self): ! return self.name, def getChildNodes(self): return () def __repr__(self): ! return "Name(%s)" % (repr(self.name),) ! ! class Function(Node): ! nodes["function"] = "Function" ! def __init__(self, name, argnames, defaults, flags, doc, code): ! self.name = name ! self.argnames = argnames ! self.defaults = defaults ! self.flags = flags ! self.doc = doc ! self.code = code ! self.varargs = self.kwargs = None ! if flags & CO_VARARGS: ! self.varargs = 1 ! if flags & CO_VARKEYWORDS: ! self.kwargs = 1 ! def getChildren(self): ! children = [] ! children.append(self.name) ! children.append(self.argnames) ! children.extend(flatten(self.defaults)) ! children.append(self.flags) ! children.append(self.doc) ! children.append(self.code) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.extend(flatten_nodes(self.defaults)) ! nodelist.append(self.code) ! return tuple(nodelist) def __repr__(self): ! return "Function(%s, %s, %s, %s, %s, %s)" % (repr(self.name), repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.doc), repr(self.code)) ! class Assert(Node): ! nodes["assert"] = "Assert" ! def __init__(self, test, fail): ! self.test = test ! self.fail = fail def getChildren(self): children = [] ! children.append(self.test) ! children.append(self.fail) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.append(self.test) ! if self.fail is not None: nodelist.append(self.fail) return tuple(nodelist) def __repr__(self): ! return "Assert(%s, %s)" % (repr(self.test), repr(self.fail)) ! class Return(Node): ! nodes["return"] = "Return" ! def __init__(self, value): ! self.value = value def getChildren(self): ! return self.value, def getChildNodes(self): ! return self.value, def __repr__(self): ! return "Return(%s)" % (repr(self.value),) ! class Power(Node): ! nodes["power"] = "Power" def __init__(self, (left, right)): self.left = left self.right = right --- 128,457 ---- return tuple(nodelist) def __repr__(self): ! return "AssList(%s)" % (repr(self.nodes),) ! class AssName(Node): ! nodes["assname"] = "AssName" ! def __init__(self, name, flags): ! self.name = name ! self.flags = flags def getChildren(self): ! return self.name, self.flags def getChildNodes(self): ! return () def __repr__(self): ! return "AssName(%s, %s)" % (repr(self.name), repr(self.flags)) ! class AssTuple(Node): ! nodes["asstuple"] = "AssTuple" ! def __init__(self, nodes): ! self.nodes = nodes def getChildren(self): ! children = [] ! children.extend(flatten(self.nodes)) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) ! return tuple(nodelist) def __repr__(self): ! return "AssTuple(%s)" % (repr(self.nodes),) ! class Assert(Node): ! nodes["assert"] = "Assert" ! def __init__(self, test, fail): ! self.test = test ! self.fail = fail def getChildren(self): ! children = [] ! children.append(self.test) ! children.append(self.fail) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.append(self.test) ! if self.fail is not None: nodelist.append(self.fail) ! return tuple(nodelist) def __repr__(self): ! return "Assert(%s, %s)" % (repr(self.test), repr(self.fail)) ! class Assign(Node): ! nodes["assign"] = "Assign" ! def __init__(self, nodes, expr): self.nodes = nodes + self.expr = expr def getChildren(self): children = [] children.extend(flatten(self.nodes)) + children.append(self.expr) return tuple(children) def getChildNodes(self): nodelist = [] nodelist.extend(flatten_nodes(self.nodes)) + nodelist.append(self.expr) return tuple(nodelist) def __repr__(self): ! return "Assign(%s, %s)" % (repr(self.nodes), repr(self.expr)) ! class AugAssign(Node): ! nodes["augassign"] = "AugAssign" ! def __init__(self, node, op, expr): ! self.node = node ! self.op = op ! self.expr = expr def getChildren(self): ! return self.node, self.op, self.expr def getChildNodes(self): ! return self.node, self.expr def __repr__(self): ! return "AugAssign(%s, %s, %s)" % (repr(self.node), repr(self.op), repr(self.expr)) ! class Backquote(Node): ! nodes["backquote"] = "Backquote" ! def __init__(self, expr): self.expr = expr def getChildren(self): ! return self.expr, def getChildNodes(self): return self.expr, def __repr__(self): ! return "Backquote(%s)" % (repr(self.expr),) ! class Bitand(Node): ! nodes["bitand"] = "Bitand" ! def __init__(self, nodes): ! self.nodes = nodes def getChildren(self): children = [] ! children.extend(flatten(self.nodes)) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) return tuple(nodelist) def __repr__(self): ! return "Bitand(%s)" % (repr(self.nodes),) ! class Bitor(Node): ! nodes["bitor"] = "Bitor" ! def __init__(self, nodes): ! self.nodes = nodes def getChildren(self): ! children = [] ! children.extend(flatten(self.nodes)) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) ! return tuple(nodelist) def __repr__(self): ! return "Bitor(%s)" % (repr(self.nodes),) ! class Bitxor(Node): ! nodes["bitxor"] = "Bitxor" ! def __init__(self, nodes): ! self.nodes = nodes def getChildren(self): ! children = [] ! children.extend(flatten(self.nodes)) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) ! return tuple(nodelist) def __repr__(self): ! return "Bitxor(%s)" % (repr(self.nodes),) ! class Break(Node): ! nodes["break"] = "Break" ! def __init__(self, ): ! pass def getChildren(self): ! return () def getChildNodes(self): ! return () def __repr__(self): ! return "Break()" ! class CallFunc(Node): ! nodes["callfunc"] = "CallFunc" ! def __init__(self, node, args, star_args = None, dstar_args = None): ! self.node = node ! self.args = args ! self.star_args = star_args ! self.dstar_args = dstar_args def getChildren(self): children = [] ! children.append(self.node) ! children.extend(flatten(self.args)) ! children.append(self.star_args) ! children.append(self.dstar_args) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.append(self.node) ! nodelist.extend(flatten_nodes(self.args)) ! if self.star_args is not None: nodelist.append(self.star_args) ! if self.dstar_args is not None: nodelist.append(self.dstar_args) return tuple(nodelist) def __repr__(self): ! return "CallFunc(%s, %s, %s, %s)" % (repr(self.node), repr(self.args), repr(self.star_args), repr(self.dstar_args)) ! class Class(Node): ! nodes["class"] = "Class" ! def __init__(self, name, bases, doc, code): ! self.name = name ! self.bases = bases ! self.doc = doc ! self.code = code def getChildren(self): children = [] ! children.append(self.name) ! children.extend(flatten(self.bases)) ! children.append(self.doc) ! children.append(self.code) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.bases)) ! nodelist.append(self.code) return tuple(nodelist) def __repr__(self): ! return "Class(%s, %s, %s, %s)" % (repr(self.name), repr(self.bases), repr(self.doc), repr(self.code)) ! class Compare(Node): ! nodes["compare"] = "Compare" ! def __init__(self, expr, ops): ! self.expr = expr ! self.ops = ops def getChildren(self): children = [] ! children.append(self.expr) ! children.extend(flatten(self.ops)) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.append(self.expr) ! nodelist.extend(flatten_nodes(self.ops)) return tuple(nodelist) def __repr__(self): ! return "Compare(%s, %s)" % (repr(self.expr), repr(self.ops)) ! class Const(Node): ! nodes["const"] = "Const" ! def __init__(self, value): ! self.value = value def getChildren(self): ! return self.value, def getChildNodes(self): ! return () def __repr__(self): ! return "Const(%s)" % (repr(self.value),) ! class Continue(Node): ! nodes["continue"] = "Continue" ! def __init__(self, ): ! pass def getChildren(self): ! return () def getChildNodes(self): return () def __repr__(self): ! return "Continue()" + class Decorators(Node): + nodes["decorators"] = "Decorators" + def __init__(self, nodes): + self.nodes = nodes def getChildren(self): ! return tuple(flatten(self.nodes)) def getChildNodes(self): ! return flatten_nodes(self.nodes) def __repr__(self): ! return "Decorators(%s)" % (repr(self.nodes),) ! class Dict(Node): ! nodes["dict"] = "Dict" ! def __init__(self, items): ! self.items = items def getChildren(self): children = [] ! children.extend(flatten(self.items)) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.items)) return tuple(nodelist) def __repr__(self): ! return "Dict(%s)" % (repr(self.items),) ! class Discard(Node): ! nodes["discard"] = "Discard" ! def __init__(self, expr): ! self.expr = expr def getChildren(self): ! return self.expr, def getChildNodes(self): ! return self.expr, def __repr__(self): ! return "Discard(%s)" % (repr(self.expr),) ! class Div(Node): ! nodes["div"] = "Div" def __init__(self, (left, right)): self.left = left self.right = right *************** *** 523,529 **** return self.left, self.right def __repr__(self): ! return "Power((%s, %s))" % (repr(self.left), repr(self.right)) class Exec(Node): nodes["exec"] = "Exec" --- 463,483 ---- return self.left, self.right def __repr__(self): ! return "Div((%s, %s))" % (repr(self.left), repr(self.right)) ! ! class Ellipsis(Node): ! nodes["ellipsis"] = "Ellipsis" ! def __init__(self, ): ! pass ! ! def getChildren(self): ! return () ! ! def getChildNodes(self): ! return () ! ! def __repr__(self): ! return "Ellipsis()" class Exec(Node): nodes["exec"] = "Exec" *************** *** 549,760 **** def __repr__(self): return "Exec(%s, %s, %s)" % (repr(self.expr), repr(self.locals), repr(self.globals)) ! class Stmt(Node): ! nodes["stmt"] = "Stmt" ! def __init__(self, nodes): ! self.nodes = nodes def getChildren(self): ! children = [] ! children.extend(flatten(self.nodes)) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) ! return tuple(nodelist) def __repr__(self): ! return "Stmt(%s)" % (repr(self.nodes),) ! class Sliceobj(Node): ! nodes["sliceobj"] = "Sliceobj" ! def __init__(self, nodes): ! self.nodes = nodes def getChildren(self): children = [] ! children.extend(flatten(self.nodes)) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) return tuple(nodelist) def __repr__(self): ! return "Sliceobj(%s)" % (repr(self.nodes),) ! class Break(Node): ! nodes["break"] = "Break" ! def __init__(self, ): ! pass def getChildren(self): ! return () def getChildNodes(self): return () def __repr__(self): ! return "Break()" - class Bitand(Node): - nodes["bitand"] = "Bitand" - def __init__(self, nodes): - self.nodes = nodes def getChildren(self): children = [] ! children.extend(flatten(self.nodes)) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) return tuple(nodelist) def __repr__(self): ! return "Bitand(%s)" % (repr(self.nodes),) - class FloorDiv(Node): - nodes["floordiv"] = "FloorDiv" - def __init__(self, (left, right)): - self.left = left - self.right = right def getChildren(self): ! return self.left, self.right def getChildNodes(self): ! return self.left, self.right def __repr__(self): ! return "FloorDiv((%s, %s))" % (repr(self.left), repr(self.right)) - class TryFinally(Node): - nodes["tryfinally"] = "TryFinally" - def __init__(self, body, final): - self.body = body - self.final = final def getChildren(self): ! return self.body, self.final def getChildNodes(self): ! return self.body, self.final def __repr__(self): ! return "TryFinally(%s, %s)" % (repr(self.body), repr(self.final)) ! class Not(Node): ! nodes["not"] = "Not" ! def __init__(self, expr): ! self.expr = expr def getChildren(self): ! return self.expr, def getChildNodes(self): ! return self.expr, def __repr__(self): ! return "Not(%s)" % (repr(self.expr),) ! class Class(Node): ! nodes["class"] = "Class" ! def __init__(self, name, bases, doc, code): ! self.name = name ! self.bases = bases ! self.doc = doc ! self.code = code def getChildren(self): children = [] ! children.append(self.name) ! children.extend(flatten(self.bases)) ! children.append(self.doc) ! children.append(self.code) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.bases)) ! nodelist.append(self.code) return tuple(nodelist) def __repr__(self): ! return "Class(%s, %s, %s, %s)" % (repr(self.name), repr(self.bases), repr(self.doc), repr(self.code)) ! class Mod(Node): ! nodes["mod"] = "Mod" ! def __init__(self, (left, right)): ! self.left = left ! self.right = right def getChildren(self): ! return self.left, self.right def getChildNodes(self): ! return self.left, self.right def __repr__(self): ! return "Mod((%s, %s))" % (repr(self.left), repr(self.right)) ! class Printnl(Node): ! nodes["printnl"] = "Printnl" ! def __init__(self, nodes, dest): ! self.nodes = nodes ! self.dest = dest def getChildren(self): ! children = [] ! children.extend(flatten(self.nodes)) ! children.append(self.dest) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) ! if self.dest is not None: nodelist.append(self.dest) ! return tuple(nodelist) def __repr__(self): ! return "Printnl(%s, %s)" % (repr(self.nodes), repr(self.dest)) ! class Tuple(Node): ! nodes["tuple"] = "Tuple" ! def __init__(self, nodes): ! self.nodes = nodes def getChildren(self): children = [] ! children.extend(flatten(self.nodes)) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) return tuple(nodelist) def __repr__(self): ! return "Tuple(%s)" % (repr(self.nodes),) ! class AssAttr(Node): ! nodes["assattr"] = "AssAttr" ! def __init__(self, expr, attrname, flags): self.expr = expr - self.attrname = attrname - self.flags = flags def getChildren(self): ! return self.expr, self.attrname, self.flags def getChildNodes(self): return self.expr, def __repr__(self): ! return "AssAttr(%s, %s, %s)" % (repr(self.expr), repr(self.attrname), repr(self.flags)) class Keyword(Node): nodes["keyword"] = "Keyword" --- 503,762 ---- def __repr__(self): return "Exec(%s, %s, %s)" % (repr(self.expr), repr(self.locals), repr(self.globals)) ! class FloorDiv(Node): ! nodes["floordiv"] = "FloorDiv" ! def __init__(self, (left, right)): ! self.left = left ! self.right = right def getChildren(self): ! return self.left, self.right def getChildNodes(self): ! return self.left, self.right def __repr__(self): ! return "FloorDiv((%s, %s))" % (repr(self.left), repr(self.right)) ! class For(Node): ! nodes["for"] = "For" ! def __init__(self, assign, list, body, else_): ! self.assign = assign ! self.list = list ! self.body = body ! self.else_ = else_ def getChildren(self): children = [] ! children.append(self.assign) ! children.append(self.list) ! children.append(self.body) ! children.append(self.else_) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.append(self.assign) ! nodelist.append(self.list) ! nodelist.append(self.body) ! if self.else_ is not None: nodelist.append(self.else_) return tuple(nodelist) def __repr__(self): ! return "For(%s, %s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.body), repr(self.else_)) ! class From(Node): ! nodes["from"] = "From" ! def __init__(self, modname, names): ! self.modname = modname ! self.names = names def getChildren(self): ! return self.modname, self.names def getChildNodes(self): return () def __repr__(self): ! return "From(%s, %s)" % (repr(self.modname), repr(self.names)) ! ! class Function(Node): ! nodes["function"] = "Function" ! def __init__(self, decorators, name, argnames, defaults, flags, doc, code): ! self.decorators = decorators ! self.name = name ! self.argnames = argnames ! self.defaults = defaults ! self.flags = flags ! self.doc = doc ! self.code = code ! self.varargs = self.kwargs = None ! if flags & CO_VARARGS: ! self.varargs = 1 ! if flags & CO_VARKEYWORDS: ! self.kwargs = 1 ! def getChildren(self): children = [] ! if self.decorators: ! children.append(flatten(self.decorators.nodes)) ! children.append(self.name) ! children.append(self.argnames) ! children.extend(flatten(self.defaults)) ! children.append(self.flags) ! children.append(self.doc) ! children.append(self.code) return tuple(children) def getChildNodes(self): nodelist = [] ! if self.decorators: ! nodelist.extend(flatten_nodes(self.decorators.nodes)) ! nodelist.extend(flatten_nodes(self.defaults)) ! nodelist.append(self.code) return tuple(nodelist) def __repr__(self): ! return "Function(%s, %s, %s, %s, %s, %s, %s)" % (repr(self.decorators), repr(self.name), repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.doc), repr(self.code)) ! ! class GenExpr(Node): ! nodes["genexpr"] = "GenExpr" ! def __init__(self, code): ! self.code = code ! self.argnames = ['[outmost-iterable]'] ! self.varargs = self.kwargs = None ! def getChildren(self): ! return self.code, def getChildNodes(self): ! return self.code, def __repr__(self): ! return "GenExpr(%s)" % (repr(self.code),) ! ! class GenExprFor(Node): ! nodes["genexprfor"] = "GenExprFor" ! def __init__(self, assign, iter, ifs): ! self.assign = assign ! self.iter = iter ! self.ifs = ifs ! self.is_outmost = False def getChildren(self): ! children = [] ! children.append(self.assign) ! children.append(self.iter) ! children.extend(flatten(self.ifs)) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.append(self.assign) ! nodelist.append(self.iter) ! nodelist.extend(flatten_nodes(self.ifs)) ! return tuple(nodelist) def __repr__(self): ! return "GenExprFor(%s, %s, %s)" % (repr(self.assign), repr(self.iter), repr(self.ifs)) ! class GenExprIf(Node): ! nodes["genexprif"] = "GenExprIf" ! def __init__(self, test): ! self.test = test def getChildren(self): ! return self.test, def getChildNodes(self): ! return self.test, def __repr__(self): ! return "GenExprIf(%s)" % (repr(self.test),) ! class GenExprInner(Node): ! nodes["genexprinner"] = "GenExprInner" ! def __init__(self, expr, quals): ! self.expr = expr ! self.quals = quals def getChildren(self): children = [] ! children.append(self.expr) ! children.extend(flatten(self.quals)) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.append(self.expr) ! nodelist.extend(flatten_nodes(self.quals)) return tuple(nodelist) def __repr__(self): ! return "GenExprInner(%s, %s)" % (repr(self.expr), repr(self.quals)) ! class Getattr(Node): ! nodes["getattr"] = "Getattr" ! def __init__(self, expr, attrname): ! self.expr = expr ! self.attrname = attrname def getChildren(self): ! return self.expr, self.attrname def getChildNodes(self): ! return self.expr, def __repr__(self): ! return "Getattr(%s, %s)" % (repr(self.expr), repr(self.attrname)) ! class Global(Node): ! nodes["global"] = "Global" ! def __init__(self, names): ! self.names = names def getChildren(self): ! return self.names, def getChildNodes(self): ! return () def __repr__(self): ! return "Global(%s)" % (repr(self.names),) ! class If(Node): ! nodes["if"] = "If" ! def __init__(self, tests, else_): ! self.tests = tests ! self.else_ = else_ def getChildren(self): children = [] ! children.extend(flatten(self.tests)) ! children.append(self.else_) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.tests)) ! if self.else_ is not None: nodelist.append(self.else_) return tuple(nodelist) def __repr__(self): ! return "If(%s, %s)" % (repr(self.tests), repr(self.else_)) ! class Import(Node): ! nodes["import"] = "Import" ! def __init__(self, names): ! self.names = names ! ! def getChildren(self): ! return self.names, ! ! def getChildNodes(self): ! return () ! ! def __repr__(self): ! return "Import(%s)" % (repr(self.names),) ! ! class Invert(Node): ! nodes["invert"] = "Invert" ! def __init__(self, expr): self.expr = expr def getChildren(self): ! return self.expr, def getChildNodes(self): return self.expr, def __repr__(self): ! return "Invert(%s)" % (repr(self.expr),) class Keyword(Node): nodes["keyword"] = "Keyword" *************** *** 771,791 **** def __repr__(self): return "Keyword(%s, %s)" % (repr(self.name), repr(self.expr)) ! class AugAssign(Node): ! nodes["augassign"] = "AugAssign" ! def __init__(self, node, op, expr): ! self.node = node ! self.op = op ! self.expr = expr def getChildren(self): ! return self.node, self.op, self.expr def getChildNodes(self): ! return self.node, self.expr def __repr__(self): ! return "AugAssign(%s, %s, %s)" % (repr(self.node), repr(self.op), repr(self.expr)) class List(Node): nodes["list"] = "List" --- 773,824 ---- def __repr__(self): return "Keyword(%s, %s)" % (repr(self.name), repr(self.expr)) ! class Lambda(Node): ! nodes["lambda"] = "Lambda" ! def __init__(self, argnames, defaults, flags, code): ! self.argnames = argnames ! self.defaults = defaults ! self.flags = flags ! self.code = code ! self.varargs = self.kwargs = None ! if flags & CO_VARARGS: ! self.varargs = 1 ! if flags & CO_VARKEYWORDS: ! self.kwargs = 1 ! ! def getChildren(self): ! children = [] ! children.append(self.argnames) ! children.extend(flatten(self.defaults)) ! children.append(self.flags) ! children.append(self.code) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.extend(flatten_nodes(self.defaults)) ! nodelist.append(self.code) ! return tuple(nodelist) def __repr__(self): ! return "Lambda(%s, %s, %s, %s)" % (repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.code)) ! ! class LeftShift(Node): ! nodes["leftshift"] = "LeftShift" ! def __init__(self, (left, right)): ! self.left = left ! self.right = right ! ! def getChildren(self): ! return self.left, self.right ! ! def getChildNodes(self): ! return self.left, self.right ! ! def __repr__(self): ! return "LeftShift((%s, %s))" % (repr(self.left), repr(self.right)) class List(Node): nodes["list"] = "List" *************** *** 805,826 **** def __repr__(self): return "List(%s)" % (repr(self.nodes),) ! class Yield(Node): ! nodes["yield"] = "Yield" ! def __init__(self, value): ! self.value = value def getChildren(self): ! return self.value, def getChildNodes(self): ! return self.value, def __repr__(self): ! return "Yield(%s)" % (repr(self.value),) ! class LeftShift(Node): ! nodes["leftshift"] = "LeftShift" def __init__(self, (left, right)): self.left = left self.right = right --- 838,904 ---- def __repr__(self): return "List(%s)" % (repr(self.nodes),) ! class ListComp(Node): ! nodes["listcomp"] = "ListComp" ! def __init__(self, expr, quals): ! self.expr = expr ! self.quals = quals def getChildren(self): ! children = [] ! children.append(self.expr) ! children.extend(flatten(self.quals)) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.append(self.expr) ! nodelist.extend(flatten_nodes(self.quals)) ! return tuple(nodelist) def __repr__(self): ! return "ListComp(%s, %s)" % (repr(self.expr), repr(self.quals)) ! class ListCompFor(Node): ! nodes["listcompfor"] = "ListCompFor" ! def __init__(self, assign, list, ifs): ! self.assign = assign ! self.list = list ! self.ifs = ifs ! ! def getChildren(self): ! children = [] ! children.append(self.assign) ! children.append(self.list) ! children.extend(flatten(self.ifs)) ! return tuple(children) ! ! def getChildNodes(self): ! nodelist = [] ! nodelist.append(self.assign) ! nodelist.append(self.list) ! nodelist.extend(flatten_nodes(self.ifs)) ! return tuple(nodelist) ! ! def __repr__(self): ! return "ListCompFor(%s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.ifs)) ! ! class ListCompIf(Node): ! nodes["listcompif"] = "ListCompIf" ! def __init__(self, test): ! self.test = test ! ! def getChildren(self): ! return self.test, ! ! def getChildNodes(self): ! return self.test, ! ! def __repr__(self): ! return "ListCompIf(%s)" % (repr(self.test),) ! ! class Mod(Node): ! nodes["mod"] = "Mod" def __init__(self, (left, right)): self.left = left self.right = right *************** *** 832,894 **** return self.left, self.right def __repr__(self): ! return "LeftShift((%s, %s))" % (repr(self.left), repr(self.right)) ! class AssName(Node): ! nodes["assname"] = "AssName" ! def __init__(self, name, flags): ! self.name = name ! self.flags = flags def getChildren(self): ! return self.name, self.flags def getChildNodes(self): ! return () def __repr__(self): ! return "AssName(%s, %s)" % (repr(self.name), repr(self.flags)) ! class While(Node): ! nodes["while"] = "While" ! def __init__(self, test, body, else_): ! self.test = test ! self.body = body ! self.else_ = else_ def getChildren(self): ! children = [] ! children.append(self.test) ! children.append(self.body) ! children.append(self.else_) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.append(self.test) ! nodelist.append(self.body) ! if self.else_ is not None: nodelist.append(self.else_) ! return tuple(nodelist) def __repr__(self): ! return "While(%s, %s, %s)" % (repr(self.test), repr(self.body), repr(self.else_)) ! class Continue(Node): ! nodes["continue"] = "Continue" ! def __init__(self, ): ! pass def getChildren(self): ! return () def getChildNodes(self): return () def __repr__(self): ! return "Continue()" ! class Backquote(Node): ! nodes["backquote"] = "Backquote" def __init__(self, expr): self.expr = expr --- 910,963 ---- return self.left, self.right def __repr__(self): ! return "Mod((%s, %s))" % (repr(self.left), repr(self.right)) ! class Module(Node): ! nodes["module"] = "Module" ! def __init__(self, doc, node): ! self.doc = doc ! self.node = node def getChildren(self): ! return self.doc, self.node def getChildNodes(self): ! return self.node, def __repr__(self): ! return "Module(%s, %s)" % (repr(self.doc), repr(self.node)) ! class Mul(Node): ! nodes["mul"] = "Mul" ! def __init__(self, (left, right)): ! self.left = left ! self.right = right def getChildren(self): ! return self.left, self.right def getChildNodes(self): ! return self.left, self.right def __repr__(self): ! return "Mul((%s, %s))" % (repr(self.left), repr(self.right)) ! class Name(Node): ! nodes["name"] = "Name" ! def __init__(self, name): ! self.name = name def getChildren(self): ! return self.name, def getChildNodes(self): return () def __repr__(self): ! return "Name(%s)" % (repr(self.name),) ! class Not(Node): ! nodes["not"] = "Not" def __init__(self, expr): self.expr = expr *************** *** 899,922 **** return self.expr, def __repr__(self): ! return "Backquote(%s)" % (repr(self.expr),) ! class Discard(Node): ! nodes["discard"] = "Discard" ! def __init__(self, expr): ! self.expr = expr def getChildren(self): ! return self.expr, def getChildNodes(self): ! return self.expr, def __repr__(self): ! return "Discard(%s)" % (repr(self.expr),) ! class Div(Node): ! nodes["div"] = "Div" def __init__(self, (left, right)): self.left = left self.right = right --- 968,1009 ---- return self.expr, def __repr__(self): ! return "Not(%s)" % (repr(self.expr),) ! class Or(Node): ! nodes["or"] = "Or" ! def __init__(self, nodes): ! self.nodes = nodes def getChildren(self): ! children = [] ! children.extend(flatten(self.nodes)) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) ! return tuple(nodelist) def __repr__(self): ! return "Or(%s)" % (repr(self.nodes),) ! class Pass(Node): ! nodes["pass"] = "Pass" ! def __init__(self, ): ! pass ! ! def getChildren(self): ! return () ! ! def getChildNodes(self): ! return () ! ! def __repr__(self): ! return "Pass()" ! ! class Power(Node): ! nodes["power"] = "Power" def __init__(self, (left, right)): self.left = left self.right = right *************** *** 928,1046 **** return self.left, self.right def __repr__(self): ! return "Div((%s, %s))" % (repr(self.left), repr(self.right)) ! class Assign(Node): ! nodes["assign"] = "Assign" ! def __init__(self, nodes, expr): self.nodes = nodes ! self.expr = expr def getChildren(self): children = [] children.extend(flatten(self.nodes)) ! children.append(self.expr) return tuple(children) def getChildNodes(self): nodelist = [] nodelist.extend(flatten_nodes(self.nodes)) ! nodelist.append(self.expr) return tuple(nodelist) def __repr__(self): ! return "Assign(%s, %s)" % (repr(self.nodes), repr(self.expr)) ! ! class Lambda(Node): ! nodes["lambda"] = "Lambda" ! def __init__(self, argnames, defaults, flags, code): ! self.argnames = argnames ! self.defaults = defaults ! self.flags = flags ! self.code = code ! self.varargs = self.kwargs = None ! if flags & CO_VARARGS: ! self.varargs = 1 ! if flags & CO_VARKEYWORDS: ! self.kwargs = 1 def getChildren(self): children = [] ! children.append(self.argnames) ! children.extend(flatten(self.defaults)) ! children.append(self.flags) ! children.append(self.code) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.defaults)) ! nodelist.append(self.code) return tuple(nodelist) def __repr__(self): ! return "Lambda(%s, %s, %s, %s)" % (repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.code)) ! class And(Node): ! nodes["and"] = "And" ! def __init__(self, nodes): ! self.nodes = nodes def getChildren(self): children = [] ! children.extend(flatten(self.nodes)) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) return tuple(nodelist) def __repr__(self): ! return "And(%s)" % (repr(self.nodes),) ! class Compare(Node): ! nodes["compare"] = "Compare" ! def __init__(self, expr, ops): ! self.expr = expr ! self.ops = ops def getChildren(self): ! children = [] ! children.append(self.expr) ! children.extend(flatten(self.ops)) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.append(self.expr) ! nodelist.extend(flatten_nodes(self.ops)) ! return tuple(nodelist) def __repr__(self): ! return "Compare(%s, %s)" % (repr(self.expr), repr(self.ops)) ! class Bitor(Node): ! nodes["bitor"] = "Bitor" ! def __init__(self, nodes): ! self.nodes = nodes def getChildren(self): children = [] ! children.extend(flatten(self.nodes)) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) return tuple(nodelist) def __repr__(self): ! return "Bitor(%s)" % (repr(self.nodes),) ! class Bitxor(Node): ! nodes["bitxor"] = "Bitxor" def __init__(self, nodes): self.nodes = nodes --- 1015,1145 ---- return self.left, self.right def __repr__(self): ! return "Power((%s, %s))" % (repr(self.left), repr(self.right)) ! class Print(Node): ! nodes["print"] = "Print" ! def __init__(self, nodes, dest): self.nodes = nodes ! self.dest = dest def getChildren(self): children = [] children.extend(flatten(self.nodes)) ! children.append(self.dest) return tuple(children) def getChildNodes(self): nodelist = [] nodelist.extend(flatten_nodes(self.nodes)) ! if self.dest is not None: nodelist.append(self.dest) return tuple(nodelist) def __repr__(self): ! return "Print(%s, %s)" % (repr(self.nodes), repr(self.dest)) + class Printnl(Node): + nodes["printnl"] = "Printnl" + def __init__(self, nodes, dest): + self.nodes = nodes + self.dest = dest def getChildren(self): children = [] ! children.extend(flatten(self.nodes)) ! children.append(self.dest) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) ! if self.dest is not None: nodelist.append(self.dest) return tuple(nodelist) def __repr__(self): ! return "Printnl(%s, %s)" % (repr(self.nodes), repr(self.dest)) ! class Raise(Node): ! nodes["raise"] = "Raise" ! def __init__(self, expr1, expr2, expr3): ! self.expr1 = expr1 ! self.expr2 = expr2 ! self.expr3 = expr3 def getChildren(self): children = [] ! children.append(self.expr1) ! children.append(self.expr2) ! children.append(self.expr3) return tuple(children) def getChildNodes(self): nodelist = [] ! if self.expr1 is not None: nodelist.append(self.expr1) ! if self.expr2 is not None: nodelist.append(self.expr2) ! if self.expr3 is not None: nodelist.append(self.expr3) return tuple(nodelist) def __repr__(self): ! return "Raise(%s, %s, %s)" % (repr(self.expr1), repr(self.expr2), repr(self.expr3)) ! class Return(Node): ! nodes["return"] = "Return" ! def __init__(self, value): ! self.value = value def getChildren(self): ! return self.value, def getChildNodes(self): ! return self.value, def __repr__(self): ! return "Return(%s)" % (repr(self.value),) ! class RightShift(Node): ! nodes["rightshift"] = "RightShift" ! def __init__(self, (left, right)): ! self.left = left ! self.right = right ! ! def getChildren(self): ! return self.left, self.right ! ! def getChildNodes(self): ! return self.left, self.right ! ! def __repr__(self): ! return "RightShift((%s, %s))" % (repr(self.left), repr(self.right)) ! ! class Slice(Node): ! nodes["slice"] = "Slice" ! def __init__(self, expr, flags, lower, upper): ! self.expr = expr ! self.flags = flags ! self.lower = lower ! self.upper = upper def getChildren(self): children = [] ! children.append(self.expr) ! children.append(self.flags) ! children.append(self.lower) ! children.append(self.upper) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.append(self.expr) ! if self.lower is not None: nodelist.append(self.lower) ! if self.upper is not None: nodelist.append(self.upper) return tuple(nodelist) def __repr__(self): ! return "Slice(%s, %s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.lower), repr(self.upper)) ! class Sliceobj(Node): ! nodes["sliceobj"] = "Sliceobj" def __init__(self, nodes): self.nodes = nodes *************** *** 1055,1131 **** return tuple(nodelist) def __repr__(self): ! return "Bitxor(%s)" % (repr(self.nodes),) ! class CallFunc(Node): ! nodes["callfunc"] = "CallFunc" ! def __init__(self, node, args, star_args = None, dstar_args = None): ! self.node = node ! self.args = args ! self.star_args = star_args ! self.dstar_args = dstar_args def getChildren(self): children = [] ! children.append(self.node) ! children.extend(flatten(self.args)) ! children.append(self.star_args) ! children.append(self.dstar_args) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.append(self.node) ! nodelist.extend(flatten_nodes(self.args)) ! if self.star_args is not None: nodelist.append(self.star_args) ! if self.dstar_args is not None: nodelist.append(self.dstar_args) return tuple(nodelist) def __repr__(self): ! return "CallFunc(%s, %s, %s, %s)" % (repr(self.node), repr(self.args), repr(self.star_args), repr(self.dstar_args)) ! ! class Global(Node): ! nodes["global"] = "Global" ! def __init__(self, names): ! self.names = names ! ! def getChildren(self): ! return self.names, ! ! def getChildNodes(self): ! return () ! ! def __repr__(self): ! return "Global(%s)" % (repr(self.names),) ! ! class Add(Node): ! nodes["add"] = "Add" ! def __init__(self, (left, right)): ! self.left = left ! self.right = right ! ! def getChildren(self): ! return self.left, self.right ! ! def getChildNodes(self): ! return self.left, self.right ! ! def __repr__(self): ! return "Add((%s, %s))" % (repr(self.left), repr(self.right)) ! ! class ListCompIf(Node): ! nodes["listcompif"] = "ListCompIf" ! def __init__(self, test): ! self.test = test ! ! def getChildren(self): ! return self.test, ! ! def getChildNodes(self): ! return self.test, ! ! def __repr__(self): ! return "ListCompIf(%s)" % (repr(self.test),) class Sub(Node): nodes["sub"] = "Sub" --- 1154,1178 ---- return tuple(nodelist) def __repr__(self): ! return "Sliceobj(%s)" % (repr(self.nodes),) ! class Stmt(Node): ! nodes["stmt"] = "Stmt" ! def __init__(self, nodes): ! self.nodes = nodes def getChildren(self): children = [] ! children.extend(flatten(self.nodes)) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) return tuple(nodelist) def __repr__(self): ! return "Stmt(%s)" % (repr(self.nodes),) class Sub(Node): nodes["sub"] = "Sub" *************** *** 1142,1316 **** def __repr__(self): return "Sub((%s, %s))" % (repr(self.left), repr(self.right)) ! class Pass(Node): ! nodes["pass"] = "Pass" ! def __init__(self, ): ! pass ! ! def getChildren(self): ! return () ! ! def getChildNodes(self): ! return () ! ! def __repr__(self): ! return "Pass()" ! ! class UnarySub(Node): ! nodes["unarysub"] = "UnarySub" ! def __init__(self, expr): self.expr = expr def getChildren(self): ! return self.expr, def getChildNodes(self): ! return self.expr, def __repr__(self): ! return "UnarySub(%s)" % (repr(self.expr),) ! class If(Node): ! nodes["if"] = "If" ! def __init__(self, tests, else_): ! self.tests = tests self.else_ = else_ def getChildren(self): children = [] ! children.extend(flatten(self.tests)) children.append(self.else_) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.tests)) if self.else_ is not None: nodelist.append(self.else_) return tuple(nodelist) def __repr__(self): ! return "If(%s, %s)" % (repr(self.tests), repr(self.else_)) ! class ListComp(Node): ! nodes["listcomp"] = "ListComp" ! def __init__(self, expr, quals): ! self.expr = expr ! self.quals = quals def getChildren(self): ! children = [] ! children.append(self.expr) ! children.extend(flatten(self.quals)) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.append(self.expr) ! nodelist.extend(flatten_nodes(self.quals)) ! return tuple(nodelist) def __repr__(self): ! return "ListComp(%s, %s)" % (repr(self.expr), repr(self.quals)) ! class ListCompFor(Node): ! nodes["listcompfor"] = "ListCompFor" ! def __init__(self, assign, list, ifs): ! self.assign = assign ! self.list = list ! self.ifs = ifs def getChildren(self): children = [] ! children.append(self.assign) ! children.append(self.list) ! children.extend(flatten(self.ifs)) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.append(self.assign) ! nodelist.append(self.list) ! nodelist.extend(flatten_nodes(self.ifs)) return tuple(nodelist) def __repr__(self): ! return "ListCompFor(%s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.ifs)) ! class GenExpr(Node): ! nodes["genexpr"] = "GenExpr" ! def __init__(self, code): ! self.code = code ! self.argnames = ['[outmost-iterable]'] ! self.varargs = self.kwargs = None def getChildren(self): ! return self.code, def getChildNodes(self): ! return self.code, def __repr__(self): ! return "GenExpr(%s)" % (repr(self.code),) ! class GenExprInner(Node): ! nodes["genexprinner"] = "GenExprInner" ! def __init__(self, expr, quals): self.expr = expr - self.quals = quals def getChildren(self): ! children = [] ! children.append(self.expr) ! children.extend(flatten(self.quals)) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.append(self.expr) ! nodelist.extend(flatten_nodes(self.quals)) ! return tuple(nodelist) def __repr__(self): ! return "GenExprInner(%s, %s)" % (repr(self.expr), repr(self.quals)) ! class GenExprFor(Node): ! nodes["genexprfor"] = "GenExprFor" ! def __init__(self, assign, iter, ifs): ! self.assign = assign ! self.iter = iter ! self.ifs = ifs ! self.is_outmost = False def getChildren(self): children = [] ! children.append(self.assign) ! children.append(self.iter) ! children.extend(flatten(self.ifs)) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.append(self.assign) ! nodelist.append(self.iter) ! nodelist.extend(flatten_nodes(self.ifs)) return tuple(nodelist) def __repr__(self): ! return "GenExprFor(%s, %s, %s)" % (repr(self.assign), repr(self.iter), repr(self.ifs)) ! class GenExprIf(Node): ! nodes["genexprif"] = "GenExprIf" ! def __init__(self, test): ! self.test = test def getChildren(self): ! return self.test, def getChildNodes(self): ! return self.test, def __repr__(self): ! return "GenExprIf(%s)" % (repr(self.test),) klasses = globals() for k in nodes.keys(): --- 1189,1339 ---- def __repr__(self): return "Sub((%s, %s))" % (repr(self.left), repr(self.right)) ! class Subscript(Node): ! nodes["subscript"] = "Subscript" ! def __init__(self, expr, flags, subs): self.expr = expr + self.flags = flags + self.subs = subs def getChildren(self): ! children = [] ! children.append(self.expr) ! children.append(self.flags) ! children.extend(flatten(self.subs)) ! return tuple(children) def getChildNodes(self): ! nodelist = [] ! nodelist.append(self.expr) ! nodelist.extend(flatten_nodes(self.subs)) ! return tuple(nodelist) def __repr__(self): ! return "Subscript(%s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.subs)) ! class TryExcept(Node): ! nodes["tryexcept"] = "TryExcept" ! def __init__(self, body, handlers, else_): ! self.body = body ! self.handlers = handlers self.else_ = else_ def getChildren(self): children = [] ! children.append(self.body) ! children.extend(flatten(self.handlers)) children.append(self.else_) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.append(self.body) ! nodelist.extend(flatten_nodes(self.handlers)) if self.else_ is not None: nodelist.append(self.else_) return tuple(nodelist) def __repr__(self): ! return "TryExcept(%s, %s, %s)" % (repr(self.body), repr(self.handlers), repr(self.else_)) ! class TryFinally(Node): ! nodes["tryfinally"] = "TryFinally" ! def __init__(self, body, final): ! self.body = body ! self.final = final def getChildren(self): ! return self.body, self.final def getChildNodes(self): ! return self.body, self.final def __repr__(self): ! return "TryFinally(%s, %s)" % (repr(self.body), repr(self.final)) ! class Tuple(Node): ! nodes["tuple"] = "Tuple" ! def __init__(self, nodes): ! self.nodes = nodes def getChildren(self): children = [] ! children.extend(flatten(self.nodes)) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.extend(flatten_nodes(self.nodes)) return tuple(nodelist) def __repr__(self): ! return "Tuple(%s)" % (repr(self.nodes),) ! class UnaryAdd(Node): ! nodes["unaryadd"] = "UnaryAdd" ! def __init__(self, expr): ! self.expr = expr def getChildren(self): ! return self.expr, def getChildNodes(self): ! return self.expr, def __repr__(self): ! return "UnaryAdd(%s)" % (repr(self.expr),) ! class UnarySub(Node): ! nodes["unarysub"] = "UnarySub" ! def __init__(self, expr): self.expr = expr def getChildren(self): ! return self.expr, def getChildNodes(self): ! return self.expr, def __repr__(self): ! return "UnarySub(%s)" % (repr(self.expr),) ! class While(Node): ! nodes["while"] = "While" ! def __init__(self, test, body, else_): ! self.test = test ! self.body = body ! self.else_ = else_ def getChildren(self): children = [] ! children.append(self.test) ! children.append(self.body) ! children.append(self.else_) return tuple(children) def getChildNodes(self): nodelist = [] ! nodelist.append(self.test) ! nodelist.append(self.body) ! if self.else_ is not None: nodelist.append(self.else_) return tuple(nodelist) def __repr__(self): ! return "While(%s, %s, %s)" % (repr(self.test), repr(self.body), repr(self.else_)) ! class Yield(Node): ! nodes["yield"] = "Yield" ! def __init__(self, value): ! self.value = value def getChildren(self): ! return self.value, def getChildNodes(self): ! return self.value, def __repr__(self): ! return "Yield(%s)" % (repr(self.value),) klasses = globals() for k in nodes.keys(): Index: Lib/compiler/pycodegen.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/compiler/pycodegen.py,v retrieving revision 1.68 diff -c -r1.68 pycodegen.py *** Lib/compiler/pycodegen.py 7 Jul 2004 20:54:46 -0000 1.68 --- Lib/compiler/pycodegen.py 1 Aug 2004 12:55:08 -0000 *************** *** 366,371 **** --- 366,378 ---- self._visitFuncOrLambda(node, isLambda=1) def _visitFuncOrLambda(self, node, isLambda=0): + if not isLambda and node.decorators: + for decorator in reversed(node.decorators.nodes): + self.visit(decorator) + ndecorators = len(node.decorators.nodes) + else: + ndecorators = 0 + gen = self.FunctionGen(node, self.scopes, isLambda, self.class_name, self.get_module()) walk(node.code, gen) *************** *** 382,387 **** --- 389,397 ---- else: self.emit('LOAD_CONST', gen) self.emit('MAKE_FUNCTION', len(node.defaults)) + + for i in range(ndecorators): + self.emit('CALL_FUNCTION', 1) def visitClass(self, node): gen = self.ClassGen(node, self.scopes, Index: Lib/compiler/symbols.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/compiler/symbols.py,v retrieving revision 1.15 diff -c -r1.15 symbols.py *** Lib/compiler/symbols.py 7 Jul 2004 20:54:47 -0000 1.15 --- Lib/compiler/symbols.py 1 Aug 2004 12:55:08 -0000 *************** *** 224,229 **** --- 224,231 ---- visitExpression = visitModule def visitFunction(self, node, parent): + if node.decorators: + self.visit(node.decorators, parent) parent.add_def(node.name) for n in node.defaults: self.visit(n, parent) Index: Lib/compiler/transformer.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/compiler/transformer.py,v retrieving revision 1.40 diff -c -r1.40 transformer.py *** Lib/compiler/transformer.py 12 Jul 2004 13:15:56 -0000 1.40 --- Lib/compiler/transformer.py 1 Aug 2004 12:55:09 -0000 *************** *** 185,213 **** ### is this sufficient? return Expression(self.com_node(nodelist[0])) def funcdef(self, nodelist): ! # funcdef: 'def' NAME parameters ':' suite # parameters: '(' [varargslist] ')' ! lineno = nodelist[1][2] ! name = nodelist[1][1] ! args = nodelist[2][2] if args[0] == symbol.varargslist: names, defaults, flags = self.com_arglist(args[1:]) else: names = defaults = () flags = 0 ! doc = self.get_docstring(nodelist[4]) # code for function ! code = self.com_node(nodelist[4]) if doc is not None: assert isinstance(code, Stmt) assert isinstance(code.nodes[0], Discard) del code.nodes[0] ! n = Function(name, names, defaults, flags, doc, code) n.lineno = lineno return n --- 185,265 ---- ### is this sufficient? return Expression(self.com_node(nodelist[0])) + def decorator_name(self, nodelist): + listlen = len(nodelist) + assert listlen >= 1 and listlen % 2 == 1 + + item = self.atom_name(nodelist) + i = 1 + while i < listlen: + assert nodelist[i][0] == token.DOT + assert nodelist[i + 1][0] == token.NAME + item = Getattr(item, nodelist[i + 1][1]) + i += 2 + + return item + + def decorator(self, nodelist): + # '@' dotted_name [ '(' [arglist] ')' ] + assert len(nodelist) in (2, 4, 5) + assert nodelist[0][0] == token.AT + + assert nodelist[1][0] == symbol.dotted_name + funcname = self.decorator_name(nodelist[1][1:]) + + if len(nodelist) > 2: + assert nodelist[2][0] == token.LPAR + expr = self.com_call_function(funcname, nodelist[3]) + else: + expr = funcname + + return expr + + def decorators(self, nodelist): + # decorators: decorator ([NEWLINE] decorator)* NEWLINE + listlen = len(nodelist) + i = 0 + items = [] + while i < listlen: + assert nodelist[i][0] == symbol.decorator + items.append(self.decorator(nodelist[i][1:])) + i += 1 + + if i < listlen and nodelist[i][0] == token.NEWLINE: + i += 1 + return Decorators(items) + def funcdef(self, nodelist): ! # -6 -5 -4 -3 -2 -1 ! # funcdef: [decorators] 'def' NAME parameters ':' suite # parameters: '(' [varargslist] ')' ! if len(nodelist) == 6: ! assert nodelist[0][0] == symbol.decorators ! decorators = self.decorators(nodelist[0][1:]) ! else: ! assert len(nodelist) == 5 ! decorators = None ! ! lineno = nodelist[-4][2] ! name = nodelist[-4][1] ! args = nodelist[-3][2] if args[0] == symbol.varargslist: names, defaults, flags = self.com_arglist(args[1:]) else: names = defaults = () flags = 0 ! doc = self.get_docstring(nodelist[-1]) # code for function ! code = self.com_node(nodelist[-1]) if doc is not None: assert isinstance(code, Stmt) assert isinstance(code.nodes[0], Discard) del code.nodes[0] ! n = Function(decorators, name, names, defaults, flags, doc, code) n.lineno = lineno return n Index: Lib/test/test_parser.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_parser.py,v retrieving revision 1.18 diff -c -r1.18 test_parser.py *** Lib/test/test_parser.py 19 May 2004 08:20:09 -0000 1.18 --- Lib/test/test_parser.py 1 Aug 2004 12:55:09 -0000 *************** *** 15,22 **** t = st1.totuple() try: st2 = parser.sequence2st(t) ! except parser.ParserError: ! self.fail("could not roundtrip %r" % s) self.assertEquals(t, st2.totuple(), "could not re-generate syntax tree") --- 15,22 ---- t = st1.totuple() try: st2 = parser.sequence2st(t) ! except parser.ParserError, why: ! self.fail("could not roundtrip %r: %s" % (s, why)) self.assertEquals(t, st2.totuple(), "could not re-generate syntax tree") *************** *** 119,124 **** --- 119,132 ---- self.check_suite("def f(a, b, foo=bar, *args, **kw): pass") self.check_suite("def f(a, b, foo=bar, **kw): pass") + self.check_suite("@staticmethod\n" + "def f(): pass") + self.check_suite("@staticmethod\n" + "@funcattrs(x, y)\n" + "def f(): pass") + self.check_suite("@funcattrs()\n" + "def f(): pass") + def test_import_from_statement(self): self.check_suite("from sys.path import *") self.check_suite("from sys.path import dirname") Index: Lib/test/test_pyclbr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_pyclbr.py,v retrieving revision 1.21 diff -c -r1.21 test_pyclbr.py *** Lib/test/test_pyclbr.py 18 Jul 2004 00:08:11 -0000 1.21 --- Lib/test/test_pyclbr.py 1 Aug 2004 12:55:09 -0000 *************** *** 8,13 **** --- 8,16 ---- import pyclbr from unittest import TestCase + StaticMethodType = type(staticmethod(lambda: None)) + ClassMethodType = type(classmethod(lambda c: None)) + # This next line triggers an error on old versions of pyclbr. from commands import getstatus *************** *** 43,53 **** print >>sys.stderr, "***",key self.failUnless(obj.has_key(key)) ! def assertEquals(self, a, b, ignore=None): ''' succeed iff a == b or a in ignore or b in ignore ''' ! if (ignore == None) or (a in ignore) or (b in ignore): return ! ! unittest.TestCase.assertEquals(self, a, b) def checkModule(self, moduleName, module=None, ignore=()): ''' succeed iff pyclbr.readmodule_ex(modulename) corresponds --- 46,55 ---- print >>sys.stderr, "***",key self.failUnless(obj.has_key(key)) ! def assertEqualsOrIgnored(self, a, b, ignore): ''' succeed iff a == b or a in ignore or b in ignore ''' ! if a not in ignore and b not in ignore: ! self.assertEquals(a, b) def checkModule(self, moduleName, module=None, ignore=()): ''' succeed iff pyclbr.readmodule_ex(modulename) corresponds *************** *** 62,72 **** dict = pyclbr.readmodule_ex(moduleName) ! def ismethod(obj, name): ! if not isinstance(obj, MethodType): ! return False ! if obj.im_self is not None: ! return False objname = obj.__name__ if objname.startswith("__") and not objname.endswith("__"): objname = "_%s%s" % (obj.im_class.__name__, objname) --- 64,85 ---- dict = pyclbr.readmodule_ex(moduleName) ! def ismethod(oclass, obj, name): ! classdict = oclass.__dict__ ! if isinstance(obj, FunctionType): ! if not isinstance(classdict[name], StaticMethodType): ! return False ! else: ! if not isinstance(obj, MethodType): ! return False ! if obj.im_self is not None: ! if (not isinstance(classdict[name], ClassMethodType) or ! obj.im_self is not oclass): ! return False ! else: ! if not isinstance(classdict[name], FunctionType): ! return False ! objname = obj.__name__ if objname.startswith("__") and not objname.endswith("__"): objname = "_%s%s" % (obj.im_class.__name__, objname) *************** *** 81,87 **** if isinstance(value, pyclbr.Function): self.assertEquals(type(py_item), FunctionType) else: ! self.assertEquals(type(py_item), ClassType) real_bases = [base.__name__ for base in py_item.__bases__] pyclbr_bases = [ getattr(base, 'name', base) for base in value.super ] --- 94,100 ---- if isinstance(value, pyclbr.Function): self.assertEquals(type(py_item), FunctionType) else: ! self.failUnless(isinstance(py_item, (ClassType, type))) real_bases = [base.__name__ for base in py_item.__bases__] pyclbr_bases = [ getattr(base, 'name', base) for base in value.super ] *************** *** 94,100 **** actualMethods = [] for m in py_item.__dict__.keys(): ! if ismethod(getattr(py_item, m), m): actualMethods.append(m) foundMethods = [] for m in value.methods.keys(): --- 107,113 ---- actualMethods = [] for m in py_item.__dict__.keys(): ! if ismethod(py_item, getattr(py_item, m), m): actualMethods.append(m) foundMethods = [] for m in value.methods.keys(): *************** *** 107,113 **** self.assertListEq(foundMethods, actualMethods, ignore) self.assertEquals(py_item.__module__, value.module) ! self.assertEquals(py_item.__name__, value.name, ignore) # can't check file or lineno except: print >>sys.stderr, "class=%s" % py_item --- 120,127 ---- self.assertListEq(foundMethods, actualMethods, ignore) self.assertEquals(py_item.__module__, value.module) ! self.assertEqualsOrIgnored(py_item.__name__, value.name, ! ignore) # can't check file or lineno except: print >>sys.stderr, "class=%s" % py_item *************** *** 132,137 **** --- 146,157 ---- self.checkModule('rfc822') self.checkModule('difflib') + def test_decorators(self): + # XXX: See comment in pyclbr_input.py for a test that would fail + # if it were not commented out. + # + self.checkModule('test.pyclbr_input') + def test_others(self): cm = self.checkModule Index: Lib/test/tokenize_tests.txt =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/tokenize_tests.txt,v retrieving revision 1.1 diff -c -r1.1 tokenize_tests.txt *** Lib/test/tokenize_tests.txt 12 May 2003 19:42:04 -0000 1.1 --- Lib/test/tokenize_tests.txt 1 Aug 2004 12:55:09 -0000 *************** *** 173,175 **** --- 173,178 ---- import sys, time x = sys.modules['time'].time() + @staticmethod + def foo(): pass + Index: Lib/test/output/test_tokenize =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/output/test_tokenize,v retrieving revision 1.8 diff -c -r1.8 test_tokenize *** Lib/test/output/test_tokenize 29 Aug 2002 15:10:30 -0000 1.8 --- Lib/test/output/test_tokenize 1 Aug 2004 12:55:09 -0000 *************** *** 645,648 **** 174,29-174,30: OP ')' 174,30-174,31: NEWLINE '\n' 175,0-175,1: NL '\n' ! 176,0-176,0: ENDMARKER '' --- 645,659 ---- 174,29-174,30: OP ')' 174,30-174,31: NEWLINE '\n' 175,0-175,1: NL '\n' ! 176,0-176,1: OP '@' ! 176,1-176,13: NAME 'staticmethod' ! 176,13-176,14: NEWLINE '\n' ! 177,0-177,3: NAME 'def' ! 177,4-177,7: NAME 'foo' ! 177,7-177,8: OP '(' ! 177,8-177,9: OP ')' ! 177,9-177,10: OP ':' ! 177,11-177,15: NAME 'pass' ! 177,15-177,16: NEWLINE '\n' ! 178,0-178,1: NL '\n' ! 179,0-179,0: ENDMARKER '' Index: Modules/parsermodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/parsermodule.c,v retrieving revision 2.82 diff -c -r2.82 parsermodule.c *** Modules/parsermodule.c 19 May 2004 08:20:13 -0000 2.82 --- Modules/parsermodule.c 1 Aug 2004 12:55:10 -0000 *************** *** 824,829 **** --- 824,830 ---- #define validate_vbar(ch) validate_terminal(ch, VBAR, "|") #define validate_doublestar(ch) validate_terminal(ch, DOUBLESTAR, "**") #define validate_dot(ch) validate_terminal(ch, DOT, ".") + #define validate_at(ch) validate_terminal(ch, AT, "@") #define validate_name(ch, str) validate_terminal(ch, NAME, str) #define VALIDATER(n) static int validate_##n(node *tree) *************** *** 2362,2381 **** return ok; } /* funcdef: ! * 'def' NAME parameters ':' suite ! * */ static int validate_funcdef(node *tree) { ! return (validate_ntype(tree, funcdef) ! && validate_numnodes(tree, 5, "funcdef") ! && validate_name(CHILD(tree, 0), "def") ! && validate_ntype(CHILD(tree, 1), NAME) ! && validate_colon(CHILD(tree, 3)) ! && validate_parameters(CHILD(tree, 2)) ! && validate_suite(CHILD(tree, 4))); } --- 2363,2434 ---- return ok; } + /* decorator: + * '@' dotted_name [ '(' [arglist] ')' ] + */ + static int + validate_decorator(node *tree) + { + int ok; + int nch = NCH(tree); + ok = (validate_ntype(tree, decorator) && + (nch == 2 || nch == 4 || nch == 5) && + validate_at(CHILD(tree, 0)) && + validate_dotted_name(CHILD(tree, 1))); + + if (ok && nch != 2) { + ok = (validate_lparen(CHILD(tree, 2)) && + validate_rparen(RCHILD(tree, -1))); + + if (ok && nch == 5) + ok = validate_arglist(CHILD(tree, 3)); + } + + return ok; + } + + /* decorators: + * decorator ([NEWLINE] decorator)* NEWLINE + */ + static int + validate_decorators(node *tree) + { + int i, nch, ok; + nch = NCH(tree); + ok = validate_ntype(tree, decorators) && nch >= 2; + + i = 0; + while (ok && i < nch - 1) { + ok = validate_decorator(CHILD(tree, i)); + if (TYPE(CHILD(tree, i + 1)) == NEWLINE) + ++i; + ++i; + } + + return ok; + } + /* funcdef: ! * ! * -6 -5 -4 -3 -2 -1 ! * [decorators] 'def' NAME parameters ':' suite */ static int validate_funcdef(node *tree) { ! int nch = NCH(tree); ! int ok = (validate_ntype(tree, funcdef) ! && ((nch == 5) || (nch == 6)) ! && validate_name(RCHILD(tree, -5), "def") ! && validate_ntype(RCHILD(tree, -4), NAME) ! && validate_colon(RCHILD(tree, -2)) ! && validate_parameters(RCHILD(tree, -3)) ! && validate_suite(RCHILD(tree, -1))); ! ! if (ok && (nch == 6)) ! ok = validate_decorators(CHILD(tree, 0)); ! ! return ok; } Index: Parser/tokenizer.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Parser/tokenizer.c,v retrieving revision 2.74 diff -c -r2.74 tokenizer.c *** Parser/tokenizer.c 20 Nov 2003 01:44:58 -0000 2.74 --- Parser/tokenizer.c 1 Aug 2004 12:55:10 -0000 *************** *** 92,97 **** --- 92,98 ---- "DOUBLESTAREQUAL", "DOUBLESLASH", "DOUBLESLASHEQUAL", + "AT", /* This table must match the #defines in token.h! */ "OP", "", *************** *** 847,852 **** --- 848,854 ---- case '}': return RBRACE; case '^': return CIRCUMFLEX; case '~': return TILDE; + case '@': return AT; default: return OP; } } Index: Python/compile.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v retrieving revision 2.309 diff -c -r2.309 compile.c *** Python/compile.c 17 Jul 2004 21:46:24 -0000 2.309 --- Python/compile.c 1 Aug 2004 12:55:11 -0000 *************** *** 1876,1881 **** --- 1876,1882 ---- else com_list(c, n, 0); } + static void com_dictmaker(struct compiling *c, node *n) { *************** *** 3963,3970 **** n = CHILD(n, 1); } else { ! REQ(n, funcdef); /* funcdef: 'def' NAME parameters ... */ ! n = CHILD(n, 2); REQ(n, parameters); /* parameters: '(' [varargslist] ')' */ n = CHILD(n, 1); } --- 3964,3972 ---- n = CHILD(n, 1); } else { ! REQ(n, funcdef); ! /* funcdef: [decorators] 'def' NAME parameters ':' suite */ ! n = RCHILD(n, -3); REQ(n, parameters); /* parameters: '(' [varargslist] ')' */ n = CHILD(n, 1); } *************** *** 4009,4023 **** } static void com_funcdef(struct compiling *c, node *n) { PyObject *co; ! int ndefs; ! REQ(n, funcdef); /* funcdef: 'def' NAME parameters ':' suite */ ndefs = com_argdefs(c, n); if (ndefs < 0) return; ! symtable_enter_scope(c->c_symtable, STR(CHILD(n, 1)), TYPE(n), n->n_lineno); co = (PyObject *)icompile(n, c); symtable_exit_scope(c->c_symtable); --- 4011,4099 ---- } static void + com_decorator_name(struct compiling *c, node *n) + { + /* dotted_name: NAME ('.' NAME)* */ + + int i, nch; + node *varname; + + REQ(n, dotted_name); + nch = NCH(n); + assert(nch >= 1 && nch % 2 == 1); + + varname = CHILD(n, 0); + REQ(varname, NAME); + com_addop_varname(c, VAR_LOAD, STR(varname)); + + for (i = 1; i < nch; i += 2) { + node *attrname; + + REQ(CHILD(n, i), DOT); + + attrname = CHILD(n, i + 1); + REQ(attrname, NAME); + com_addop_name(c, LOAD_ATTR, STR(attrname)); + } + } + + static void + com_decorator(struct compiling *c, node *n) + { + /* decorator: '@' dotted_name [ '(' [arglist] ')' ] */ + int nch = NCH(n); + assert(nch >= 2); + REQ(CHILD(n, 0), AT); + com_decorator_name(c, CHILD(n, 1)); + + if (nch > 2) { + assert(nch == 4 || nch == 5); + REQ(CHILD(n, 2), LPAR); + REQ(CHILD(n, nch - 1), RPAR); + com_call_function(c, CHILD(n, 3)); + } + } + + static int + com_decorators(struct compiling *c, node *n) + { + int i, nch, ndecorators; + + /* decorator ([NEWLINE] decorator)* NEWLINE */ + nch = NCH(n); + assert(nch >= 2); + REQ(CHILD(n, nch - 1), NEWLINE); + + ndecorators = 0; + for (i = NCH(n) - 1; i >= 0; --i) { + node *ch = CHILD(n, i); + if (TYPE(ch) != NEWLINE) { + com_decorator(c, ch); + ++ndecorators; + } + } + + return ndecorators; + } + + static void com_funcdef(struct compiling *c, node *n) { PyObject *co; ! int ndefs, ndecorators; ! REQ(n, funcdef); ! /* -6 -5 -4 -3 -2 -1 ! funcdef: [decorators] 'def' NAME parameters ':' suite */ ! ! if (NCH(n) == 6) ! ndecorators = com_decorators(c, CHILD(n, 0)); ! else ! ndecorators = 0; ! ndefs = com_argdefs(c, n); if (ndefs < 0) return; ! symtable_enter_scope(c->c_symtable, STR(RCHILD(n, -4)), TYPE(n), n->n_lineno); co = (PyObject *)icompile(n, c); symtable_exit_scope(c->c_symtable); *************** *** 4033,4039 **** else com_addoparg(c, MAKE_FUNCTION, ndefs); com_pop(c, ndefs); ! com_addop_varname(c, VAR_STORE, STR(CHILD(n, 1))); com_pop(c, 1); Py_DECREF(co); } --- 4109,4120 ---- else com_addoparg(c, MAKE_FUNCTION, ndefs); com_pop(c, ndefs); ! while (ndecorators > 0) { ! com_addoparg(c, CALL_FUNCTION, 1); ! com_pop(c, 1); ! ndecorators--; ! } ! com_addop_varname(c, VAR_STORE, STR(RCHILD(n, -4))); com_pop(c, 1); Py_DECREF(co); } *************** *** 4112,4118 **** switch (TYPE(n)) { /* Definition nodes */ ! case funcdef: com_funcdef(c, n); break; --- 4193,4199 ---- switch (TYPE(n)) { /* Definition nodes */ ! case funcdef: com_funcdef(c, n); break; *************** *** 4377,4397 **** { PyObject *doc; node *ch; ! REQ(n, funcdef); /* funcdef: 'def' NAME parameters ':' suite */ ! c->c_name = STR(CHILD(n, 1)); ! doc = get_docstring(c, CHILD(n, 4)); if (doc != NULL) { (void) com_addconst(c, doc); Py_DECREF(doc); } else (void) com_addconst(c, Py_None); /* No docstring */ ! ch = CHILD(n, 2); /* parameters: '(' [varargslist] ')' */ ch = CHILD(ch, 1); /* ')' | varargslist */ if (TYPE(ch) == varargslist) com_arglist(c, ch); c->c_infunction = 1; ! com_node(c, CHILD(n, 4)); c->c_infunction = 0; com_strip_lnotab(c); com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None)); --- 4458,4480 ---- { PyObject *doc; node *ch; ! REQ(n, funcdef); ! /* -6 -5 -4 -3 -2 -1 ! funcdef: [decorators] 'def' NAME parameters ':' suite */ ! c->c_name = STR(RCHILD(n, -4)); ! doc = get_docstring(c, RCHILD(n, -1)); if (doc != NULL) { (void) com_addconst(c, doc); Py_DECREF(doc); } else (void) com_addconst(c, Py_None); /* No docstring */ ! ch = RCHILD(n, -3); /* parameters: '(' [varargslist] ')' */ ch = CHILD(ch, 1); /* ')' | varargslist */ if (TYPE(ch) == varargslist) com_arglist(c, ch); c->c_infunction = 1; ! com_node(c, RCHILD(n, -1)); c->c_infunction = 0; com_strip_lnotab(c); com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None)); *************** *** 5587,5595 **** loop: switch (TYPE(n)) { case funcdef: { ! char *func_name = STR(CHILD(n, 1)); symtable_add_def(st, func_name, DEF_LOCAL); ! symtable_default_args(st, CHILD(n, 2)); symtable_enter_scope(st, func_name, TYPE(n), n->n_lineno); symtable_funcdef(st, n); symtable_exit_scope(st); --- 5670,5681 ---- loop: switch (TYPE(n)) { case funcdef: { ! char *func_name; ! if (NCH(n) == 6) ! symtable_node(st, CHILD(n, 0)); ! func_name = STR(RCHILD(n, -4)); symtable_add_def(st, func_name, DEF_LOCAL); ! symtable_default_args(st, RCHILD(n, -3)); symtable_enter_scope(st, func_name, TYPE(n), n->n_lineno); symtable_funcdef(st, n); symtable_exit_scope(st); *************** *** 5734,5739 **** --- 5820,5836 ---- to be coded with great care, even though they look like rather innocuous. Each case must double-check TYPE(n). */ + case decorator: + if (TYPE(n) == decorator) { + /* decorator: '@' dotted_name [ '(' [arglist] ')' ] */ + node *name, *varname; + name = CHILD(n, 1); + REQ(name, dotted_name); + varname = CHILD(name, 0); + REQ(varname, NAME); + symtable_add_use(st, STR(varname)); + } + /* fall through */ case argument: if (TYPE(n) == argument && NCH(n) == 3) { n = CHILD(n, 2); *************** *** 5787,5793 **** if (NCH(n) == 4) symtable_params(st, CHILD(n, 1)); } else ! symtable_params(st, CHILD(n, 2)); body = CHILD(n, NCH(n) - 1); symtable_node(st, body); } --- 5884,5890 ---- if (NCH(n) == 4) symtable_params(st, CHILD(n, 1)); } else ! symtable_params(st, RCHILD(n, -3)); body = CHILD(n, NCH(n) - 1); symtable_node(st, body); } Index: Tools/compiler/ast.txt =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/compiler/ast.txt,v retrieving revision 1.5 diff -c -r1.5 ast.txt *** Tools/compiler/ast.txt 19 May 2004 08:20:33 -0000 1.5 --- Tools/compiler/ast.txt 1 Aug 2004 12:55:11 -0000 *************** *** 8,14 **** # = ... a default value for the node constructor (optional args) Module: doc*, node Stmt: nodes! ! Function: name*, argnames*, defaults!, flags*, doc*, code Lambda: argnames*, defaults!, flags*, code Class: name*, bases!, doc*, code Pass: --- 8,15 ---- # = ... a default value for the node constructor (optional args) Module: doc*, node Stmt: nodes! ! Decorators: nodes! ! Function: decorators&, name*, argnames*, defaults!, flags*, doc*, code Lambda: argnames*, defaults!, flags*, code Class: name*, bases!, doc*, code Pass: Index: Tools/compiler/astgen.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/compiler/astgen.py,v retrieving revision 1.7 diff -c -r1.7 astgen.py *** Tools/compiler/astgen.py 18 Jul 2004 06:02:02 -0000 1.7 --- Tools/compiler/astgen.py 1 Aug 2004 12:55:12 -0000 *************** *** 154,172 **** else: print >> buf, " return %s" % COMMA.join(clist) else: ! print >> buf, " nodes = []" ! template = " nodes.%s(%sself.%s%s)" for name in self.argnames: if self.argprops[name] == P_NONE: tmp = (" if self.%s is not None:" ! " nodes.append(self.%s)") print >> buf, tmp % (name, name) elif self.argprops[name] == P_NESTED: print >> buf, template % ("extend", "flatten_nodes(", name, ")") elif self.argprops[name] == P_NODE: print >> buf, template % ("append", "", name, "") ! print >> buf, " return tuple(nodes)" def _gen_repr(self, buf): print >> buf, " def __repr__(self):" --- 154,172 ---- else: print >> buf, " return %s" % COMMA.join(clist) else: ! print >> buf, " nodelist = []" ! template = " nodelist.%s(%sself.%s%s)" for name in self.argnames: if self.argprops[name] == P_NONE: tmp = (" if self.%s is not None:" ! " nodelist.append(self.%s)") print >> buf, tmp % (name, name) elif self.argprops[name] == P_NESTED: print >> buf, template % ("extend", "flatten_nodes(", name, ")") elif self.argprops[name] == P_NODE: print >> buf, template % ("append", "", name, "") ! print >> buf, " return tuple(nodelist)" def _gen_repr(self, buf): print >> buf, " def __repr__(self):" *************** *** 208,214 **** # some extra code for a Node's __init__ method name = mo.group(1) cur = classes[name] ! return classes.values() def main(): prologue, epilogue = load_boilerplate(sys.argv[-1]) --- 208,214 ---- # some extra code for a Node's __init__ method name = mo.group(1) cur = classes[name] ! return sorted(classes.values(), key=lambda n: n.name) def main(): prologue, epilogue = load_boilerplate(sys.argv[-1]) *************** *** 245,253 **** def flatten_nodes(list): return [n for n in flatten(list) if isinstance(n, Node)] ! def asList(nodes): l = [] ! for item in nodes: if hasattr(item, "asList"): l.append(item.asList()) else: --- 245,253 ---- def flatten_nodes(list): return [n for n in flatten(list) if isinstance(n, Node)] ! def asList(nodearg): l = [] ! for item in nodearg: if hasattr(item, "asList"): l.append(item.asList()) else: *************** *** 274,279 **** --- 274,294 ---- class EmptyNode(Node): pass + class Expression(Node): + # Expression is an artificial node class to support "eval" + nodes["expression"] = "Expression" + def __init__(self, node): + self.node = node + + def getChildren(self): + return self.node, + + def getChildNodes(self): + return self.node, + + def __repr__(self): + return "Expression(%s)" % (repr(self.node)) + ### EPILOGUE klasses = globals() for k in nodes.keys(): Index: Tools/compiler/regrtest.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/compiler/regrtest.py,v retrieving revision 1.4 diff -c -r1.4 regrtest.py *** Tools/compiler/regrtest.py 9 Aug 2002 16:37:36 -0000 1.4 --- Tools/compiler/regrtest.py 1 Aug 2004 12:55:12 -0000 *************** *** 47,52 **** --- 47,54 ---- continue # make sure the .pyc file is not over-written os.chmod(source + "c", 444) + elif file == 'CVS': + pass else: path = os.path.join(dir, file) if os.path.isdir(path): *** /dev/null Sat Nov 15 11:00:11 2003 --- Lib/test/pyclbr_input.py Sun Aug 1 13:41:04 2004 *************** *** 0 **** --- 1,33 ---- + """Test cases for test_pyclbr.py""" + + def f(): pass + + class Other(object): + @classmethod + def foo(c): pass + + def om(self): pass + + class B (object): + def bm(self): pass + + class C (B): + foo = Other().foo + om = Other.om + + d = 10 + + # XXX: This causes test_pyclbr.py to fail, but only because the + # introspection-based is_method() code in the test can't + # distinguish between this and a geniune method function like m(). + # The pyclbr.py module gets this right as it parses the text. + # + #f = f + + def m(self): pass + + @staticmethod + def sm(self): pass + + @classmethod + def cm(self): pass *** /dev/null Sat Nov 15 11:00:11 2003 --- Lib/test/test_decorators.py Sat Jul 31 20:45:38 2004 *************** *** 0 **** --- 1,194 ---- + import unittest + from test import test_support + + def funcattrs(**kwds): + def decorate(func): + func.__dict__.update(kwds) + return func + return decorate + + class MiscDecorators (object): + @staticmethod + def author(name): + def decorate(func): + func.__dict__['author'] = name + return func + return decorate + + # ----------------------------------------------- + + class DbcheckError (Exception): + def __init__(self, exprstr, func, args, kwds): + # A real version of this would set attributes here + Exception.__init__(self, "dbcheck %r failed (func=%s args=%s kwds=%s)" % + (exprstr, func, args, kwds)) + + + def dbcheck(exprstr, globals=None, locals=None): + "Decorator to implement debugging assertions" + def decorate(func): + expr = compile(exprstr, "dbcheck-%s" % func.func_name, "eval") + def check(*args, **kwds): + if not eval(expr, globals, locals): + raise DbcheckError(exprstr, func, args, kwds) + return func(*args, **kwds) + return check + return decorate + + # ----------------------------------------------- + + def countcalls(counts): + "Decorator to count calls to a function" + def decorate(func): + name = func.func_name + counts[name] = 0 + def call(*args, **kwds): + counts[name] += 1 + return func(*args, **kwds) + # XXX: Would like to say: call.func_name = func.func_name here + # to make nested decorators work in any order, but func_name + # is a readonly attribute + return call + return decorate + + # ----------------------------------------------- + + def memoize(func): + saved = {} + def call(*args): + try: + return saved[args] + except KeyError: + res = func(*args) + saved[args] = res + return res + except TypeError: + # Unhashable argument + return func(*args) + return call + + # ----------------------------------------------- + + class TestDecorators(unittest.TestCase): + + def test_single(self): + class C(object): + @staticmethod + def foo(): return 42 + self.assertEqual(C.foo(), 42) + self.assertEqual(C().foo(), 42) + + def test_dotted(self): + decorators = MiscDecorators() + @decorators.author('Cleese') + def foo(): return 42 + self.assertEqual(foo(), 42) + self.assertEqual(foo.author, 'Cleese') + + def test_argforms(self): + # A few tests of argument passing, as we use restricted form + # of expressions for decorators. + + def noteargs(*args, **kwds): + def decorate(func): + setattr(func, 'dbval', (args, kwds)) + return func + return decorate + + args = ( 'Now', 'is', 'the', 'time' ) + kwds = dict(one=1, two=2) + @noteargs(*args, **kwds) + def f1(): return 42 + self.assertEqual(f1(), 42) + self.assertEqual(f1.dbval, (args, kwds)) + + @noteargs('terry', 'gilliam', eric='idle', john='cleese') + def f2(): return 84 + self.assertEqual(f2(), 84) + self.assertEqual(f2.dbval, (('terry', 'gilliam'), + dict(eric='idle', john='cleese'))) + + @noteargs(1, 2,) + def f3(): pass + self.assertEqual(f3.dbval, ((1, 2), {})) + + def test_dbcheck(self): + @dbcheck('args[1] is not None') + def f(a, b): + return a + b + self.assertEqual(f(1, 2), 3) + self.assertRaises(DbcheckError, f, 1, None) + + def test_memoize(self): + # XXX: This doesn't work unless memoize is the last decorator - + # see the comment in countcalls. + counts = {} + @countcalls(counts) @memoize + def double(x): + return x * 2 + + self.assertEqual(counts, dict(double=0)) + + # Only the first call with a given argument bumps the call count: + # + self.assertEqual(double(2), 4) + self.assertEqual(counts['double'], 1) + self.assertEqual(double(2), 4) + self.assertEqual(counts['double'], 1) + self.assertEqual(double(3), 6) + self.assertEqual(counts['double'], 2) + + # Unhashable arguments do not get memoized: + # + self.assertEqual(double([10]), [10, 10]) + self.assertEqual(counts['double'], 3) + self.assertEqual(double([10]), [10, 10]) + self.assertEqual(counts['double'], 4) + + def test_errors(self): + # Test syntax restrictions - these are all compile-time errors: + # + for expr in [ "1+2", "x[3]", "(1, 2)" ]: + # Sanity check: is expr is a valid expression by itself? + compile(expr, "testexpr", "exec") + + codestr = "@%s\ndef f(): pass" % expr + self.assertRaises(SyntaxError, compile, codestr, "test", "exec") + + # Test runtime errors + + def unimp(func): + raise NotImplementedError + context = dict(nullval=None, unimp=unimp) + + for expr, exc in [ ("undef", NameError), + ("nullval", TypeError), + ("nullval.attr", AttributeError), + ("unimp", NotImplementedError)]: + codestr = "@%s\ndef f(): pass\nassert f() is None" % expr + code = compile(codestr, "test", "exec") + self.assertRaises(exc, eval, code, context) + + def test_double(self): + class C(object): + @funcattrs(abc=1, xyz="haha") + @funcattrs(booh=42) + def foo(self): return 42 + self.assertEqual(C().foo(), 42) + self.assertEqual(C.foo.abc, 1) + self.assertEqual(C.foo.xyz, "haha") + self.assertEqual(C.foo.booh, 42) + + def test_order(self): + class C(object): + @funcattrs(abc=1) @staticmethod + def foo(): return 42 + # This wouldn't work if staticmethod was called first + self.assertEqual(C.foo(), 42) + self.assertEqual(C().foo(), 42) + + def test_main(): + test_support.run_unittest(TestDecorators) + + if __name__=="__main__": + test_main()