Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-croniter for openSUSE:Factory checked in at 2021-03-12 13:33:27 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-croniter (Old) and /work/SRC/openSUSE:Factory/.python-croniter.new.2401 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-croniter" Fri Mar 12 13:33:27 2021 rev:15 rq:878436 version:1.0.8 Changes: -------- --- /work/SRC/openSUSE:Factory/python-croniter/python-croniter.changes 2020-11-26 23:16:11.877075064 +0100 +++ /work/SRC/openSUSE:Factory/.python-croniter.new.2401/python-croniter.changes 2021-03-12 13:33:28.406338771 +0100 @@ -1,0 +2,12 @@ +Fri Mar 12 03:42:51 UTC 2021 - Steve Kowalik <steven.kowa...@suse.com> + +- Update to 1.0.8: + * Update `_expand` to lowercase each component of the expression. + * Fix _expand to reject int literals with underscores + * Fix combination of star and invalid expression bugs + * Security fix: fix overflow when using cron ranges + * Fix #155: raise CroniterBadCronError when error syntax + * Fix match when datetime has microseconds + * Added Python 3.8 and 3.9 support + +------------------------------------------------------------------- Old: ---- croniter-0.3.36.tar.gz New: ---- croniter-1.0.8.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-croniter.spec ++++++ --- /var/tmp/diff_new_pack.127KwU/_old 2021-03-12 13:33:29.230339927 +0100 +++ /var/tmp/diff_new_pack.127KwU/_new 2021-03-12 13:33:29.234339933 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-croniter # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,13 +18,13 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-croniter -Version: 0.3.36 +Version: 1.0.8 Release: 0 Summary: Python iterators for datetime objects with cron-like format License: MIT -Group: Development/Languages/Python URL: http://github.com/kiorky/croniter Source: https://files.pythonhosted.org/packages/source/c/croniter/croniter-%{version}.tar.gz +BuildRequires: %{python_module future} BuildRequires: %{python_module natsort} BuildRequires: %{python_module pytest >= 3.0.3} BuildRequires: %{python_module python-dateutil} ++++++ croniter-0.3.36.tar.gz -> croniter-1.0.8.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/croniter-0.3.36/PKG-INFO new/croniter-1.0.8/PKG-INFO --- old/croniter-0.3.36/PKG-INFO 2020-11-02 17:09:51.354224200 +0100 +++ new/croniter-1.0.8/PKG-INFO 2021-03-06 12:30:08.018225700 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.2 Name: croniter -Version: 0.3.36 +Version: 1.0.8 Summary: croniter provides iteration for datetime object with cron like format Home-page: http://github.com/kiorky/croniter Author: Matsumoto Taichi, kiorky @@ -232,10 +232,70 @@ Changelog ============== + 1.0.8 (2021-03-06) + ------------------ + + - Update `_expand` to lowercase each component of the expression. + This is in relation to #157. With this change, croniter accepts and correctly handles `* * 10-L * *`. + [cuu508] + + + 1.0.7 (2021-03-02) + ------------------ + + - Fix _expand to reject int literals with underscores + [cuu508] + - Remove a debug statement to make flake8 happy + [cuu508] + + 1.0.6 (2021-02-01) + ------------------ + + - Fix combination of star and invalid expression bugs + [kiorky] + + + 1.0.5 (2021-01-29) + ------------------ + + - Security fix: fix overflow when using cron ranges + [kiorky] + + 1.0.4 (2021-01-29) + ------------------ + + - Spelling fix release + + + 1.0.3 (2021-01-29) + ------------------ + + - Fix #155: raise CroniterBadCronError when error syntax + [kiorky] + + + 1.0.2 (2021-01-19) + ------------------ + + - Fix match when datetime has microseconds + [kiorky] + + 1.0.1 (2021-01-06) + ------------------ + - no changes, just to make sense with new semver2 (making croniter on a stable state) + [kiorky] + + + 0.3.37 (2020-12-31) + ------------------- + + - Added Python 3.8 and 3.9 support + [eumiro] + + 0.3.36 (2020-11-02) ------------------- - - Nothing changed yet. - Updated docs section regarding ``max_years_between_matches`` to be more shorter and hopefully more relevant. [Kintyre] - Don't install tests @@ -482,5 +542,7 @@ Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/croniter-0.3.36/docs/CHANGES.rst new/croniter-1.0.8/docs/CHANGES.rst --- old/croniter-0.3.36/docs/CHANGES.rst 2020-11-02 17:09:51.000000000 +0100 +++ new/croniter-1.0.8/docs/CHANGES.rst 2021-03-06 12:30:07.000000000 +0100 @@ -1,10 +1,70 @@ Changelog ============== +1.0.8 (2021-03-06) +------------------ + +- Update `_expand` to lowercase each component of the expression. + This is in relation to #157. With this change, croniter accepts and correctly handles `* * 10-L * *`. + [cuu508] + + +1.0.7 (2021-03-02) +------------------ + +- Fix _expand to reject int literals with underscores + [cuu508] +- Remove a debug statement to make flake8 happy + [cuu508] + +1.0.6 (2021-02-01) +------------------ + +- Fix combination of star and invalid expression bugs + [kiorky] + + +1.0.5 (2021-01-29) +------------------ + +- Security fix: fix overflow when using cron ranges + [kiorky] + +1.0.4 (2021-01-29) +------------------ + +- Spelling fix release + + +1.0.3 (2021-01-29) +------------------ + +- Fix #155: raise CroniterBadCronError when error syntax + [kiorky] + + +1.0.2 (2021-01-19) +------------------ + +- Fix match when datetime has microseconds + [kiorky] + +1.0.1 (2021-01-06) +------------------ +- no changes, just to make sense with new semver2 (making croniter on a stable state) + [kiorky] + + +0.3.37 (2020-12-31) +------------------- + +- Added Python 3.8 and 3.9 support + [eumiro] + + 0.3.36 (2020-11-02) ------------------- -- Nothing changed yet. - Updated docs section regarding ``max_years_between_matches`` to be more shorter and hopefully more relevant. [Kintyre] - Don't install tests diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/croniter-0.3.36/requirements/base.txt new/croniter-1.0.8/requirements/base.txt --- old/croniter-0.3.36/requirements/base.txt 2020-11-02 17:09:51.000000000 +0100 +++ new/croniter-1.0.8/requirements/base.txt 2021-03-06 12:30:07.000000000 +0100 @@ -1,3 +1,4 @@ python_dateutil +future natsort -e . diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/croniter-0.3.36/setup.py new/croniter-1.0.8/setup.py --- old/croniter-0.3.36/setup.py 2020-11-02 17:09:51.000000000 +0100 +++ new/croniter-1.0.8/setup.py 2021-03-06 12:30:07.000000000 +0100 @@ -23,7 +23,7 @@ setup( name='croniter', - version='0.3.36', + version='1.0.8', py_modules=['croniter', ], description=( 'croniter provides iteration for datetime ' @@ -51,6 +51,8 @@ "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "Topic :: Software Development :: Libraries :: Python Modules"], packages=find_packages('src', exclude=['tests*', '*.tests*']), package_dir={'': 'src'}, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/croniter-0.3.36/src/croniter/croniter.py new/croniter-1.0.8/src/croniter/croniter.py --- old/croniter-0.3.36/src/croniter/croniter.py 2020-11-02 17:09:51.000000000 +0100 +++ new/croniter-1.0.8/src/croniter/croniter.py 2021-03-06 12:30:07.000000000 +0100 @@ -5,17 +5,18 @@ import math import re +import sys from time import time import datetime from dateutil.relativedelta import relativedelta from dateutil.tz import tzutc import calendar import natsort +from future.utils import raise_from -step_search_re = re.compile(r'^([^-]+)-([^-/]+)(/(.*))?$') -search_re = re.compile(r'^([^-]+)-([^-/]+)(/(.*))?$') + +step_search_re = re.compile(r'^([^-]+)-([^-/]+)(/(\d+))?$') only_int_re = re.compile(r'^\d+$') -any_int_re = re.compile(r'^\d+') star_or_int_re = re.compile(r'^(\d+|\*)$') VALID_LEN_EXPRESSION = [5, 6] @@ -47,7 +48,7 @@ (0, 23), (1, 31), (1, 12), - (0, 6), + (0, 7), (0, 59) ) DAYS = ( @@ -115,7 +116,7 @@ @classmethod def _alphaconv(cls, index, key, expressions): try: - return cls.ALPHACONV[index][key.lower()] + return cls.ALPHACONV[index][key] except KeyError: raise CroniterNotAlphaError( "[{0}] is not acceptable".format(" ".join(expressions))) @@ -294,7 +295,9 @@ DAYS = self.DAYS def proc_month(d): - if expanded[3][0] != '*': + try: + expanded[3].index('*') + except ValueError: diff_month = nearest_diff_method( d.month, expanded[3], self.MONTHS_IN_YEAR) days = DAYS[month - 1] @@ -316,7 +319,9 @@ return False, d def proc_day_of_month(d): - if expanded[2][0] != '*': + try: + expanded[2].index('*') + except ValueError: days = DAYS[month - 1] if month == 2 and self.is_leap(year) is True: days += 1 @@ -342,7 +347,9 @@ return False, d def proc_day_of_week(d): - if expanded[4][0] != '*': + try: + expanded[4].index('*') + except ValueError: diff_day_of_week = nearest_diff_method( d.isoweekday() % 7, expanded[4], 7) if diff_day_of_week is not None and diff_day_of_week != 0: @@ -406,7 +413,9 @@ return False, d def proc_hour(d): - if expanded[1][0] != '*': + try: + expanded[1].index('*') + except ValueError: diff_hour = nearest_diff_method(d.hour, expanded[1], 24) if diff_hour is not None and diff_hour != 0: if is_prev: @@ -418,7 +427,9 @@ return False, d def proc_minute(d): - if expanded[0][0] != '*': + try: + expanded[0].index('*') + except ValueError: diff_min = nearest_diff_method(d.minute, expanded[0], 60) if diff_min is not None and diff_min != 0: if is_prev: @@ -430,7 +441,9 @@ def proc_second(d): if len(expanded) == 6: - if expanded[5][0] != '*': + try: + expanded[5].index('*') + except ValueError: diff_sec = nearest_diff_method(d.second, expanded[5], 60) if diff_sec is not None and diff_sec != 0: d += relativedelta(seconds=diff_sec) @@ -516,8 +529,11 @@ return False @classmethod - def expand(cls, expr_format): - expressions = expr_format.split() + def _expand(cls, expr_format): + # Split the expression in components, and normalize L -> l, MON -> mon, + # etc. Keep expr_format untouched so we can use it in the exception + # messages. + expressions = [e.lower() for e in expr_format.split()] if len(expressions) not in VALID_LEN_EXPRESSION: raise CroniterBadCronError(cls.bad_length) @@ -538,27 +554,34 @@ raise CroniterBadCronError( "[{0}] is not acceptable".format(expr_format)) + # Before matching step_search_re, normalize "*" to "{min}-{max}". + # Example: in the minute field, "*/5" normalizes to "0-59/5" t = re.sub(r'^\*(\/.+)$', r'%d-%d\1' % ( cls.RANGES[i][0], cls.RANGES[i][1]), str(e)) - m = search_re.search(t) + m = step_search_re.search(t) if not m: + # Before matching step_search_re, + # normalize "{start}/{step}" to "{start}-{max}/{step}". + # Example: in the minute field, "10/5" normalizes to "10-59/5" t = re.sub(r'^(.+)\/(.+)$', r'\1-%d/\2' % ( cls.RANGES[i][1]), str(e)) m = step_search_re.search(t) if m: + # early abort if low/high are out of bounds + (low, high, step) = m.group(1), m.group(2), m.group(4) or 1 if i == 2 and high == 'l': high = '31' - if not any_int_re.search(low): + if not only_int_re.search(low): low = "{0}".format(cls._alphaconv(i, low, expressions)) - if not any_int_re.search(high): + if not only_int_re.search(high): high = "{0}".format(cls._alphaconv(i, high, expressions)) if ( @@ -573,6 +596,11 @@ "[{0}] is not acceptable".format(expr_format)) low, high, step = map(int, [low, high, step]) + if ( + max(low, high) > max(cls.RANGES[i][0], cls.RANGES[i][1]) + ): + raise CroniterBadCronError( + "{0} is out of bands".format(expr_format)) try: rng = range(low, high + 1, step) except ValueError as exc: @@ -625,6 +653,17 @@ return expanded, nth_weekday_of_month @classmethod + def expand(cls, expr_format): + """Shallow non Croniter ValueError inside a nice CroniterBadCronError""" + try: + return cls._expand(expr_format) + except ValueError as exc: + error_type, error_instance, traceback = sys.exc_info() + if isinstance(exc, CroniterError): + raise + raise_from(CroniterBadCronError, exc) + + @classmethod def is_valid(cls, expression): try: cls.expand(expression) @@ -637,7 +676,9 @@ def match(cls, cron_expression, testdate, day_or=True): cron = cls(cron_expression, testdate, ret_type=datetime.datetime, day_or=day_or) td, ms1 = cron.get_current(datetime.datetime), relativedelta(microseconds=1) - cron.set_current(td + ms1) + if not td.microsecond: + td = td + ms1 + cron.set_current(td) tdp, tdt = cron.get_current(), cron.get_prev() return (max(tdp, tdt) - min(tdp, tdt)).total_seconds() < 60 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/croniter-0.3.36/src/croniter/tests/test_croniter.py new/croniter-1.0.8/src/croniter/tests/test_croniter.py --- old/croniter-0.3.36/src/croniter/tests/test_croniter.py 2020-11-02 17:09:51.000000000 +0100 +++ new/croniter-1.0.8/src/croniter/tests/test_croniter.py 2021-03-06 12:30:07.000000000 +0100 @@ -6,10 +6,8 @@ from functools import partial from time import sleep import pytz -import croniter as cr from croniter import croniter, croniter_range, CroniterBadDateError, CroniterBadCronError, CroniterNotAlphaError from croniter.tests import base -from tzlocal import get_localzone import dateutil.tz @@ -237,6 +235,16 @@ self.assertEqual(n4.month, 12) self.assertEqual(n4.day, 31) + def testRangeWithUppercaseLastDayOfMonth(self): + base = datetime(2015, 9, 4) + itr = croniter('0 0 29-L * *', base) + n1 = itr.get_next(datetime) + self.assertEqual(n1.month, 9) + self.assertEqual(n1.day, 29) + n2 = itr.get_next(datetime) + self.assertEqual(n2.month, 9) + self.assertEqual(n2.day, 30) + def testPrevLastDayOfMonth(self): base = datetime(2009, 12, 31, hour=20) itr = croniter('0 0 l * *', base) @@ -288,6 +296,9 @@ self.assertRaises(ValueError, croniter, '-90 * * * *') self.assertRaises(ValueError, croniter, 'a * * * *') self.assertRaises(ValueError, croniter, '* * * janu-jun *') + self.assertRaises(ValueError, croniter, '1-1_0 * * * *') + self.assertRaises(ValueError, croniter, '0-10/ * * * *') + self.assertRaises(CroniterBadCronError, croniter, "0-1& * * * *", datetime.now()) def testSundayToThursdayWithAlphaConversion(self): base = datetime(2010, 8, 25, 15, 56) # wednesday @@ -1285,6 +1296,23 @@ with self.assertRaises(StopIteration): next(iterable) + def test_issue151(self): + """.""" + self.assertTrue( + croniter.match("* * * * *", datetime(2019, 1, 14, 11, 0, 59, 999999))) + + def test_overflow(self): + """.""" + self.assertRaises(CroniterBadCronError, croniter , "0-10000000 * * * *", datetime.now()) + + def test_issue156(self): + """.""" + dt = croniter("* * * * *,0", datetime(2019, 1, 14, 11, 0, 59, 999999)).get_next() + self.assertEqual(1547463660.0, dt) + self.assertRaises(CroniterBadCronError, croniter, "* * * * *,b") + dt = croniter("0 0 * * *,sat#3", datetime(2019, 1, 14, 11, 0, 59, 999999)).get_next() + self.assertEqual(1547856000.0, dt) + if __name__ == '__main__': unittest.main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/croniter-0.3.36/src/croniter.egg-info/PKG-INFO new/croniter-1.0.8/src/croniter.egg-info/PKG-INFO --- old/croniter-0.3.36/src/croniter.egg-info/PKG-INFO 2020-11-02 17:09:51.000000000 +0100 +++ new/croniter-1.0.8/src/croniter.egg-info/PKG-INFO 2021-03-06 12:30:07.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.2 Name: croniter -Version: 0.3.36 +Version: 1.0.8 Summary: croniter provides iteration for datetime object with cron like format Home-page: http://github.com/kiorky/croniter Author: Matsumoto Taichi, kiorky @@ -232,10 +232,70 @@ Changelog ============== + 1.0.8 (2021-03-06) + ------------------ + + - Update `_expand` to lowercase each component of the expression. + This is in relation to #157. With this change, croniter accepts and correctly handles `* * 10-L * *`. + [cuu508] + + + 1.0.7 (2021-03-02) + ------------------ + + - Fix _expand to reject int literals with underscores + [cuu508] + - Remove a debug statement to make flake8 happy + [cuu508] + + 1.0.6 (2021-02-01) + ------------------ + + - Fix combination of star and invalid expression bugs + [kiorky] + + + 1.0.5 (2021-01-29) + ------------------ + + - Security fix: fix overflow when using cron ranges + [kiorky] + + 1.0.4 (2021-01-29) + ------------------ + + - Spelling fix release + + + 1.0.3 (2021-01-29) + ------------------ + + - Fix #155: raise CroniterBadCronError when error syntax + [kiorky] + + + 1.0.2 (2021-01-19) + ------------------ + + - Fix match when datetime has microseconds + [kiorky] + + 1.0.1 (2021-01-06) + ------------------ + - no changes, just to make sense with new semver2 (making croniter on a stable state) + [kiorky] + + + 0.3.37 (2020-12-31) + ------------------- + + - Added Python 3.8 and 3.9 support + [eumiro] + + 0.3.36 (2020-11-02) ------------------- - - Nothing changed yet. - Updated docs section regarding ``max_years_between_matches`` to be more shorter and hopefully more relevant. [Kintyre] - Don't install tests @@ -482,5 +542,7 @@ Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/croniter-0.3.36/src/croniter.egg-info/requires.txt new/croniter-1.0.8/src/croniter.egg-info/requires.txt --- old/croniter-0.3.36/src/croniter.egg-info/requires.txt 2020-11-02 17:09:51.000000000 +0100 +++ new/croniter-1.0.8/src/croniter.egg-info/requires.txt 2021-03-06 12:30:07.000000000 +0100 @@ -1,2 +1,3 @@ +future natsort python_dateutil diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/croniter-0.3.36/tox.ini new/croniter-1.0.8/tox.ini --- old/croniter-0.3.36/tox.ini 2020-11-02 17:09:51.000000000 +0100 +++ new/croniter-1.0.8/tox.ini 2021-03-06 12:30:07.000000000 +0100 @@ -1,7 +1,7 @@ [tox] minversion = 2.3 envlist = - {py26,py27,py34,py35,py36,py37}-std + {py26,py27,py34,py35,py36,py37,py38,py39}-std py27-coverage skipsdist = true @@ -14,8 +14,8 @@ COVERAGE_FILE={envdir}/coverage_report changedir = src commands = - {py26,py27,py34,py35,py36,py37}-std: py.test -v . - {py27,py34,py35,py36,py37}-std: flake8 croniter/croniter.py + {py26,py27,py34,py35,py36,py37,py38,py39}-std: py.test -v . + {py27,py34,py35,py36,py37,py38,py39}-std: flake8 croniter/croniter.py py27-coverage: coverage erase py27-coverage: sh -c 'cd .. && coverage run $(which py.test) -v src' py27-coverage: coverage report