django-celery-beat icon indicating copy to clipboard operation
django-celery-beat copied to clipboard

Exception in admin: invalid literal for int() with base 10: '1DAY'

Open nijel opened this issue 1 year ago • 5 comments

Summary:

Include a brief description of the problem here, and fill out the version info below.

  • Celery Version: 5.2.7
  • Celery-Beat Version: 2.5.0

Exact steps to reproduce the issue:

  1. Create task with cron schedule 0 2 * * monday (m/h/dM/MY/d) UTC (created via Python crontab(hour=2, minute=0, day_of_week="monday"))
  2. Open it in admin interface
  3. Get a crash

Detailed information

Please include more detailed information here, such as relevant information about your system setup, things you did to try and debug the problem, log messages, etc.

Traceback (most recent call last):
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/cron_descriptor/ExpressionDescriptor.py", line 131, in get_full_description
    day_of_week_desc = self.get_day_of_week_description()
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/cron_descriptor/ExpressionDescriptor.py", line 342, in get_day_of_week_description
    return self.get_segment_description(
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/cron_descriptor/ExpressionDescriptor.py", line 467, in get_segment_description
    description = get_description_format(expression).format(get_single_item_description(expression))
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/cron_descriptor/ExpressionDescriptor.py", line 345, in <lambda>
    lambda s: get_day_name(s),
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/cron_descriptor/ExpressionDescriptor.py", line 315, in get_day_name
    return ExpressionDescriptor.number_to_day(int(exp))

During handling of the above exception (invalid literal for int() with base 10: '1DAY'), another exception occurred:
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/django/core/handlers/exception.py", line 56, in inner
    response = get_response(request)
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/sentry_sdk/integrations/django/views.py", line 85, in sentry_wrapped_callback
    return callback(request, *args, **kwargs)
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/django/contrib/admin/options.py", line 686, in wrapper
    return self.admin_site.admin_view(view)(*args, **kwargs)
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/django/utils/decorators.py", line 134, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/django/views/decorators/cache.py", line 62, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/django/contrib/admin/sites.py", line 242, in inner
    return view(request, *args, **kwargs)
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/django/contrib/admin/options.py", line 1894, in change_view
    return self.changeform_view(request, object_id, form_url, extra_context)
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/django_celery_beat/admin.py", line 155, in changeform_view
    crontab_dict[crontab.id] = crontab.human_readable
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/django_celery_beat/models.py", line 319, in human_readable
    human_readable = get_description('{} {} {} {} {}'.format(
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/cron_descriptor/ExpressionDescriptor.py", line 664, in get_description
    return descripter.get_description(DescriptionTypeEnum.FULL)
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/cron_descriptor/ExpressionDescriptor.py", line 108, in get_description
    description = choices.get(description_type, self.get_seconds_description)()
  File "/home/weblate/weblate-env/lib/python3.9/site-packages/cron_descriptor/ExpressionDescriptor.py", line 148, in get_full_description
    raise FormatException(description)

Seems like monday becomes 1DAY somewhere on the way.

nijel avatar Mar 24 '23 11:03 nijel

is this regression result of this change https://github.com/celery/django-celery-beat/pull/622?

auvipy avatar Mar 24 '23 12:03 auvipy

I think it is.

nijel avatar Mar 24 '23 12:03 nijel

I've also created https://github.com/Salamek/cron-descriptor/issues/65 as this might be better to address in cron_descriptor.

PS: Still, django-celery-beat might catch FormatException here and display original crontab in case human friendly description is not available.

nijel avatar Mar 24 '23 12:03 nijel

Guys, full length day/month names are not valid in CRON expression, you need to "normalize" your "cron" format to valid CRON format before passing it into cron-descriptor.

I have looked over celery.schedules.crontab src and it normalizes strings used in provided "cron" to integers, maybe use that to generate correct integer based CRON and then pass that into cron-descriptor?

(Something like this but better & tested):

c = crontab(hour=2, minute=0, day_of_week="monday")

# celery.schedules,crontab converts named days & months to their integer representation, use that instead!


minute, = c.minute
hour, = c.hour
day_of_week, = c.day_of_week

valid_cron = '{} {} {} {} {}'.format(  #!FIXME this will totally going to break when used with different CRON parameters provided into crontab()
    minute,
    hour,
    c._orig_day_of_month,
    c._orig_month_of_year,
    day_of_week
)
print(valid_cron)

Salamek avatar Mar 24 '23 14:03 Salamek

Ugh very ugly bug.

  1. Maybe we should mention it in the documentation? Because at that page it looks that name of day of week is supported;
  2. Or make transformation from week day to number on django-celery-beat side as suggest @Salamek ?

Akay7 avatar Apr 03 '24 03:04 Akay7