From 4f05de4365706a1dfd16e2421f8cf750b9d229d6 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Wed, 13 Apr 2011 23:06:23 +0200 Subject: [PATCH] ticket #685: implement no-arg dir() --- Cython/Compiler/ParseTreeTransforms.py | 44 ++++++++++++++++---------- tests/run/locals.pyx | 33 ++++++++++++++++--- 2 files changed, 55 insertions(+), 22 deletions(-) diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index 1e9cf7b1..251ca7dd 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -1750,25 +1750,35 @@ class TransformBuiltinMethods(EnvTransform): error(node.pos, u"'%s' not a valid cython attribute or is being used incorrectly" % attribute) return node - def visit_SimpleCallNode(self, node): + def _inject_locals(self, node, func_name): + # locals()/dir() builtins + lenv = self.current_env() + entry = lenv.lookup_here(func_name) + if entry: + # not the builtin + return node + max_args_count = {'dir': 1, 'locals': 0}[func_name] + if len(node.args) > max_args_count: + error(self.pos, "Builtin '%s()' called with wrong number of args, expected %d, got %d" % ( + func_name, max_args_count, len(node.args))) + return node + pos = node.pos + if func_name =='locals': + items = [ ExprNodes.DictItemNode(pos, + key=ExprNodes.StringNode(pos, value=var), + value=ExprNodes.NameNode(pos, name=var)) + for var in lenv.entries ] + return ExprNodes.DictNode(pos, key_value_pairs=items) + else: + items = [ ExprNodes.StringNode(pos, value=var) + for var in lenv.entries ] + return ExprNodes.ListNode(pos, args=items) - # locals builtin + def visit_SimpleCallNode(self, node): if isinstance(node.function, ExprNodes.NameNode): - if node.function.name == 'locals': - lenv = self.current_env() - entry = lenv.lookup_here('locals') - if entry: - # not the builtin 'locals' - return node - if len(node.args) > 0: - error(self.pos, "Builtin 'locals()' called with wrong number of args, expected 0, got %d" % len(node.args)) - return node - pos = node.pos - items = [ ExprNodes.DictItemNode(pos, - key=ExprNodes.StringNode(pos, value=var), - value=ExprNodes.NameNode(pos, name=var)) - for var in lenv.entries ] - return ExprNodes.DictNode(pos, key_value_pairs=items) + func_name = node.function.name + if func_name in ('dir', 'locals'): + return self._inject_locals(node, func_name) # cython.foo function = node.function.as_cython_attribute() diff --git a/tests/run/locals.pyx b/tests/run/locals.pyx index 6209224a..0da74c20 100644 --- a/tests/run/locals.pyx +++ b/tests/run/locals.pyx @@ -1,14 +1,24 @@ -__doc__ = u""" ->>> sorted( get_locals(1,2,3, k=5) .items()) -[('args', (2, 3)), ('kwds', {'k': 5}), ('x', 1), ('y', 'hi'), ('z', 5)] - -""" +# mode: run +# tag: builtins, locals, dir def get_locals(x, *args, **kwds): + """ + >>> sorted( get_locals(1,2,3, k=5) .items()) + [('args', (2, 3)), ('kwds', {'k': 5}), ('x', 1), ('y', 'hi'), ('z', 5)] + """ cdef int z = 5 y = "hi" return locals() +def get_dir(x, *args, **kwds): + """ + >>> sorted( get_dir(1,2,3, k=5) ) + ['args', 'kwds', 'x', 'y', 'z'] + """ + cdef int z = 5 + y = "hi" + return dir() + def in_locals(x, *args, **kwds): """ >>> in_locals('z') @@ -22,6 +32,19 @@ def in_locals(x, *args, **kwds): y = "hi" return x in locals() +def in_dir(x, *args, **kwds): + """ + >>> in_dir('z') + True + >>> in_dir('args') + True + >>> in_dir('X') + False + """ + cdef int z = 5 + y = "hi" + return x in dir() + def sorted(it): l = list(it) l.sort() -- 2.26.2