proper packaging

This commit is contained in:
Mathieu Le Marec - Pasquet 2012-09-29 17:33:14 +02:00
parent f6b7b17bdd
commit f984a87b93
22 changed files with 800 additions and 394 deletions

11
.gitignore vendored
View File

@ -1,4 +1,13 @@
*.pyc
*app.pyc
t/
eggs
\.*.cfg
b.sh
develop-eggs
parts
bin
*minitage*
*.egg-info
*.pyc
*.swp

View File

@ -1,12 +0,0 @@
Thank you to all who have contributed to this project!
If you contributed and not listed below please let me know.
mrmachine
Hinnack
shazow
kiorky
jlsandell
mag009
djmitche
GreatCombinator
chris-baynes

6
MANIFEST.in Normal file
View File

@ -0,0 +1,6 @@
include *.txt *.cfg *.rst
recursive-include docs *
recursive-include src *
global-exclude *pyc

8
README
View File

@ -1,8 +0,0 @@
_ _
___ _ __ ___ _ __ (_) |_ ___ _ __
/ __| '__/ _ \| '_ \| | __/ _ \ '__|
| (__| | | (_) | | | | | || __/ |
\___|_| \___/|_| |_|_|\__\___|_|
croniter provides iteration for datetime object with cron like format.
Website: https://github.com/taichino/croniter

96
README.rst Normal file
View File

@ -0,0 +1,96 @@
Introduction
============
.. contents::
croniter provides iteration for datetime object with cron like format.
::
_ _
___ _ __ ___ _ __ (_) |_ ___ _ __
/ __| '__/ _ \| '_ \| | __/ _ \ '__|
| (__| | | (_) | | | | | || __/ |
\___|_| \___/|_| |_|_|\__\___|_|
Website: https://github.com/taichino/croniter
Usage
============
Simple example of usage is followings::
>>> from croniter import croniter
>>> from datetime import datetime
>>> base = datetime(2010, 1, 25, 4, 46)
>>> iter = croniter('*/5 * * * *', base) # every 5 minites
>>> print iter.get_next(datetime) # 2010-01-25 04:50:00
>>> print iter.get_next(datetime) # 2010-01-25 04:55:00
>>> print iter.get_next(datetime) # 2010-01-25 05:00:00
>>>
>>> iter = croniter('2 4 * * mon,fri', base) # 04:02 on every Monday and Friday
>>> print iter.get_next(datetime) # 2010-01-26 04:02:00
>>> print iter.get_next(datetime) # 2010-01-30 04:02:00
>>> print iter.get_next(datetime) # 2010-02-02 04:02:00
All you need to know is constructor and get_next, these signature are following::
>>> def __init__(self, cron_format, start_time=time.time())
croniter iterate along with 'cron_format' from 'start_time'.
cron_format is 'min hour day month day_of_week', and please refer to
http://en.wikipedia.org/wiki/Cron for details.::
>>> def get_next(self, ret_type=float)
get_next return next time in iteration with 'ret_type'.
And ret_type accept only 'float' or 'datetime'.
Now, supported get_prev method. (>= 0.2.0)::
>>> base = datetime(2010, 8, 25)
>>> itr = croniter('0 0 1 * *', base)
>>> print itr.get_prev(datetime) # 2010-08-01 00:00:00
>>> print itr.get_prev(datetime) # 2010-07-01 00:00:00
>>> print itr.get_prev(datetime) # 2010-06-01 00:00:00
Develop this package
====================
::
git clone https://github.com/taichino/croniter.git
cd croniter
python bootstrap.py -d
bin/buildout -vvvvvvN
bin/test
Make a new release
====================
We use zest.fullreleaser, a great releaser infrastructure.
Do and follow the instructions
::
bin/fullrelease
Contributors
===============
Thank you to all who have contributed to this project!
If you contributed and not listed below please let me know.
- mrmachine
- Hinnack
- shazow
- kiorky
- jlsandell
- mag009
- djmitche
- GreatCombinator
- chris-baynes

121
bootstrap.py Normal file
View File

@ -0,0 +1,121 @@
##############################################################################
#
# Copyright (c) 2006 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Bootstrap a buildout-based project
Simply run this script in a directory containing a buildout.cfg.
The script accepts buildout command-line options, so you can
use the -c option to specify an alternate configuration file.
"""
import os, shutil, sys, tempfile, urllib2
from optparse import OptionParser
tmpeggs = tempfile.mkdtemp()
is_jython = sys.platform.startswith('java')
# parsing arguments
parser = OptionParser()
parser.add_option("-v", "--version", dest="version",
help="use a specific zc.buildout version")
parser.add_option("-d", "--distribute",
action="store_true", dest="distribute", default=False,
help="Use Disribute rather than Setuptools.")
parser.add_option("-c", None, action="store", dest="config_file",
help=("Specify the path to the buildout configuration "
"file to be used."))
options, args = parser.parse_args()
# if -c was provided, we push it back into args for buildout' main function
if options.config_file is not None:
args += ['-c', options.config_file]
if options.version is not None:
VERSION = '==%s' % options.version
else:
VERSION = ''
# We decided to always use distribute, make sure this is the default for us
# USE_DISTRIBUTE = options.distribute
USE_DISTRIBUTE = True
args = args + ['bootstrap']
to_reload = False
try:
import pkg_resources
if not hasattr(pkg_resources, '_distribute'):
to_reload = True
raise ImportError
except ImportError:
ez = {}
if USE_DISTRIBUTE:
exec urllib2.urlopen('http://python-distribute.org/distribute_setup.py'
).read() in ez
ez['use_setuptools'](to_dir=tmpeggs, download_delay=0, no_fake=True)
else:
exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
).read() in ez
ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
if to_reload:
reload(pkg_resources)
else:
import pkg_resources
if sys.platform == 'win32':
def quote(c):
if ' ' in c:
return '"%s"' % c # work around spawn lamosity on windows
else:
return c
else:
def quote (c):
return c
cmd = 'from setuptools.command.easy_install import main; main()'
ws = pkg_resources.working_set
if USE_DISTRIBUTE:
requirement = 'distribute'
else:
requirement = 'setuptools'
if is_jython:
import subprocess
assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd',
quote(tmpeggs), 'zc.buildout' + VERSION],
env=dict(os.environ,
PYTHONPATH=
ws.find(pkg_resources.Requirement.parse(requirement)).location
),
).wait() == 0
else:
assert os.spawnle(
os.P_WAIT, sys.executable, quote (sys.executable),
'-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout' + VERSION,
dict(os.environ,
PYTHONPATH=
ws.find(pkg_resources.Requirement.parse(requirement)).location
),
) == 0
ws.add_entry(tmpeggs)
ws.require('zc.buildout' + VERSION)
import zc.buildout.buildout
zc.buildout.buildout.main(args)
shutil.rmtree(tmpeggs)

84
buildout.cfg Normal file
View File

@ -0,0 +1,84 @@
[buildout]
package-name = croniter
develop = .
parts =
scripts
omelette
test
coverage
report
report-xml
extensions =
mr.developer
buildout.minitagificator
buildout.dumppickedversions
auto-checkout =
sources-dir=${buildout:directory}/src.mrdeveloper
test-eggs= ${buildout:package-name} [test]
eggs = ${buildout:package-name}
[sources]
[scripts]
recipe=zc.recipe.egg
eggs = ${buildout:eggs}
zest.releaser
ipython
interpreter = scripts
scripts =
ipython
croniter
fullrelease
paster
nose
nosetests
fullrelease
lasttagdiff
lasttaglog
longtest
postrelease
prerelease
release
rst2html.py
rst2latex.py
rst2man.py
rst2odt_prepstyles.py
rst2odt.py
rst2pseudoxml.py
rst2s5.py
rst2xetex.py
rst2xml.py
rstpep2html.py
[test]
recipe = zc.recipe.testrunner
defaults = ['-v', '-s', '${buildout:package-name}']
eggs = ${buildout:test-eggs}
[coverage]
recipe = zc.recipe.egg
eggs = coverage
initialization =
include = '--source=${buildout:directory}/src'
sys.argv = sys.argv[:] + ['run', include, 'bin/test', '--xml']
[report]
recipe = zc.recipe.egg
eggs = coverage
scripts = coverage=report
initialization =
sys.argv = sys.argv[:] + ['html', '-i']
[report-xml]
recipe = zc.recipe.egg
eggs = coverage
scripts = coverage=report-xml
initialization =
sys.argv = sys.argv[:] + ['xml', '-i']
[omelette]
recipe = collective.recipe.omelette
eggs = ${scripts:eggs}
[versions]

View File

@ -1,9 +0,0 @@
# -*- coding: utf-8 -*-
# defer imports to be accesible in setup.py
from _release import (
__doc__,
__author__,
__version__,
__license__,
)
from croniter import croniter

View File

@ -1,43 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = "Matsumoto Taichi"
__version__ = "0.3.2"
__license__ = "MIT License"
__doc__ = """
Simple example of usage is followings
>>> from croniter import croniter
>>> from datetime import datetime
>>> base = datetime(2010, 1, 25, 4, 46)
>>> iter = croniter('*/5 * * * *', base) # every 5 minites
>>> print iter.get_next(datetime) # 2010-01-25 04:50:00
>>> print iter.get_next(datetime) # 2010-01-25 04:55:00
>>> print iter.get_next(datetime) # 2010-01-25 05:00:00
>>>
>>> iter = croniter('2 4 * * mon,fri', base) # 04:02 on every Monday and Friday
>>> print iter.get_next(datetime) # 2010-01-26 04:02:00
>>> print iter.get_next(datetime) # 2010-01-30 04:02:00
>>> print iter.get_next(datetime) # 2010-02-02 04:02:00
All you need to know is constructor and get_next, these signature are following.
>>> def __init__(self, cron_format, start_time=time.time())
croniter iterate along with 'cron_format' from 'start_time'.
cron_format is 'min hour day month day_of_week', and please refer to
http://en.wikipedia.org/wiki/Cron for details.
>>> def get_next(self, ret_type=float)
get_next return next time in iteration with 'ret_type'.
And ret_type accept only 'float' or 'datetime'.
Now, supported get_prev method. (>= 0.2.0)
>>> base = datetime(2010, 8, 25)
>>> itr = croniter('0 0 1 * *', base)
>>> print itr.get_prev(datetime) # 2010-08-01 00:00:00
>>> print itr.get_prev(datetime) # 2010-07-01 00:00:00
>>> print itr.get_prev(datetime) # 2010-06-01 00:00:00
"""
# vim:set et sts=4 ts=4 tw=80:

View File

@ -1,305 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import unittest
from datetime import datetime
from croniter import croniter
class CroniterTest(unittest.TestCase):
def testSecond(self):
base = datetime(2012, 4, 6, 13, 26, 10)
itr = croniter('*/1 * * * * *', base)
n1 = itr.get_next(datetime)
self.assertEqual(base.year, n1.year)
self.assertEqual(base.month, n1.month)
self.assertEqual(base.day, n1.day)
self.assertEqual(base.hour, n1.hour)
self.assertEqual(base.minute, n1.minute)
self.assertEqual(base.second + 1, n1.second)
def testMinute(self):
# minute asterisk
base = datetime(2010, 1, 23, 12, 18)
itr = croniter('*/1 * * * *', base)
n1 = itr.get_next(datetime) # 19
self.assertEqual(base.year, n1.year)
self.assertEqual(base.month, n1.month)
self.assertEqual(base.day, n1.day)
self.assertEqual(base.hour, n1.hour)
self.assertEqual(base.minute, n1.minute - 1)
for i in range(39): # ~ 58
itr.get_next()
n2 = itr.get_next(datetime)
self.assertEqual(n2.minute, 59)
n3 = itr.get_next(datetime)
self.assertEqual(n3.minute, 0)
self.assertEqual(n3.hour, 13)
itr = croniter('*/5 * * * *', base)
n4 = itr.get_next(datetime)
self.assertEqual(n4.minute, 20)
for i in range(6):
itr.get_next()
n5 = itr.get_next(datetime)
self.assertEqual(n5.minute, 55)
n6 = itr.get_next(datetime)
self.assertEqual(n6.minute, 0)
self.assertEqual(n6.hour, 13)
def testHour(self):
base = datetime(2010, 1, 24, 12, 2)
itr = croniter('0 */3 * * *', base)
n1 = itr.get_next(datetime)
self.assertEqual(n1.hour, 15)
self.assertEqual(n1.minute, 0)
for i in range(2):
itr.get_next()
n2 = itr.get_next(datetime)
self.assertEqual(n2.hour, 0)
self.assertEqual(n2.day, 25)
def testDay(self):
base = datetime(2010, 2, 24, 12, 9)
itr = croniter('0 0 */3 * *', base)
n1 = itr.get_next(datetime)
self.assertEqual(n1.day, 27)
n2 = itr.get_next(datetime)
self.assertEqual(n2.day, 3)
# test leap year
base = datetime(1996, 2, 27)
itr = croniter('0 0 * * *', base)
n1 = itr.get_next(datetime)
self.assertEqual(n1.day, 28)
self.assertEqual(n1.month, 2)
n2 = itr.get_next(datetime)
self.assertEqual(n2.day, 29)
self.assertEqual(n2.month, 2)
base2 = datetime(2000, 2, 27)
itr2 = croniter('0 0 * * *', base2)
n3 = itr2.get_next(datetime)
self.assertEqual(n3.day, 28)
self.assertEqual(n3.month, 2)
n4 = itr2.get_next(datetime)
self.assertEqual(n4.day, 29)
self.assertEqual(n4.month, 2)
def testWeekDay(self):
base = datetime(2010, 2, 25)
itr = croniter('0 0 * * sat', base)
n1 = itr.get_next(datetime)
self.assertEqual(n1.isoweekday(), 6)
self.assertEqual(n1.day, 27)
n2 = itr.get_next(datetime)
self.assertEqual(n2.isoweekday(), 6)
self.assertEqual(n2.day, 6)
self.assertEqual(n2.month, 3)
base = datetime(2010, 1, 25)
itr = croniter('0 0 1 * wed', base)
n1 = itr.get_next(datetime)
self.assertEqual(n1.month, 1)
self.assertEqual(n1.day, 27)
self.assertEqual(n1.year, 2010)
n2 = itr.get_next(datetime)
self.assertEqual(n2.month, 2)
self.assertEqual(n2.day, 1)
self.assertEqual(n2.year, 2010)
n3 = itr.get_next(datetime)
self.assertEqual(n3.month, 2)
self.assertEqual(n3.day, 3)
self.assertEqual(n3.year, 2010)
def testMonth(self):
base = datetime(2010, 1, 25)
itr = croniter('0 0 1 * *', base)
n1 = itr.get_next(datetime)
self.assertEqual(n1.month, 2)
self.assertEqual(n1.day, 1)
n2 = itr.get_next(datetime)
self.assertEqual(n2.month, 3)
self.assertEqual(n2.day, 1)
for i in range(8):
itr.get_next()
n3 = itr.get_next(datetime)
self.assertEqual(n3.month, 12)
self.assertEqual(n3.year, 2010)
n4 = itr.get_next(datetime)
self.assertEqual(n4.month, 1)
self.assertEqual(n4.year, 2011)
def testError(self):
itr = croniter('* * * * *')
self.assertRaises(TypeError, itr.get_next, str)
self.assertRaises(ValueError, croniter, '* * * *')
self.assertRaises(ValueError, croniter, '* * 5-1 * *')
self.assertRaises(KeyError, croniter, '* * * janu-jun *')
def testPrevMinute(self):
base = datetime(2010, 8, 25, 15, 56)
itr = croniter('*/1 * * * *', base)
prev = itr.get_prev(datetime)
self.assertEqual(base.year, prev.year)
self.assertEqual(base.month, prev.month)
self.assertEqual(base.day, prev.day)
self.assertEqual(base.hour, prev.hour)
self.assertEqual(base.minute, prev.minute+1)
base = datetime(2010, 8, 25, 15, 0)
itr = croniter('*/1 * * * *', base)
prev = itr.get_prev(datetime)
self.assertEqual(base.year, prev.year)
self.assertEqual(base.month, prev.month)
self.assertEqual(base.day, prev.day)
self.assertEqual(base.hour, prev.hour+1)
self.assertEqual(59, prev.minute)
base = datetime(2010, 8, 25, 0, 0)
itr = croniter('*/1 * * * *', base)
prev = itr.get_prev(datetime)
self.assertEqual(base.year, prev.year)
self.assertEqual(base.month, prev.month)
self.assertEqual(base.day, prev.day+1)
self.assertEqual(23, prev.hour)
self.assertEqual(59, prev.minute)
def testPrevDayOfMonthWithCrossing(self):
"""Test getting previous occurrence that crosses into previous month."""
base = datetime(2012, 3, 15, 0, 0)
itr = croniter('0 0 22 * *', base)
prev = itr.get_prev(datetime)
self.assertEqual(prev.year, 2012)
self.assertEqual(prev.month, 2)
self.assertEqual(prev.day, 22)
self.assertEqual(prev.hour, 0)
self.assertEqual(prev.minute, 0)
def testPrevWeekDay(self):
base = datetime(2010, 8, 25, 15, 56)
itr = croniter('0 0 * * sat,sun', base)
prev1 = itr.get_prev(datetime)
self.assertEqual(prev1.year, base.year)
self.assertEqual(prev1.month, base.month)
self.assertEqual(prev1.day, 22)
self.assertEqual(prev1.hour, 0)
self.assertEqual(prev1.minute, 0)
prev2 = itr.get_prev(datetime)
self.assertEqual(prev2.year, base.year)
self.assertEqual(prev2.month, base.month)
self.assertEqual(prev2.day, 21)
self.assertEqual(prev2.hour, 0)
self.assertEqual(prev2.minute, 0)
prev3 = itr.get_prev(datetime)
self.assertEqual(prev3.year, base.year)
self.assertEqual(prev3.month, base.month)
self.assertEqual(prev3.day, 15)
self.assertEqual(prev3.hour, 0)
self.assertEqual(prev3.minute, 0)
def testPrevWeekDay2(self):
base = datetime(2010, 8, 25, 15, 56)
itr = croniter('10 0 * * 0', base)
prev = itr.get_prev(datetime)
self.assertEqual(prev.day, 22)
self.assertEqual(prev.hour, 0)
self.assertEqual(prev.minute, 10)
def testISOWeekday(self):
base = datetime(2010, 2, 25)
itr = croniter('0 0 * * 7', base)
n1 = itr.get_next(datetime)
self.assertEqual(n1.isoweekday(), 7)
self.assertEqual(n1.day, 28)
n2 = itr.get_next(datetime)
self.assertEqual(n2.isoweekday(), 7)
self.assertEqual(n2.day, 7)
self.assertEqual(n2.month, 3)
def testBug1(self):
base = datetime(2012, 2, 24)
itr = croniter('5 0 */2 * *', base)
n1 = itr.get_prev(datetime)
self.assertEqual(n1.day, 22)
self.assertEqual(n1.hour, 0)
self.assertEqual(n1.minute, 5)
def testBug2(self):
base = datetime(2012, 01, 01, 00, 00)
iter = croniter('0 * * 3 *', base)
n1 = iter.get_next(datetime)
self.assertEqual(n1.year, base.year)
self.assertEqual(n1.month, 3)
self.assertEqual(n1.day, base.day)
self.assertEqual(n1.hour, base.hour)
self.assertEqual(n1.minute, base.minute)
n2 = iter.get_next(datetime)
self.assertEqual(n2.year, base.year)
self.assertEqual(n2.month, 3)
self.assertEqual(n2.day, base.day)
self.assertEqual(n2.hour, base.hour + 1)
self.assertEqual(n2.minute, base.minute)
n3 = iter.get_next(datetime)
self.assertEqual(n3.year, base.year)
self.assertEqual(n3.month, 3)
self.assertEqual(n3.day, base.day)
self.assertEqual(n3.hour, base.hour + 2)
self.assertEqual(n3.minute, base.minute)
def testPreviousHour(self):
base = datetime(2012, 6, 23, 17, 41)
itr = croniter('* 10 * * *', base)
prev1 = itr.get_prev(datetime)
self.assertEqual(prev1.year, base.year)
self.assertEqual(prev1.month, base.month)
self.assertEqual(prev1.day, base.day)
self.assertEqual(prev1.hour, 10)
self.assertEqual(prev1.minute, 59)
def testPreviousDay(self):
base = datetime(2012, 6, 27, 00, 15)
itr = croniter('* * 26 * *', base)
prev1 = itr.get_prev(datetime)
self.assertEqual(prev1.year, base.year)
self.assertEqual(prev1.month, base.month)
self.assertEqual(prev1.day, 26)
self.assertEqual(prev1.hour, 23)
self.assertEqual(prev1.minute, 59)
def testPreviousMonth(self):
base = datetime(2012, 6, 18, 00, 15)
itr = croniter('* * * 5 *', base)
prev1 = itr.get_prev(datetime)
self.assertEqual(prev1.year, base.year)
self.assertEqual(prev1.month, 5)
self.assertEqual(prev1.day, 31)
self.assertEqual(prev1.hour, 23)
self.assertEqual(prev1.minute, 59)
def testPreviousDow(self):
base = datetime(2012, 5, 13, 18, 48)
itr = croniter('* * * * sat', base)
prev1 = itr.get_prev(datetime)
self.assertEqual(prev1.year, base.year)
self.assertEqual(prev1.month, base.month)
self.assertEqual(prev1.day, 12)
self.assertEqual(prev1.hour, 23)
self.assertEqual(prev1.minute, 59)
def testGetCurrent(self):
base = datetime(2012, 9, 25, 11, 24)
itr = croniter('* * * * *', base)
res = itr.get_current(datetime)
self.assertEqual(base.year, res.year)
self.assertEqual(base.month, res.month)
self.assertEqual(base.day, res.day)
self.assertEqual(base.hour, res.hour)
self.assertEqual(base.minute, res.minute)
if __name__ == '__main__':
unittest.main()

7
docs/CHANGES.rst Normal file
View File

@ -0,0 +1,7 @@
Changelog
==============
0.3.3 (unreleased)
-------------------
- proper packaging

View File

@ -1,25 +1,42 @@
# -*- coding: utf-8 -*-
from setuptools import setup
__version__, __doc__, __license__, __author__ = None, None, None, None
# get __version__, __doc__, __license__, __author__
execfile("croniter/_release.py")
import os
from setuptools import setup, find_packages
def read(*rnames):
return open(
os.path.join('.', *rnames)
).read()
long_description = "\n\n".join(
[read('README.rst'),
read('docs', 'CHANGES.rst'),
]
)
setup(
packages = ('croniter',),
name = 'croniter',
version = __version__,
py_modules = ['croniter', 'croniter_test'],
version = "0.3.3dev",
py_modules = ['croniter', ],
description = 'croniter provides iteration for datetime object with cron like format',
long_description = __doc__,
author = __author__,
author_email = 'taichino@gmail.com',
long_description = long_description,
author = "Matsumoto Taichi, kiorky",
author_email = 'taichino@gmail.com, kiorky@cryptelium.net',
url = 'http://github.com/taichino/croniter',
keywords = 'datetime, iterator, cron',
install_requires = ["python-dateutil", "setuptools",],
license = __license__,
install_requires = ["python-dateutil", "zope.interface",
"setuptools",],
license = "MIT License",
classifiers = ["Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: POSIX",
"Programming Language :: Python",
"Topic :: Software Development :: Libraries :: Python Modules"]
"Topic :: Software Development :: Libraries :: Python Modules"],
packages=find_packages('src'),
package_dir = {'': 'src'},
include_package_data=True,
extras_require = {
'test': [
'plone.testing',
],
},
)

2
src/croniter/__init__.py Normal file
View File

@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
from croniter import croniter

16
src/croniter/testing.py Normal file
View File

@ -0,0 +1,16 @@
from plone.testing.layer import Layer as Base
class Layer(Base):
defaultBases = tuple()
class IntegrationLayer(Layer):
"""."""
class FunctionnalLayer(IntegrationLayer):
"""."""
CRONITER_FIXTURE = Layer()
CRONITER_INTEGRATION_TESTING = IntegrationLayer()
CRONITER_FUNCTIONAL_TESTING = FunctionnalLayer()

View File

View File

@ -0,0 +1,44 @@
import unittest2 as unittest
from croniter.testing import (
CRONITER_FIXTURE as UNIT_TESTING,
CRONITER_INTEGRATION_TESTING as INTEGRATION_TESTING,
CRONITER_FUNCTIONAL_TESTING as FUNCTIONAL_TESTING,
)
from croniter.tests.globals import *
"""
Lot of files generated by the collective.generic packages will try to load user defined objects in user specific files.
The final goal is to regenerate easyly the test infrastructure on templates updates without impacting
user-specific test boilerplate.
We do not use paster local commands (insert/update) as it cannot determine witch is specific or not and we prefer to totally
separe generated stuff and what is user specific
"""
class TestCase(unittest.TestCase):
"""We use this base class for all the tests in this package.
If necessary, we can put common utility or setup code in here.
"""
layer = UNIT_TESTING
def setUp(self):
super(TestCase, self).setUp()
class IntegrationTestCase(TestCase):
"""Integration base TestCase."""
layer = INTEGRATION_TESTING
class FunctionalTestCase(TestCase):
"""Functionnal base TestCase."""
layer = FUNCTIONAL_TESTING
# vim:set ft=python:

View File

@ -0,0 +1,9 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__docformat__ = 'restructuredtext en'
from pprint import pprint
from copy import deepcopy as dc
# vim:set et sts=4 ts=4 tw=80:

View File

@ -0,0 +1,308 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import unittest
from datetime import datetime
from croniter import croniter
from croniter.tests import base
class CroniterTest(base.TestCase):
def testSecond(self):
base = datetime(2012, 4, 6, 13, 26, 10)
itr = croniter('*/1 * * * * *', base)
n1 = itr.get_next(datetime)
self.assertEqual(base.year, n1.year)
self.assertEqual(base.month, n1.month)
self.assertEqual(base.day, n1.day)
self.assertEqual(base.hour, n1.hour)
self.assertEqual(base.minute, n1.minute)
self.assertEqual(base.second + 1, n1.second)
def testMinute(self):
# minute asterisk
base = datetime(2010, 1, 23, 12, 18)
itr = croniter('*/1 * * * *', base)
n1 = itr.get_next(datetime) # 19
self.assertEqual(base.year, n1.year)
self.assertEqual(base.month, n1.month)
self.assertEqual(base.day, n1.day)
self.assertEqual(base.hour, n1.hour)
self.assertEqual(base.minute, n1.minute - 1)
for i in range(39): # ~ 58
itr.get_next()
n2 = itr.get_next(datetime)
self.assertEqual(n2.minute, 59)
n3 = itr.get_next(datetime)
self.assertEqual(n3.minute, 0)
self.assertEqual(n3.hour, 13)
itr = croniter('*/5 * * * *', base)
n4 = itr.get_next(datetime)
self.assertEqual(n4.minute, 20)
for i in range(6):
itr.get_next()
n5 = itr.get_next(datetime)
self.assertEqual(n5.minute, 55)
n6 = itr.get_next(datetime)
self.assertEqual(n6.minute, 0)
self.assertEqual(n6.hour, 13)
def testHour(self):
base = datetime(2010, 1, 24, 12, 2)
itr = croniter('0 */3 * * *', base)
n1 = itr.get_next(datetime)
self.assertEqual(n1.hour, 15)
self.assertEqual(n1.minute, 0)
for i in range(2):
itr.get_next()
n2 = itr.get_next(datetime)
self.assertEqual(n2.hour, 0)
self.assertEqual(n2.day, 25)
def testDay(self):
base = datetime(2010, 2, 24, 12, 9)
itr = croniter('0 0 */3 * *', base)
n1 = itr.get_next(datetime)
self.assertEqual(n1.day, 27)
n2 = itr.get_next(datetime)
self.assertEqual(n2.day, 3)
# test leap year
base = datetime(1996, 2, 27)
itr = croniter('0 0 * * *', base)
n1 = itr.get_next(datetime)
self.assertEqual(n1.day, 28)
self.assertEqual(n1.month, 2)
n2 = itr.get_next(datetime)
self.assertEqual(n2.day, 29)
self.assertEqual(n2.month, 2)
base2 = datetime(2000, 2, 27)
itr2 = croniter('0 0 * * *', base2)
n3 = itr2.get_next(datetime)
self.assertEqual(n3.day, 28)
self.assertEqual(n3.month, 2)
n4 = itr2.get_next(datetime)
self.assertEqual(n4.day, 29)
self.assertEqual(n4.month, 2)
def testWeekDay(self):
base = datetime(2010, 2, 25)
itr = croniter('0 0 * * sat', base)
n1 = itr.get_next(datetime)
self.assertEqual(n1.isoweekday(), 6)
self.assertEqual(n1.day, 27)
n2 = itr.get_next(datetime)
self.assertEqual(n2.isoweekday(), 6)
self.assertEqual(n2.day, 6)
self.assertEqual(n2.month, 3)
base = datetime(2010, 1, 25)
itr = croniter('0 0 1 * wed', base)
n1 = itr.get_next(datetime)
self.assertEqual(n1.month, 1)
self.assertEqual(n1.day, 27)
self.assertEqual(n1.year, 2010)
n2 = itr.get_next(datetime)
self.assertEqual(n2.month, 2)
self.assertEqual(n2.day, 1)
self.assertEqual(n2.year, 2010)
n3 = itr.get_next(datetime)
self.assertEqual(n3.month, 2)
self.assertEqual(n3.day, 3)
self.assertEqual(n3.year, 2010)
def testMonth(self):
base = datetime(2010, 1, 25)
itr = croniter('0 0 1 * *', base)
n1 = itr.get_next(datetime)
self.assertEqual(n1.month, 2)
self.assertEqual(n1.day, 1)
n2 = itr.get_next(datetime)
self.assertEqual(n2.month, 3)
self.assertEqual(n2.day, 1)
for i in range(8):
itr.get_next()
n3 = itr.get_next(datetime)
self.assertEqual(n3.month, 12)
self.assertEqual(n3.year, 2010)
n4 = itr.get_next(datetime)
self.assertEqual(n4.month, 1)
self.assertEqual(n4.year, 2011)
def testError(self):
itr = croniter('* * * * *')
self.assertRaises(TypeError, itr.get_next, str)
self.assertRaises(ValueError, croniter, '* * * *')
self.assertRaises(ValueError, croniter, '* * 5-1 * *')
self.assertRaises(KeyError, croniter, '* * * janu-jun *')
def testPrevMinute(self):
base = datetime(2010, 8, 25, 15, 56)
itr = croniter('*/1 * * * *', base)
prev = itr.get_prev(datetime)
self.assertEqual(base.year, prev.year)
self.assertEqual(base.month, prev.month)
self.assertEqual(base.day, prev.day)
self.assertEqual(base.hour, prev.hour)
self.assertEqual(base.minute, prev.minute+1)
base = datetime(2010, 8, 25, 15, 0)
itr = croniter('*/1 * * * *', base)
prev = itr.get_prev(datetime)
self.assertEqual(base.year, prev.year)
self.assertEqual(base.month, prev.month)
self.assertEqual(base.day, prev.day)
self.assertEqual(base.hour, prev.hour+1)
self.assertEqual(59, prev.minute)
base = datetime(2010, 8, 25, 0, 0)
itr = croniter('*/1 * * * *', base)
prev = itr.get_prev(datetime)
self.assertEqual(base.year, prev.year)
self.assertEqual(base.month, prev.month)
self.assertEqual(base.day, prev.day+1)
self.assertEqual(23, prev.hour)
self.assertEqual(59, prev.minute)
def testPrevDayOfMonthWithCrossing(self):
"""Test getting previous occurrence that crosses into previous month."""
base = datetime(2012, 3, 15, 0, 0)
itr = croniter('0 0 22 * *', base)
prev = itr.get_prev(datetime)
self.assertEqual(prev.year, 2012)
self.assertEqual(prev.month, 2)
self.assertEqual(prev.day, 22)
self.assertEqual(prev.hour, 0)
self.assertEqual(prev.minute, 0)
def testPrevWeekDay(self):
base = datetime(2010, 8, 25, 15, 56)
itr = croniter('0 0 * * sat,sun', base)
prev1 = itr.get_prev(datetime)
self.assertEqual(prev1.year, base.year)
self.assertEqual(prev1.month, base.month)
self.assertEqual(prev1.day, 22)
self.assertEqual(prev1.hour, 0)
self.assertEqual(prev1.minute, 0)
prev2 = itr.get_prev(datetime)
self.assertEqual(prev2.year, base.year)
self.assertEqual(prev2.month, base.month)
self.assertEqual(prev2.day, 21)
self.assertEqual(prev2.hour, 0)
self.assertEqual(prev2.minute, 0)
prev3 = itr.get_prev(datetime)
self.assertEqual(prev3.year, base.year)
self.assertEqual(prev3.month, base.month)
self.assertEqual(prev3.day, 15)
self.assertEqual(prev3.hour, 0)
self.assertEqual(prev3.minute, 0)
def testPrevWeekDay2(self):
base = datetime(2010, 8, 25, 15, 56)
itr = croniter('10 0 * * 0', base)
prev = itr.get_prev(datetime)
self.assertEqual(prev.day, 22)
self.assertEqual(prev.hour, 0)
self.assertEqual(prev.minute, 10)
def testISOWeekday(self):
base = datetime(2010, 2, 25)
itr = croniter('0 0 * * 7', base)
n1 = itr.get_next(datetime)
self.assertEqual(n1.isoweekday(), 7)
self.assertEqual(n1.day, 28)
n2 = itr.get_next(datetime)
self.assertEqual(n2.isoweekday(), 7)
self.assertEqual(n2.day, 7)
self.assertEqual(n2.month, 3)
def testBug1(self):
base = datetime(2012, 2, 24)
itr = croniter('5 0 */2 * *', base)
n1 = itr.get_prev(datetime)
self.assertEqual(n1.day, 22)
self.assertEqual(n1.hour, 0)
self.assertEqual(n1.minute, 5)
def testBug2(self):
base = datetime(2012, 01, 01, 00, 00)
iter = croniter('0 * * 3 *', base)
n1 = iter.get_next(datetime)
self.assertEqual(n1.year, base.year)
self.assertEqual(n1.month, 3)
self.assertEqual(n1.day, base.day)
self.assertEqual(n1.hour, base.hour)
self.assertEqual(n1.minute, base.minute)
n2 = iter.get_next(datetime)
self.assertEqual(n2.year, base.year)
self.assertEqual(n2.month, 3)
self.assertEqual(n2.day, base.day)
self.assertEqual(n2.hour, base.hour + 1)
self.assertEqual(n2.minute, base.minute)
n3 = iter.get_next(datetime)
self.assertEqual(n3.year, base.year)
self.assertEqual(n3.month, 3)
self.assertEqual(n3.day, base.day)
self.assertEqual(n3.hour, base.hour + 2)
self.assertEqual(n3.minute, base.minute)
def testPreviousHour(self):
base = datetime(2012, 6, 23, 17, 41)
itr = croniter('* 10 * * *', base)
prev1 = itr.get_prev(datetime)
self.assertEqual(prev1.year, base.year)
self.assertEqual(prev1.month, base.month)
self.assertEqual(prev1.day, base.day)
self.assertEqual(prev1.hour, 10)
self.assertEqual(prev1.minute, 59)
def testPreviousDay(self):
base = datetime(2012, 6, 27, 00, 15)
itr = croniter('* * 26 * *', base)
prev1 = itr.get_prev(datetime)
self.assertEqual(prev1.year, base.year)
self.assertEqual(prev1.month, base.month)
self.assertEqual(prev1.day, 26)
self.assertEqual(prev1.hour, 23)
self.assertEqual(prev1.minute, 59)
def testPreviousMonth(self):
base = datetime(2012, 6, 18, 00, 15)
itr = croniter('* * * 5 *', base)
prev1 = itr.get_prev(datetime)
self.assertEqual(prev1.year, base.year)
self.assertEqual(prev1.month, 5)
self.assertEqual(prev1.day, 31)
self.assertEqual(prev1.hour, 23)
self.assertEqual(prev1.minute, 59)
def testPreviousDow(self):
base = datetime(2012, 5, 13, 18, 48)
itr = croniter('* * * * sat', base)
prev1 = itr.get_prev(datetime)
self.assertEqual(prev1.year, base.year)
self.assertEqual(prev1.month, base.month)
self.assertEqual(prev1.day, 12)
self.assertEqual(prev1.hour, 23)
self.assertEqual(prev1.minute, 59)
def testGetCurrent(self):
base = datetime(2012, 9, 25, 11, 24)
itr = croniter('* * * * *', base)
res = itr.get_current(datetime)
self.assertEqual(base.year, res.year)
self.assertEqual(base.month, res.month)
self.assertEqual(base.day, res.day)
self.assertEqual(base.hour, res.hour)
self.assertEqual(base.minute, res.minute)
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1,56 @@
"""
Launching all doctests in the tests directory using:
- the base layer in testing.py
"""
from croniter.tests.base import FunctionalTestCase
# GLOBALS avalaible in doctests
# IMPORT/DEFINE objects there or inside ./user_globals.py (better)
# globals from the testing product are also available.
# example:
# from for import bar
# and in your doctests, you can do:
# >>> bar.something
from croniter.tests.globals import *
from croniter.testing import CRONITER_FUNCTIONAL_TESTING as FUNCTIONAL_TESTING
import unittest2 as unittest
import glob
import os
import logging
import doctest
from plone.testing import layered
optionflags = (doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE| doctest.REPORT_ONLY_FIRST_FAILURE)
def test_suite():
"""."""
logger = logging.getLogger('croniter')
cwd = os.path.dirname(__file__)
files = []
try:
files = glob.glob(os.path.join(cwd, '*txt'))
files += glob.glob(os.path.join(cwd, '*rst'))
except Exception,e:
logger.warn('No doctests for croniter')
suite = unittest.TestSuite()
globs = globals()
for s in files:
suite.addTests([
layered(
doctest.DocFileSuite(
s,
globs = globs,
module_relative=False,
optionflags=optionflags,
),
layer=FUNCTIONAL_TESTING
),
])
return suite

View File

@ -1,10 +1,13 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import unittest
import time
from datetime import datetime, date
from croniter import croniter
from croniter.tests import base
class timerTest(object):
def __init__(self):
self.tests = tuple(getattr(self, m) for m in dir(self) if m.lower().startswith('test'))
@ -12,7 +15,6 @@ class timerTest(object):
def run(self):
for test in self.tests:
test()
class CroniterTest(timerTest):
def testMinute(self):
@ -205,8 +207,14 @@ class CroniterTest(timerTest):
n2 = itr.get_next(datetime)
n2.isoweekday() == 7
n2.day == 7
n2.month == 3
n2.month == 3
class TestCase(base.TestCase):
"""make zope.testrunner happy"""
def test_Noop(self):
self.assertEqual(1,1)
if __name__ == '__main__':
from timeit import Timer
t = Timer('c=CroniterTest();c.run()', 'from __main__ import CroniterTest')