quetz-mod_python-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Graham Dumpleton <grah...@dscpl.com.au>
Subject Re: Python 2.5 nested auth functions in publisher.
Date Sun, 29 Oct 2006 05:18:19 GMT

On 29/10/2006, at 12:05 PM, Graham Dumpleton wrote:

>
> On 28/10/2006, at 10:01 PM, Dan Eloff wrote:
>
>> On 10/28/06, Graham Dumpleton <grahamd@dscpl.com.au> wrote:
>>> Dan, the code that needs to be updated is:
>>>
>>>          if "__auth__" in func_code.co_names:
>>>              i = list(func_code.co_names).index("__auth__")
>>>              __auth__ = func_code.co_consts[i+1]
>>>              if hasattr(__auth__, "co_name"):
>>>                  __auth__ = new.function(__auth__, func_globals)
>>>              found_auth = 1
>>>
>>> Note how it accesses code objects for functions from co_consts. Do
>>> they still appear
>>> to be there in Python 2.5? Are you able to work out some code that
>>> does the same
>>> thing as this?
>>>
>>
>> Using the test function:
>>
>>>>> def foo(a,b):
>> 	d = 5
>> 	def __auth__(req):
>> 		return True
>> 	e = d + 5
>>
>>>>> fc = foo.func_code
>>>>> import new
>>>>> func_globals = globals()
>>>>> for i, var_name in enumerate(fc.co_varnames):
>> 	if var_name == '__auth__':
>> 		__auth__ = fc.co_consts[i-fc.co_argcount+1]
>> 		if hasattr(__auth__, 'co_name'):
>> 			__auth__ = new.function(__auth__, func_globals)
>> 		found_auth = 1
>> 		break
>>
>>>>> __auth__
>> <function __auth__ at 0x01159830>
>>
>> I am curious as to the hasattr(__auth__, 'co_name') section. Is there
>> any case where this is not true? (and does it make sense to say
>> found_auth = 1 if it isn't?)
>
> The co_name check is making sure it is a code object as opposed to a
> dictionary or some other constant.
>
> See:
>
>   http://www.modpython.org/live/current/doc-html/hand-pub-alg- 
> auth.html
>
> for what __auth__ can be.

Actually, I am partly wrong about that, when nesting these inside of a
function they must be functions or a constant, they can't be a  
dictionary.
The documentation even states this:

   Note that this technique will also work if __auth__ or __access__  
is a
   constant, but will not work if they are a dictionary or a list.

What I have found though is that even in Python 2.3.5, the names can be
found in co_varnames. The problem is that in Python 2.3.5, where the
names appear in co_varnames, they aren't in the same order as they
appear in co_names or as required for indexing into co_consts which
looks like a bug to me.

The question now is whether in Python 2.5 the names appear in  
co_varnames
in the correct order or not. If they aren't in the correct order and  
it is still
broken, makes it impossible for it to work.

Can you run the following test program and see if you get what would be
expected.



def handler(req):
     def __auth__(req, user, password):
         return 1
     def __access__(req, user):
         return 1
     __auth_realm__ = 'REALM'

func_code = handler.func_code

print func_code.co_names
print func_code.co_varnames
print func_code.co_argcount
print

def lookup(name):
     i = None
     if name in func_code.co_names:
         names = func_code.co_names
         i = list(names).index(name)
     elif func_code.co_argcount < len(func_code.co_varnames):
         names = func_code.co_varnames[func_code.co_argcount:]
         if name in names:
             i = list(names).index(name)
     if i is not None:
         return (1, func_code.co_consts[i+1])
     return (0, None)

print '__auth__', lookup('__auth__')
print '__access__', lookup('__access__')
print '__auth_realm__', lookup('__auth_realm__')



On Python 2.3.5 I get:



('__auth__', '__access__', '__auth_realm__')
('req', '__access__', '__auth_realm__', '__auth__')
1

__auth__ (1, <code object __auth__ at 0x6a8a0, file "hack.py", line 2>)
__access__ (1, <code object __access__ at 0x70660, file "hack.py",  
line 4>)
__auth_realm__ (1, 'REALM')


Thanks.

Graham


Mime
View raw message