Python decorator syntax limitations
Hi all, The following is what I want to do, but this results in a syntax error: @news_page('template.html').lookup(News, 'news_id', 'news') def view(request, group, news): pass What does work is the equivalent old way of doing decorating: def view(request, group, news): pass view = news_page('template.html').lookup(News, 'news_id', 'news') (view) Any suggestions? I have my reasons for doing this, (news_page is a class, and __call__ is used to wrap the template.) I'm sure this is a limitation in the syntax, but would parenthesis somewhere help? Thanks! Jonathan -- http://mail.python.org/mailman/listinfo/python-list
Re: Python decorator syntax limitations
Thanks a lot, all of you! This was really helpful. (or at least give me the inspiration I needed to finish it.) I'm sure this is a use case where most other options are less readable than the chain of methods in the decorator. In this use case, I had a lot of Django views to which access permissions had to be attached. Chaining the permissions was in my opinion the easiest way to go but appeared not to work because Guido had a gut feeling about that. Using multiple decorators in the usual way (like every following wraps the previous) does not work, because these decorators need to access the same authentication class. (little hard to explain, but take from me that I had a case where it didn't work.) Placing all possible options in the constructor method of the decorator like Steve Howell proposed would work but is ugly. This is what I made. I'll upgrade my news_page decorator to work in the following way. (Applying the news_page decorator to 'view', will turn it into a class, but make it callable buy wrapping the actual view in __call__. So we can still apply the other methods to the view. @news_page('template.html') def view(request, group, news): ... pass view.lookup(News, 'news_id', 'news') view.require_administrator() That is still rather ugly, because the 'lookup' option is appended behind the view. I kept playing with the code and came to the following: @require_administrator @do_lookup(News, 'news_id', 'news) @news_page('template.html') def view(request, group, news): ... pass Where 'do_lookup' and 'require_administrator' passes the method, but sets some parameters. So, 'do_lookup' can access class members of news_page. It would look like: def do_lookup(*lookup_options): def set_options(news_page_view): news_page_view.lookup(*lookup_options) return news_page_view return set_options def require_administrator(news_page_view): news_page_view.require_administrator() return news_page_view Maybe, I'll join the discussion later on, when I have time to read all the conversations and write down good arguments. But, honestly, I'm satisfied with the last result. Have a nice day! -- http://mail.python.org/mailman/listinfo/python-list
Replacing globals in exec by custom class
Hi all, I wonder if anyone can explain some weird behaviour in Python. What I'm trying to do is to execute a string of python code through the 'exec' statement. I pass an instance of my Global class, which acts like a dict. By overriding the __getitem__ method, the Global should pretend that a global variable, named 'xx' does exist. This does work for the outermost scope in the executed code, but inside the nested function, 'q', the Global instance seems never to be accessed, 'xx' is not found, while the globals() built-in still returns the custom Global instance. According to python's executing model [1], the interpreter is supposed to look into globals(), if a variable has not been assigned in the inner scope. What am I missing here? [1] http://docs.python.org/reference/executionmodel.html {{{ class Global(dict): def __init__(self): pass def __getitem__(self, key): import __builtin__ if key == 'xx': return 'xx' if hasattr(__builtin__, key): return getattr(__builtin__, key) else key in self.__dict__: return self.__dict__[key] def __setitem__(self, key, value): self.__dict__[key] = value def __str__(self): return ' ' + unicode(self.__dict__) code=""" print globals() print xx # Does work, prints 'xx' def q(): print globals().__getitem__('xx') # Does work, prints 'xx' print globals()['xx'] # Does work, prints 'xx' print xx # Does not work, cannot find xx q() """ g = Global() exec(compile(code, 'my code', 'exec'), g, g) }}} -- http://mail.python.org/mailman/listinfo/python-list
Re: Replacing globals in exec by custom class
Thanks for your response! (And sorry about the syntax error, I forgot to test my code after cleaning up some debug statements before posting, the else should have been elif indeed.) It's very interesing, how Python works internally. According to a thread on the Python mailing list in 2002, it seems that the implementation of CPython bypasses __getitem__ of the dict object, when it is used as Global namespace. (For performance reasons.) http://mail.python.org/pipermail/python-dev/2002-October/029753.html -- http://mail.python.org/mailman/listinfo/python-list