Ticket #568 (reopened defect)

Opened 19 months ago

Last modified 19 months ago

cache utility does not handle default argument values

Reported by: Wichert Owned by:
Priority: normal Milestone:
Component: Other Version: 0.9.7
Severity: normal Keywords:
Cc:

Description

I got an IndexError? on the args_keys[arg] = args[i] line in _make_dict_from_args() method if I did not pass arguments which had a default value in to a function.

I modified the code to build a list of default arguments and use that instead. This is safer than skipping those arguments in case you change the defaults but your have persisting cache entries in a dbm or memcache.

def _make_dict_from_args(func, args):
    """Inspects function for name of args"""
    args_keys = {}
    argspec = inspect.getargspec(func)
    if argspec[3] is not None:
        defaults = (None,)*(len(argspec[0])-len(argspec[3])) + argspec[3]
    for i, arg in enumerate(argspec[0]):
        if arg != "self":
            try:
                args_keys[arg] = args[i]
            except IndexError:
                args_keys[arg] = defaults[i]
    return args_keys

Change History

Changed 19 months ago by Wichert

The code which triggered this for me looked like this:

@cache
def image_url(uuid, scale="80x80"):
    # Bunch of database queries to generate the URL
    return URL

Which was called from a template like this:

h.image_url(article.image_id)

Changed 19 months ago by Wichert

I found the traceback:

Module tostyle4you.lib.cache:71 in wrapper
<<          key_dict=kwargs.copy()
            if args:
                key_dict.update(_make_dict_from_args(func, args))
            cache_key = " ".join(["%s=%s" % (k, v) for k, v in key_dict.iteritems()])
>>  key_dict.update(_make_dict_from_args(func, args))
Module pylons.decorators.cache:141 in _make_dict_from_args
<<      for i, arg in enumerate(inspect.getargspec(func)[0]):
            if arg != "self":
                args_keys[arg] = args[i]
        return args_keys
>>  args_keys[arg] = args[i]
IndexError: tuple index out of range

Changed 19 months ago by Philip Jenvey

  • status changed from new to closed
  • resolution set to fixed

For some reason 'args' here did not include the defaults, due to decorator 2.2.0. This works fine in decorator 2.3.2, which is now the minimum dependency

Changed 19 months ago by Wichert Akkerman

  • status changed from closed to reopened
  • resolution fixed deleted

I retested this twice with decorator 2.3.2 and the bug still exists. The locals at the point where it aborts are:

arg  	'scale'
args 	(u'',)
args_keys 	{'token': u''}
func 	<function image_url at 0x3b169f0>
i 	1

Notice how args does not include the default value for the scale paramter.

Changed 19 months ago by Philip Jenvey

You assured us this was fixed over IRC, what has changed? Were you mistaken? I could never reproduce it, under Python 2.5.1, and using decorator 2.3.2

Changed 19 months ago by Wichert Akkerman

It appears I was indeed mistaken :(

I am using python 2.5.2 here, I doubt that makes a difference though.

Changed 19 months ago by Philip Jenvey

Can you pastebin the entire traceback again, using the beaker_cache decorator? The one you pasted seems to be from your custom version of that decorator

Note that there's a text version of the traceback in the interactive debugger, which is better for pasting

Changed 19 months ago by Philip Jenvey

Oh yes, also, try touch'ing the controller file. I'm thinking the bytecode could be stale (the decorator module does some tricky things via eval)

Changed 19 months ago by Philip Jenvey

Wichert - we're ramping up for the 0.9.7 release today, and we can't reproduce this, so if you manage to ping us back immediately about this we might be able to sort it out before the 0.9.7 final. I have a feeling it's your environment

Note: See TracTickets for help on using tickets.


Powered by Pylons - Contact Administrators