cameronmaske / celery-once

Celery Once allows you to prevent multiple execution and queuing of celery tasks.
https://pypi.python.org/pypi/celery_once/
BSD 2-Clause "Simplified" License
662 stars 90 forks source link

Keyword-arg as list of str not handled properly #11

Closed brouberol closed 9 years ago

brouberol commented 9 years ago

I'm facing an issue when sending a keyword argument containing a list of strings.

The task is called as

>>> import_files.delay(access_type='local:files', filepaths=map(os.path.abspath, ['tmp/tmpfile1', 'tmp/tmpfile2'])

The getcallargs(self.run, *args, **kwargs) call, returns the following dict:

{
    'access_type': 'local:files', 
    'server': None, 
    'user': None, 
    'filepaths': ['/home/br/code/project/project/tmp/tmpfile1', '/home/br/code/project/project/tmp/tmpfile2'], 
    'password': None
}

which generates the key

"qo_externalapi.tasks.marin.import_marin_files_access_type-local:files_filepaths-['/home/br/code/project/project/tmp/tmpfile1', '/home/br/code/project/project/tmp/tmpfile2']_password-None_server-None_user-None"

When the task call returns, the getcallargs(self.run, *args, **kwargs) call now returns the following dict:

{
    'access_type': 'local:files', 
    'server': None, 
    'user': None, 
    'filepaths': [u'/home/br/code/project/project/tmp/tmpfile1', u'/home/br/code/project/project/tmp/tmpfile2'], 
    'password': None
}

which generates the key

"qo_externalapi.tasks.marin.import_marin_files_access_type-local:files_filepaths-[u'/home/br/code/project/project/tmp/tmpfile1', u'/home/br/code/project/project/tmp/tmpfile2']_password-None_server-None_user-None"

The (subtle) difference is that inspect.getcallargs added the "u" prefix in front of each string in the filepaths kwargs. As this results in two different keys, I can only delay a task once, until the lock expires.

cameronmaske commented 9 years ago

@brouberol Great bug report! Thanks for taking the time to include all the examples code.

I think the best bet would be to extend kwargs_to_list to force str/unicodes into one standard form https://github.com/TrackMaven/celery-once/blob/dbce7508536eb8a2d3184dd2dded42a86357882c/celery_once/helpers.py#L37

Will hopefully get around to patching this week!

brouberol commented 9 years ago

Heh, no worries. No example, no patch, right :smile:

Let me know if there is anything I can do to make this work. I think we may need to recursively iterate over each kwarg and force convert any str to unicode (in the python2 sense). Does that seem right to you?