Python decorator syntax limitations

2010-01-18 Thread Jonathan S
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

2010-01-18 Thread Jonathan S
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

2010-12-08 Thread Jonathan S
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

2010-12-09 Thread Jonathan S
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