salamek / cron-descriptor Goto Github PK
View Code? Open in Web Editor NEWA Python library that converts cron expressions into human readable strings.
License: MIT License
A Python library that converts cron expressions into human readable strings.
License: MIT License
Hey,
Installing on a raspberrypi raspbian I get:
From pip3 install -r requirements.txt
Downloading/unpacking cron-descriptor (from -r requirements.txt (line 6))
Downloading cron_descriptor-1.2.9.tar.gz
Running setup.py (path:/tmp/pip-build-m6nvvpb9/cron-descriptor/setup.py) egg_info for package cron-descriptor
Traceback (most recent call last):
File "<string>", line 17, in <module>
File "/tmp/pip-build-m6nvvpb9/cron-descriptor/setup.py", line 30, in <module>
long_description=open('README.md').read(),
File "/usr/lib/python3.4/encodings/ascii.py", line 26, in decode
return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 2514: ordinal not in range(128)
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "<string>", line 17, in <module>
File "/tmp/pip-build-m6nvvpb9/cron-descriptor/setup.py", line 30, in <module>
long_description=open('README.md').read(),
File "/usr/lib/python3.4/encodings/ascii.py", line 26, in decode
return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 2514: ordinal not in range(128)
----------------------------------------
Cleaning up...
Parsing the expression "A * * * * " are returning the value "'At A minutes past the hour' instead of raising the exception FormatException
from cron_descriptor import get_description
get_description('A * * * *')
Please can you update pip version?
locale folder doesn't have a .mo file for ko_KR locale.( which makes module doesn't accept the locale code)
I've converted ko_KR.po -> ko_KR.mo file and added to locale folder
and when I tested with following code it works without any problem.
from cron_descriptor import get_description, Options
if __name__ in '__main__':
options = Options()
expr_ls = [
'0 30 3,9,14,16,19,23 ? * SAT-SUN *'
, '0 0 16 ? * SAT *'
, '0 0 23 1/1 * ? *'
, '0 20 3,9,14,16,19,23 ? * SAT-SUN *'
, '0 0/1 * 1/1 * ? *'
, '0 0,30 15,16,17,18,19,20,21,22,23,1,2,3 1/1 * ? *'
, '0 0/15 * 1/1 * ? *'
]
options.locale_code = 'ko_KR'
for expr in expr_ls:
print(get_description(expr, options))
options.locale_code = 'cs_CZ'
for expr in expr_ls:
print(get_description(expr, options))
I suspect .mo file got filtered out by ignore list when it was pushed.
Would it be possible for me to make PR?
Salamek,
De following string is accepted:
print(get_description("* * * * 6-3"))
Every minute, Saturday through Wednesday
That interpretation looks fine, but I was not able to find any cron flavour that would actually support a range starting with a higher start-value than end-value (although in this case this feature would have been a nice to have).
When doing pip install cron-descriptor
the following deprecation warning appears:
DEPRECATION: cron-descriptor is being installed using the legacy 'setup.py install' method, because it does not have a 'pyproject.toml' and the 'wheel' package is not installed. pip 23.1 will enforce this behaviour change. A possible replacement is to enable the '--use-pep517' option. Discussion can be found at pypa/pip#8559
Possibly same issue as #6, but with hours rather than days.
>>> from cron_descriptor import get_description, ExpressionDescriptor
>>> print(get_description("15 6,10-20 * * *"))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "cron-descriptor-test/env/local/lib/python2.7/site-packages/cron_descriptor/ExpressionDescriptor.py", line 582, in get_description
return descripter.get_description(DescriptionTypeEnum.FULL)
File "cron-descriptor-test/env/local/lib/python2.7/site-packages/cron_descriptor/ExpressionDescriptor.py", line 101, in get_description
description = choices.get(description_type, self.get_seconds_description)()
File "cron-descriptor-test/env/local/lib/python2.7/site-packages/cron_descriptor/ExpressionDescriptor.py", line 149, in get_full_description
Hi Salamek,
I noticed the weekdays are not translated, while the rest of the string is. I made a small modification to get a localized day of week returned. I did not make a pull request as it is very small and perhaps you prefer a different solution.
Tools.py:
from .Exception import WrongArgumentException
from calendar import day_name
def number_to_day(day_number):
"""Returns day name by its number
Args:
day_number: Number of a day
Returns:
Day corresponding to day_number
Raises:
IndexError: When day_number is not found
"""
return [day_name[6], day_name[0], day_name[1], day_name[2], day_name[3], day_name[4], day_name[5]][day_number]
number_to_month also return hard coded strings, but I do not see those returned in the results (always full month names).
Originally reported at celery/django-celery-beat#647
Having crontab 0 2 * * monday
leads to an exception (FormatException: null
):
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)
The following code handles mon
fine, but turns monday
into 1DAY
:
cron-descriptor/cron_descriptor/ExpressionParser.py
Lines 172 to 174 in 0c575c6
That later fails in conversion to int. The conversion in celery works the other way – it extracts the first three letters of the string and uses that to convert to the int:
Package cannot be installed through pip on python 3.12
For DayOfWeekStartIndexZero=True, the value of 7 should be normalized to 0. If not, you will get an error.
I have a use case where I am trying to add on to your ExpressionDescriptor.get_full_description
method so that I can omit any arbitrary component of the humanreadable expression (in my case, the time_segment
).
In order to do so, I have chosen to extend your ExpressionDescriptor
class and add my omission function. This is partially because I also need to account for some irregularities that come up when you start ripping pieces of the expression out willy-nilly. I figured this could also be done with Options
, but it looked like it would be a lot more work.
However, I found I have IndexErrors with _expression_parts
if I try to call get_time_of_day_description
, get_day_of_month_description
, get_month_description
, get_day_of_week_description
, or get_year_description
in my function.
I also found that I can call get_description
first (either the exported function or ExpressionDescriptor
itself) and then I no longer get exceptions when calling my function from my ExpressionDescriptor
instance.
This is probably because parsing the expression and then setting the _expression_parts
are the first behaviours in the ExpressionDescriptor.get_description
function.
I would argue that it is appropriate to parse in the __init__
function for the class, because the expression parts seem needed for quite a few other functions of the class.
If there is a good reason to not set the parser in the __init__
function, then I would request that the ExpressionParser class be made available as part of the package so that anyone can call the parser as needed.
We could add a main.py to this project so that you would be able to run it in the terminal like:
> python -m cron_descriptor '* * * * *'
Every minute
Hi 👋
I would like to know if it would be possible to push the package as a wheel in pypi ?
Accordingly to the python packaging documentation, there's a github worfklow that lets you build and publish automatically on pypi.
If you are interested I can submit a PR 🙂
I'm attempting to make a Gentoo Ebuild for cron-descriptor-1.2.20. I'm only making use of the distutils-r1 eclass and it's interface for setuptools. This default setup forbids 'tests' packages from being installed.
- ERROR: dev-python/cron_descriptor-1.2.20::overlay failed (install phase):
- Package installs 'tests' package which is forbidden and likely a bug in the build system.
I am fairly inexperienced at this, but based on other packages, it is fairly standard that 'tests' be excluded from the setuptools packages.
I believe this to be a small bug with setup.py
Using version 1.2.24
(latest) with Python 3.9.5
, I see the following:
>>> import cron_descriptor as cd
>>> cd.get_description("*/10 * * * *")
'Every 10 minutes'
>>> cd.get_description("*/10 */1 * * *")
'Every 10 minutes'
Crontab guru shows the following translations:
*/10 * * * *
- "At every 10th minute."
*/10 */1 * * *
- "At every 10th minute past every hour."
from cron_descriptor import get_description
cron_express = "30 */6 * 1,2,3 1-5"
print(get_description(cron_express))
在每小时的 30 分, 每 6 小时, Monday 到 Friday, 仅在 January, February, 和 March
As we can see, there is a mixture of Chinese and English
The way this module parses 6 part Cron expressions is incompatible with other heavily used Python modules like parse-crontab.
For example, the following Expression "* * * * * *" is described as "Every second" while parse-crontab
treats it as "Every minute". This is because parse-crontab
assumes the 6th star in this case is the year (and thus the expression contains minutes, hours, ..., years), while this module requires a 4 digit number in that slot to make the same assumption (and otherwise, assumes this is an expression containing seconds).
I'd like to suggest adding an option that would adopt the parsing convention of parse-crontab
and thus make this module more compatible with other Python modules.
I'm happy to make the change and submit a PR.
Loading other languages than english is not working.
Please, accept pull request with fix for it.
Thanks.
Best regards.
This code
from cron_descriptor import get_description
get_description("0 0-13 * * *")
returns
"Between 12:00 AM and 01:59 PM"
That's not wrong, but there is missing information.
A better description would be:
At minute 0 past every hour from 0 through 13.
(got from crontab.guru)
GitHub releases has v1.2.23 , but PyPI only has 1.2.21
The italian translation may not be perfect in certain circumstances.
E.g., "* 0-7,19-23 * * *" would returns:
Ogni minuto, alle 00:00 al 07:59 e 19:00 al 23:59
I've used the following snippet:
import cron_descriptor
descripter = cron_descriptor.ExpressionDescriptor("* 0-7,19-23 * * *", use_24hour_time_format=True, locale_code='it_IT')
print(descripter.get_description())
The correct result should be:
Ogni minuto, dalle 00:00 alle 07:59 e dalle 19:00 alle 23:59
This can be obtained modifying the it_IT.po as follows:
# diff -ruN it_IT.po.orig it_IT.po
--- it_IT.po.orig 2019-01-17 11:24:15.033002345 +0100
+++ it_IT.po 2019-01-17 11:25:45.237514411 +0100
@@ -96,7 +96,7 @@
#: ExpressionDescriptor.py:218
#, python-brace-format
msgid "at {0}"
-msgstr "alle {0}"
+msgstr "dalle {0}"
#: ExpressionDescriptor.py:241
msgid "first"
@@ -151,7 +151,7 @@
#: ExpressionDescriptor.py:318
#, python-brace-format
msgid ", {0} through {1}"
-msgstr ", {0} al {1}"
+msgstr ", {0} alle {1}"
#: ExpressionDescriptor.py:272
#, python-brace-format
@@ -207,7 +207,7 @@
#: ExpressionDescriptor.py:385
msgid " and "
-msgstr " e "
+msgstr " e dalle "
#: ExpressionDescriptor.py:433
msgid ", every minute"
But I think that this would lead to errors in other circumstances (e.g. "0,30 6-17 * * *").
That's why using the "between {0} and {1}" syntax as follows should be a better option:
Ogni minuto, tra le 00:00 e le 07:59 e tra le 19:00 e le 23:59
Supporting timezones would be nice.
I have some system running with UTC, but crontabs should be represented on a central console running on CET (that is +0100).
I know implementing timezones may be tricky under some circumstances, such as "* 0-7,19-23 * * *".
I was testing some inputs in a try except block to see if the user enters a proper cronstring, during which I found something weird:
So far so good:
Your input, * * 23 * * , lead to the following repeat string: Every minute, on day 23 of the month
When you enter something like * * * facerolloverkeyboard *, or * * * * facerolloverkeyboard it will throw a FormatException as expected.
However, when you enter * * facerolloverkeyboard * *, it doesn't throw an error, instead it says:
Your input, * * facerolloverkeyboard * *, lead to the following repeat string: Every minute, on day facerolloverkeyboard of the month
I believe the path is
through: https://github.com/Salamek/cron-descriptor/blob/master/cron_descriptor/ExpressionDescriptor.py#L386
into: https://github.com/Salamek/cron-descriptor/blob/master/cron_descriptor/ExpressionDescriptor.py#L455
Similarly, when you enter facerolloverkeyboard * * * *, it doesn't throw an error, instead it says:
Your input, facerolloverkeyboard * * * *, lead to the following repeat string: At facerolloverkeyboard minutes past the hour
I believe the path is
through: https://github.com/Salamek/cron-descriptor/blob/master/cron_descriptor/ExpressionDescriptor.py#L255
into: https://github.com/Salamek/cron-descriptor/blob/master/cron_descriptor/ExpressionDescriptor.py#L455
I am not quite sure where the correct FormatException get thrown, and why it's not thrown for minutes and DoM. If you have any clue I can take it up from there and test and make a PR.
See new code with upper() below.
# convert SUN-SAT format to 0-6 format
for day_number in self._cron_days:
expression_parts[5] = expression_parts[5].upper()
expression_parts[5] = expression_parts[5].replace(self._cron_days[day_number], str(day_number))
# convert JAN-DEC format to 1-12 format
for month_number in self._cron_months:
expression_parts[4] = expression_parts[4].upper()
expression_parts[4] = expression_parts[4].replace(self._cron_months[month_number], str(month_number))
I fixed my code by upper casing the cron expression before calling your excellent code. Thanks.
Like this expression ExpressionDescriptor.GetDescription("* * * * 4L");
shows a full description like:
"Every minute, on the last Thursday of the month"
I actually expect this expression ExpressionDescriptor.GetDescription("30 02 14 * * *");
to show
"Every day at 02:02:30 PM"
instead of
"At 02:02:30 PM"
Anyone who is already familiar with this package and knows how to update this one?
The result is "Every second, between day L and 10 of the month",but expect "Every second, 10 days before the last day of the month"
Hi!
Glad to see nice project here!!
I want to use cron-descriptor out from box, but have one trouble.
When i "pip install cron-descriptor" there are no locale folder in my installed env.
(test) danis@user:/tmp$ pip install cron_descriptor
(test) danis@user:~/.virtualenvs/test$ ll lib/python2.7/site-packages/cron_descriptor
total 128
drwxrwxr-x 2 danis danis 4096 сен 6 11:06 ./
drwxrwxr-x 25 danis danis 4096 сен 6 11:06 ../
-rw-rw-r-- 1 danis danis 858 сен 6 11:06 CasingTypeEnum.py
-rw-rw-r-- 1 danis danis 558 сен 6 11:06 CasingTypeEnum.pyc
-rw-rw-r-- 1 danis danis 920 сен 6 11:06 DescriptionTypeEnum.py
-rw-rw-r-- 1 danis danis 679 сен 6 11:06 DescriptionTypeEnum.pyc
-rw-rw-r-- 1 danis danis 1304 сен 6 11:06 Exception.py
-rw-rw-r-- 1 danis danis 1411 сен 6 11:06 Exception.pyc
-rw-rw-r-- 1 danis danis 21663 сен 6 11:06 ExpressionDescriptor.py
-rw-rw-r-- 1 danis danis 23261 сен 6 11:06 ExpressionDescriptor.pyc
-rw-rw-r-- 1 danis danis 6579 сен 6 11:06 ExpressionParser.py
-rw-rw-r-- 1 danis danis 4504 сен 6 11:06 ExpressionParser.pyc
-rw-rw-r-- 1 danis danis 1277 сен 6 11:06 GetText.py
-rw-rw-r-- 1 danis danis 1154 сен 6 11:06 GetText.pyc
-rw-rw-r-- 1 danis danis 1171 сен 6 11:06 __init__.py
-rw-rw-r-- 1 danis danis 601 сен 6 11:06 __init__.pyc
-rw-rw-r-- 1 danis danis 1265 сен 6 11:06 Options.py
-rw-rw-r-- 1 danis danis 1127 сен 6 11:06 Options.pyc
-rw-rw-r-- 1 danis danis 1206 сен 6 11:06 StringBuilder.py
-rw-rw-r-- 1 danis danis 1411 сен 6 11:06 StringBuilder.pyc
So no locale folder at all. And no localization for me.
Is there any special reason for behavior like that?
I can pull request, to port locale folder if you want.
PS
Installed version - 1.2.5
Python - 2.7.12
The tar file with lib contains locale folder, but it is not copied in installation directory.
In our GitHub Actions:
python setup.py test
WARNING: Testing via this command is deprecated and will be removed in a future version. Users looking for a generic test entry point independent of test runner are encouraged to use tox.
https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html
I can't see anything that would cause an incompatibility with Python 3.6 and all the tests pass when ran against 3.6.7.
Mind bumping the maximum supported version?
Hello. Thank you very much for this library. It seems to be working well, except for a couple of corner-case issues. Here's some code:
import cron_descriptor
cron = '30 4 1,15 * FRI'
print(f'Description for [{cron}] is: {cron_descriptor.get_description(cron)}')
Output:
Description for [30 4 1,15 * FRI] is: At 04:30 AM, on day 1 and 15 of the month, only on Friday
This should actually be something like:
Description for [30 4 1,15 * FRI] is: At 04:30 AM, on day 1 and 15 of the month, plus every Friday
This is in keeping with the crontab(5) man page which indicates the day-of-month and day-of-week criteria should be combined with OR rather than AND.
Note: The day of a command's execution can be specified by two fields — day of month, and day of week. If both fields are restricted (i.e., aren't *), the command will be run when either field matches the current time. For example,
``30 4 1,15 * 5'' would cause a command to be run at 4:30 am on the 1st and 15th of each month, plus every Friday.
However, there is an exception to this due to a bug in Vixie cron/ISC cron/cronie. Because cron fails to parse asterisk fields that contain more than just a single asterisk (for example, */2
), it will join the criteria together with AND rather than OR for those entries, in violation of its own man page. So for this code:
cron = '30 4 */2 * FRI'
print(f'Description for [{cron}] is: {cron_descriptor.get_description(cron)}')
cron-descriptor actually evaluates the code the same way the buggy cron does:
Description for [30 4 */2 * FRI] is: At 04:30 AM, every 2 days, only on Friday
(more details on the asterisk bug in cron is here: https://crontab.guru/cron-bug.html The consensus seems to be that this bug should not be fixed due to its having been around for decades now.)
So, could the incorrect evaluation of cron entries like "30 4 1,5 * FRI" be fixed, while still keeping consistency with the buggy versions of cron for entries like "30 4 */2 * FRI"?
Thanks for looking into it, and for your work on this tool.
"2-59/3 1 * * *" not supported, however "2-59/3 1,9 * * *" is ok.
I have very limited cron expression experience so hopefully this is a valid expression and I'm not wasting people's time.
Code:
from cron_descriptor import get_description, ExpressionDescriptor
print(get_description("22 26 18 ? JAN,DEC WED#1,1,2,3,4 *"))
Result: At 06:26:22 PM, on the None Wednesday, Monday, Tuesday, Wednesday, and Thursday of the month, only in January and December
Expected result: At 06:26:22 PM, on the first Wednesday, Monday, Tuesday, Wednesday, and Thursday of the month, only in January and December
The project is MIT license but some of the code has headers look like GPL:
https://github.com/Salamek/cron-descriptor/blob/master/cron_descriptor/ExpressionParser.py
Would you please help clarify if the project is entirely MIT licensed, with GPL license headers included in error?
Or is the project GPL licensed, with the contents of the LICENSE file being in error?
Or is the project partly MIT-licensed and partly GPL-licensed, without the differently-licensed files being segregated?
Thanks for your help
Hi Salamek,
I noticed the combination of individual weekdays and a range leads to syntax errors:
>>> from cron_descriptor import get_description, ExpressionDescriptor
>>> print(get_description("38 20 * * 0,2,3-6"))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/site-packages/cron_descriptor/ExpressionDescriptor.py", line 568, in get_description
return descripter.get_description(DescriptionTypeEnum.FULL)
File "/usr/lib/python2.7/site-packages/cron_descriptor/ExpressionDescriptor.py", line 101, in get_description
description = choices.get(description_type, self.get_seconds_description)()
File "/usr/lib/python2.7/site-packages/cron_descriptor/ExpressionDescriptor.py", line 151, in get_full_description
raise FormatException(description)
cron_descriptor.Exception.FormatException: An error occured when generating the expression description. Check the cron expression syntax.
Just ranges or individual weekdays do work ok.
Seems like bad values like a >60 in seconds or minutes, >23 in hours, etc. are just accepted.
Also, bogus values are just parsed as-is.
Shouldn't the descriptor throw an error for these?
Thanks
In [9]: get_description("*40 * * * *")
Out[9]: 'At *40 minutes past the hour'
In [10]: get_description("*foobar * * * *")
Out[10]: 'At *foobar minutes past the hour'
In [11]: get_description("foobar * * * *")
Out[11]: 'At foobar minutes past the hour'
In [13]: get_description("*123123123 * * * *")
Out[13]: 'At *123123123 minutes past the hour'
In [14]: get_description("123123123 * * * *")
Out[14]: 'At 123123123 minutes past the hour'
In [15]: get_description("123123123 * * * * *")
Out[15]: 'At 123123123 seconds past the minute'
Hello @Salamek ,
I created a Golang port of your repo, and would like it added to the Readme.
https://github.com/jsuar/go-cron-descriptor
I made sure to:
Let me know if there's anything I need to do on my end.
Thanks,
jsuar
Hello,
msgid ", starting {0}" for spanish (es_ES) is not present. This causes missing parts on some descriptions.
Thank you
Hi there,
You got a PKGBUILD in your project which is super nice.
Mind throwing that into the AUR?
If you don't feel like it, I could do that as well and maintain updates etc.
Hello, I was wondering if you can possibly help me figure out the best way to avoid bad cron entries like this one:"3-59/10 * * * 1-7" the code bombs out and it does not continue processing. is there a way for me to improve the code on my side to avoid this issue? perhaps I can improve the for loop to avoid processing a bad entry like the example I provided?
any help is greatly appreciated and thank you so much for this amazing library, it is so important!
here is the code I using:
#!/usr/bin/env python
import csv
import sys
from cron_descriptor import ExpressionDescriptor, Options, DescriptionTypeEnum, CasingTypeEnum
expressionField = "cron_expression"
humanReadableField = "cron_human_readable"
def main():
infile = sys.stdin
outfile = sys.stdout
r = csv.DictReader(infile)
header = r.fieldnames
w = csv.DictWriter(outfile, r.fieldnames)
w.writeheader()
options = Options()
options.verbose = True
options.throw_exception_on_parse_error = True
options.casing_type = CasingTypeEnum.Sentence
for result in r:
cron_expression = result[expressionField]
descripter = ExpressionDescriptor(cron_expression, options)
result[humanReadableField] = str(descripter.get_description(DescriptionTypeEnum.FULL))
w.writerow(result)
main()
I am having trouble displaying all languages in a proper way. The content of the PO files seems to be a variation of ASCII encodings in UTF-8 format. Encoding them in real UTF-8 would solve all those issues I think.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.