From aea721becd4bbd844329a62a26035837e973eb15 Mon Sep 17 00:00:00 2001 From: Gerhard Weis Date: Fri, 6 Jan 2012 13:24:37 +1000 Subject: * support Python 3 * moved tests package into isolate package --- CHANGES.txt | 5 + setup.py | 16 +- src/isodate/isostrf.py | 2 +- src/isodate/tests/__init__.py | 45 ++++ src/isodate/tests/test_date.py | 122 ++++++++++ src/isodate/tests/test_datetime.py | 110 +++++++++ src/isodate/tests/test_duration.py | 479 +++++++++++++++++++++++++++++++++++++ src/isodate/tests/test_time.py | 139 +++++++++++ src/tests/__init__.py | 45 ---- src/tests/test_date.py | 122 ---------- src/tests/test_datetime.py | 110 --------- src/tests/test_duration.py | 473 ------------------------------------ src/tests/test_time.py | 139 ----------- 13 files changed, 914 insertions(+), 893 deletions(-) create mode 100644 src/isodate/tests/__init__.py create mode 100644 src/isodate/tests/test_date.py create mode 100644 src/isodate/tests/test_datetime.py create mode 100644 src/isodate/tests/test_duration.py create mode 100644 src/isodate/tests/test_time.py delete mode 100644 src/tests/__init__.py delete mode 100644 src/tests/test_date.py delete mode 100644 src/tests/test_datetime.py delete mode 100644 src/tests/test_duration.py delete mode 100644 src/tests/test_time.py diff --git a/CHANGES.txt b/CHANGES.txt index e68b105..cb1a7a0 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,11 @@ CHANGES ======= +0.4.6 (2012-01-06) +------------------ + +- added Python 3 compatibility via 2to3 + 0.4.5 (2012-01-06) ------------------ diff --git a/setup.py b/setup.py index f565c3b..21e5418 100644 --- a/setup.py +++ b/setup.py @@ -29,18 +29,26 @@ import os setupargs = {} +try: + from distutils.command.build_py import build_py_2to3 as build_py +except ImportError: + # 2.x + from distutils.command.build_py import build_py + try: from setuptools import setup - setupargs['test_suite'] = 'tests.test_suite' + setupargs['test_suite'] = 'isodate.tests.test_suite' + setupargs['use_2to3'] = True except ImportError: from distutils.core import setup + setupargs['cmdclass'] = {'build_py': build_py} def read(*rnames): return open(os.path.join(os.path.dirname(__file__), *rnames)).read() setup(name='isodate', - version='0.4.5', - packages=['isodate',], + version='0.4.6', + packages=['isodate', 'isodate.tests'], package_dir={'': 'src'}, # dependencies: @@ -64,6 +72,8 @@ setup(name='isodate', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 3', 'Topic :: Internet', 'Topic :: Software Development :: Libraries :: Python Modules', ], diff --git a/src/isodate/isostrf.py b/src/isodate/isostrf.py index 13480e0..e492a39 100644 --- a/src/isodate/isostrf.py +++ b/src/isodate/isostrf.py @@ -159,7 +159,7 @@ def _strfduration(tdt, format, yeardigits=4): # at least one component has to be there. return ret and ''.join(ret) or '0D' elif match.group(0) == '%p': - return str(abs(tdt.days / 7)) + 'W' + return str(abs(tdt.days // 7)) + 'W' return match.group(0) return re.sub('%d|%f|%H|%m|%M|%S|%W|%Y|%C|%%|%P|%p', repl, format) diff --git a/src/isodate/tests/__init__.py b/src/isodate/tests/__init__.py new file mode 100644 index 0000000..67512d0 --- /dev/null +++ b/src/isodate/tests/__init__.py @@ -0,0 +1,45 @@ +############################################################################## +# Copyright 2009, Gerhard Weis +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the authors nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT +############################################################################## +''' +Collect all test suites into one TestSuite instance. +''' + +import unittest +from isodate.tests import test_date, test_time, test_datetime, test_duration + +def test_suite(): + ''' + Return a new TestSuite instance consisting of all available TestSuites. + ''' + return unittest.TestSuite([ + test_date.test_suite(), + test_time.test_suite(), + test_datetime.test_suite(), + test_duration.test_suite()]) + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite') diff --git a/src/isodate/tests/test_date.py b/src/isodate/tests/test_date.py new file mode 100644 index 0000000..fb6ba8c --- /dev/null +++ b/src/isodate/tests/test_date.py @@ -0,0 +1,122 @@ +############################################################################## +# Copyright 2009, Gerhard Weis +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the authors nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT +############################################################################## +''' +Test cases for the isodate module. +''' +import unittest +from datetime import date +from isodate import parse_date, ISO8601Error, date_isoformat +from isodate import DATE_CENTURY, DATE_YEAR, DATE_MONTH +from isodate import DATE_EXT_COMPLETE, DATE_BAS_COMPLETE +from isodate import DATE_BAS_ORD_COMPLETE, DATE_EXT_ORD_COMPLETE +from isodate import DATE_BAS_WEEK, DATE_BAS_WEEK_COMPLETE +from isodate import DATE_EXT_WEEK, DATE_EXT_WEEK_COMPLETE + +# the following list contains tuples of ISO date strings and the expected +# result from the parse_date method. A result of None means an ISO8601Error +# is expected. The test cases are grouped into dates with 4 digit years +# and 6 digit years. +TEST_CASES = {4: [('19', date(1901, 1, 1), DATE_CENTURY), + ('1985', date(1985, 1, 1), DATE_YEAR), + ('1985-04', date(1985, 4, 1), DATE_MONTH), + ('1985-04-12', date(1985, 4, 12), DATE_EXT_COMPLETE), + ('19850412', date(1985, 4, 12), DATE_BAS_COMPLETE), + ('1985102', date(1985, 4, 12), DATE_BAS_ORD_COMPLETE), + ('1985-102', date(1985, 4, 12), DATE_EXT_ORD_COMPLETE), + ('1985W155', date(1985, 4, 12), DATE_BAS_WEEK_COMPLETE), + ('1985-W15-5', date(1985, 4, 12), DATE_EXT_WEEK_COMPLETE), + ('1985W15', date(1985, 4, 8), DATE_BAS_WEEK), + ('1985-W15', date(1985, 4, 8), DATE_EXT_WEEK), + ('1989-W15', date(1989, 4, 10), DATE_EXT_WEEK), + ('1989-W15-5', date(1989, 4, 14), DATE_EXT_WEEK_COMPLETE), + ('1-W1-1', None, DATE_BAS_WEEK_COMPLETE)], + 6: [('+0019', date(1901, 1, 1), DATE_CENTURY), + ('+001985', date(1985, 1, 1), DATE_YEAR), + ('+001985-04', date(1985, 4, 1), DATE_MONTH), + ('+001985-04-12', date(1985, 4, 12), DATE_EXT_COMPLETE), + ('+0019850412', date(1985, 4, 12), DATE_BAS_COMPLETE), + ('+001985102', date(1985, 4, 12), DATE_BAS_ORD_COMPLETE), + ('+001985-102', date(1985, 4, 12), DATE_EXT_ORD_COMPLETE), + ('+001985W155', date(1985, 4, 12), DATE_BAS_WEEK_COMPLETE), + ('+001985-W15-5', date(1985, 4, 12), DATE_EXT_WEEK_COMPLETE), + ('+001985W15', date(1985, 4, 8), DATE_BAS_WEEK), + ('+001985-W15', date(1985, 4, 8), DATE_EXT_WEEK)]} + +def create_testcase(yeardigits, datestring, expectation, format): + ''' + Create a TestCase class for a specific test. + + This allows having a separate TestCase for each test tuple from the + TEST_CASES list, so that a failed test won't stop other tests. + ''' + + class TestDate(unittest.TestCase): + ''' + A test case template to parse an ISO date string into a date + object. + ''' + + def test_parse(self): + ''' + Parse an ISO date string and compare it to the expected value. + ''' + if expectation is None: + self.assertRaises(ISO8601Error, parse_date, datestring, + yeardigits) + else: + result = parse_date(datestring, yeardigits) + self.assertEqual(result, expectation) + + def test_format(self): + ''' + Take date object and create ISO string from it. + This is the reverse test to test_parse. + ''' + if expectation is None: + self.assertRaises(AttributeError, + date_isoformat, expectation, format, + yeardigits) + else: + self.assertEqual(date_isoformat(expectation, format, + yeardigits), + datestring) + + return unittest.TestLoader().loadTestsFromTestCase(TestDate) + +def test_suite(): + ''' + Construct a TestSuite instance for all test cases. + ''' + suite = unittest.TestSuite() + for yeardigits, tests in TEST_CASES.items(): + for datestring, expectation, format in tests: + suite.addTest(create_testcase(yeardigits, datestring, + expectation, format)) + return suite + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite') diff --git a/src/isodate/tests/test_datetime.py b/src/isodate/tests/test_datetime.py new file mode 100644 index 0000000..fd50039 --- /dev/null +++ b/src/isodate/tests/test_datetime.py @@ -0,0 +1,110 @@ +############################################################################## +# Copyright 2009, Gerhard Weis +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the authors nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT +############################################################################## +''' +Test cases for the isodatetime module. +''' +import unittest +from datetime import datetime + +from isodate import parse_datetime, UTC, FixedOffset, datetime_isoformat +from isodate import DATE_BAS_COMPLETE, TIME_BAS_MINUTE, TIME_BAS_COMPLETE +from isodate import DATE_EXT_COMPLETE, TIME_EXT_MINUTE +from isodate import TZ_BAS, TZ_EXT, TZ_HOUR +from isodate import DATE_BAS_ORD_COMPLETE, DATE_EXT_ORD_COMPLETE +from isodate import DATE_BAS_WEEK_COMPLETE, DATE_EXT_WEEK_COMPLETE + +# the following list contains tuples of ISO datetime strings and the expected +# result from the parse_datetime method. A result of None means an ISO8601Error +# is expected. +TEST_CASES = [('19850412T1015', datetime(1985, 4, 12, 10, 15), + DATE_BAS_COMPLETE + 'T' + TIME_BAS_MINUTE), + ('1985-04-12T10:15', datetime(1985, 4, 12, 10, 15), + DATE_EXT_COMPLETE + 'T' + TIME_EXT_MINUTE), + ('1985102T1015Z', datetime(1985, 4, 12, 10, 15, tzinfo=UTC), + DATE_BAS_ORD_COMPLETE + 'T' + TIME_BAS_MINUTE + TZ_BAS), + ('1985-102T10:15Z', datetime(1985, 4, 12, 10, 15, tzinfo=UTC), + DATE_EXT_ORD_COMPLETE + 'T' + TIME_EXT_MINUTE + TZ_EXT), + ('1985W155T1015+0400', datetime(1985, 4, 12, 10, 15, + tzinfo=FixedOffset(4, 0, + '+0400')), + DATE_BAS_WEEK_COMPLETE + 'T' + TIME_BAS_MINUTE + TZ_BAS), + ('1985-W15-5T10:15+04', datetime(1985, 4, 12, 10, 15, + tzinfo=FixedOffset(4, 0, + '+0400')), + DATE_EXT_WEEK_COMPLETE + 'T' + TIME_EXT_MINUTE + TZ_HOUR), + ('20110410T101225.123000Z', + datetime(2011, 4, 10, 10, 12, 25, 123000, tzinfo=UTC), + DATE_BAS_COMPLETE + 'T' + TIME_BAS_COMPLETE + ".%f" + TZ_BAS)] + + +def create_testcase(datetimestring, expectation, format): + """ + Create a TestCase class for a specific test. + + This allows having a separate TestCase for each test tuple from the + TEST_CASES list, so that a failed test won't stop other tests. + """ + + class TestDateTime(unittest.TestCase): + ''' + A test case template to parse an ISO datetime string into a + datetime object. + ''' + + def test_parse(self): + ''' + Parse an ISO datetime string and compare it to the expected value. + ''' + result = parse_datetime(datetimestring) + self.assertEqual(result, expectation) + + def test_format(self): + ''' + Take datetime object and create ISO string from it. + This is the reverse test to test_parse. + ''' + if expectation is None: + self.assertRaises(AttributeError, + datetime_isoformat, expectation, format) + else: + self.assertEqual(datetime_isoformat(expectation, format), + datetimestring) + + return unittest.TestLoader().loadTestsFromTestCase(TestDateTime) + + +def test_suite(): + ''' + Construct a TestSuite instance for all test cases. + ''' + suite = unittest.TestSuite() + for datetimestring, expectation, format in TEST_CASES: + suite.addTest(create_testcase(datetimestring, expectation, format)) + return suite + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite') diff --git a/src/isodate/tests/test_duration.py b/src/isodate/tests/test_duration.py new file mode 100644 index 0000000..d8b4cf2 --- /dev/null +++ b/src/isodate/tests/test_duration.py @@ -0,0 +1,479 @@ +############################################################################## +# Copyright 2009, Gerhard Weis +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the authors nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT +############################################################################## +''' +Test cases for the isoduration module. +''' +import unittest +import operator +from datetime import timedelta, date, datetime + +from isodate import Duration, parse_duration, ISO8601Error +from isodate import D_DEFAULT, D_WEEK, D_ALT_EXT, duration_isoformat + +# the following list contains tuples of ISO duration strings and the expected +# result from the parse_duration method. A result of None means an ISO8601Error +# is expected. +PARSE_TEST_CASES = {'P18Y9M4DT11H9M8S': (Duration(4, 8, 0, 0, 9, 11, 0, 9, 18), + D_DEFAULT, None), + 'P2W': (timedelta(weeks=2), D_WEEK, None), + 'P3Y6M4DT12H30M5S': (Duration(4, 5, 0, 0, 30, 12, 0, 6, 3), + D_DEFAULT, None), + 'P23DT23H': (timedelta(hours=23, days=23), + D_DEFAULT, None), + 'P4Y': (Duration(years=4), D_DEFAULT, None), + 'P1M': (Duration(months=1), D_DEFAULT, None), + 'PT1M': (timedelta(minutes=1), D_DEFAULT, None), + 'P0.5Y': (Duration(years=0.5), D_DEFAULT, None), + 'PT36H': (timedelta(hours=36), D_DEFAULT, 'P1DT12H'), + 'P1DT12H': (timedelta(days=1, hours=12), D_DEFAULT, None), + '+P11D': (timedelta(days=11), D_DEFAULT, 'P11D'), + '-P2W': (timedelta(weeks=-2), D_WEEK, None), + '-P2.2W': (timedelta(weeks=-2.2), D_DEFAULT, + '-P15DT9H36M'), + 'P1DT2H3M4S': (timedelta(days=1, hours=2, minutes=3, + seconds=4), D_DEFAULT, None), + 'P1DT2H3M': (timedelta(days=1, hours=2, minutes=3), + D_DEFAULT, None), + 'P1DT2H': (timedelta(days=1, hours=2), D_DEFAULT, None), + 'PT2H': (timedelta(hours=2), D_DEFAULT, None), + 'PT2.3H': (timedelta(hours=2.3), D_DEFAULT, 'PT2H18M'), + 'PT2H3M4S': (timedelta(hours=2, minutes=3, seconds=4), + D_DEFAULT, None), + 'PT3M4S': (timedelta(minutes=3, seconds=4), D_DEFAULT, + None), + 'PT22S': (timedelta(seconds=22), D_DEFAULT, None), + 'PT22.22S': (timedelta(seconds=22.22), 'PT%S.%fS', + 'PT22.220000S'), + '-P2Y': (Duration(years=-2), D_DEFAULT, None), + '-P3Y6M4DT12H30M5S': (Duration(-4, -5, 0, 0, -30, -12, 0, + -6, -3), D_DEFAULT, None), + '-P1DT2H3M4S': (timedelta(days=-1, hours=-2, minutes=-3, + seconds=-4), D_DEFAULT, None), + # alternative format + 'P0018-09-04T11:09:08': (Duration(4, 8, 0, 0, 9, 11, 0, 9, + 18), D_ALT_EXT, None), + #'PT000022.22': timedelta(seconds=22.22), + } + +# d1 d2 '+', '-', '>' +# A list of test cases to test addition and subtraction between datetime and +# Duration objects. +# each tuple contains 2 duration strings, and a result string for addition and +# one for subtraction. The last value says, if the first duration is greater +# than the second. +MATH_TEST_CASES = (('P5Y7M1DT9H45M16.72S', 'PT27M24.68S', + 'P5Y7M1DT10H12M41.4S', 'P5Y7M1DT9H17M52.04S', None), + ('PT28M12.73S', 'PT56M29.92S', + 'PT1H24M42.65S', '-PT28M17.19S', False), + ('P3Y7M23DT5H25M0.33S', 'PT1H1.95S', + 'P3Y7M23DT6H25M2.28S', 'P3Y7M23DT4H24M58.38S', None), + ('PT1H1.95S', 'P3Y7M23DT5H25M0.33S', + 'P3Y7M23DT6H25M2.28S', '-P3Y7M23DT4H24M58.38S', None), + ('P1332DT55M0.33S', 'PT1H1.95S', + 'P1332DT1H55M2.28S', 'P1331DT23H54M58.38S', True), + ('PT1H1.95S', 'P1332DT55M0.33S', + 'P1332DT1H55M2.28S', '-P1331DT23H54M58.38S', False)) + +# A list of test cases to test addition and subtraction of date/datetime +# and Duration objects. They are tested against the results of an +# equal long timedelta duration. +DATE_TEST_CASES = ( (date(2008, 2, 29), + timedelta(days=10, hours=12, minutes=20), + Duration(days=10, hours=12, minutes=20)), + (date(2008, 1, 31), + timedelta(days=10, hours=12, minutes=20), + Duration(days=10, hours=12, minutes=20)), + (datetime(2008, 2, 29), + timedelta(days=10, hours=12, minutes=20), + Duration(days=10, hours=12, minutes=20)), + (datetime(2008, 1, 31), + timedelta(days=10, hours=12, minutes=20), + Duration(days=10, hours=12, minutes=20)), + (datetime(2008, 4, 21), + timedelta(days=10, hours=12, minutes=20), + Duration(days=10, hours=12, minutes=20)), + (datetime(2008, 5, 5), + timedelta(days=10, hours=12, minutes=20), + Duration(days=10, hours=12, minutes=20)), + (datetime(2000, 1, 1), + timedelta(hours=-33), + Duration(hours=-33)), + (datetime(2008, 5, 5), + Duration(years=1, months=1, days=10, hours=12, + minutes=20), + Duration(months=13, days=10, hours=12, minutes=20)), + (datetime(2000, 3, 30), + Duration(years=1, months=1, days=10, hours=12, + minutes=20), + Duration(months=13, days=10, hours=12, minutes=20)), + ) + +# A list of test cases of additon of date/datetime and Duration. The results +# are compared against a given expected result. +DATE_CALC_TEST_CASES = ( + (date(2000, 2, 1), + Duration(years=1, months=1), + date(2001, 3, 1)), + (date(2000, 2, 29), + Duration(years=1, months=1), + date(2001, 3, 29)), + (date(2000, 2, 29), + Duration(years=1), + date(2001, 2, 28)), + (date(1996, 2, 29), + Duration(years=4), + date(2000, 2, 29)), + (date(2096, 2, 29), + Duration(years=4), + date(2100, 2, 28)), + (date(2000, 2, 1), + Duration(years=-1, months=-1), + date(1999, 1, 1)), + (date(2000, 2, 29), + Duration(years=-1, months=-1), + date(1999, 1, 29)), + (date(2000, 2, 1), + Duration(years=1, months=1, days=1), + date(2001, 3, 2)), + (date(2000, 2, 29), + Duration(years=1, months=1, days=1), + date(2001, 3, 30)), + (date(2000, 2, 29), + Duration(years=1, days=1), + date(2001, 3, 1)), + (date(1996, 2, 29), + Duration(years=4, days=1), + date(2000, 3, 1)), + (date(2096, 2, 29), + Duration(years=4, days=1), + date(2100, 3, 1)), + (date(2000, 2, 1), + Duration(years=-1, months=-1, days=-1), + date(1998, 12, 31)), + (date(2000, 2, 29), + Duration(years=-1, months=-1, days=-1), + date(1999, 1, 28)), + (date(2001, 4, 1), + Duration(years=-1, months=-1, days=-1), + date(2000, 2, 29)), + (date(2000, 4, 1), + Duration(years=-1, months=-1, days=-1), + date(1999, 2, 28)), + (Duration(years=1, months=2), + Duration(years=0, months=0, days=1), + Duration(years=1, months=2, days=1)), + (Duration(years=-1, months=-1, days=-1), + date(2000, 4, 1), + date(1999, 2, 28)), + (Duration(years=1, months=1, weeks=5), + date(2000, 1, 30), + date(2001, 4, 4)), + (Duration(years=1, months=1, weeks=5), + 'raise exception', + None), + ('raise exception', + Duration(years=1, months=1, weeks=5), + None), + (Duration(years=1, months=2), + timedelta(days=1), + Duration(years=1, months=2, days=1)), + (timedelta(days=1), + Duration(years=1, months=2), + Duration(years=1, months=2, days=1)), + #(date(2000, 1, 1), + # Duration(years=1.5), + # date(2001, 6, 1)), + #(date(2000, 1, 1), + # Duration(years=1, months=1.5), + # date(2001, 2, 14)), + ) + + +class DurationTest(unittest.TestCase): + ''' + This class tests various other aspects of the isoduration module, + which are not covered with the test cases listed above. + ''' + + def test_associative(self): + ''' + Adding 2 durations to a date is not associative. + ''' + days1 = Duration(days=1) + months1 = Duration(months=1) + start = date(2000, 3, 30) + res1 = start + days1 + months1 + res2 = start + months1 + days1 + self.assertNotEqual(res1, res2) + + def test_typeerror(self): + ''' + Test if TypError is raised with certain parameters. + ''' + self.assertRaises(TypeError, parse_duration, date(2000, 1, 1)) + self.assertRaises(TypeError, operator.sub, Duration(years=1), + date(2000, 1, 1)) + self.assertRaises(TypeError, operator.sub, 'raise exc', + Duration(years=1)) + + def test_parseerror(self): + ''' + Test for unparseable duration string. + ''' + self.assertRaises(ISO8601Error, parse_duration, 'T10:10:10') + + def test_repr(self): + ''' + Test __repr__ and __str__ for Duration obqects. + ''' + dur = Duration(10, 10, years=10, months=10) + self.assertEqual('10 years, 10 months, 10 days, 0:00:10', str(dur)) + self.assertEqual('isodate.duration.Duration(10, 10, 0,' + ' years=10, months=10)', repr(dur)) + + def test_neg(self): + ''' + Test __neg__ for Duration objects. + ''' + self.assertEqual(-Duration(0), Duration(0)) + self.assertEqual(-Duration(years=1, months=1), + Duration(years=-1, months=-1)) + self.assertEqual(-Duration(years=1, months=1), Duration(months=-13)) + self.assertNotEqual(-Duration(years=1), timedelta(days=-365)) + self.assertNotEqual(-timedelta(days=365), Duration(years=-1)) + # FIXME: this test fails in python 3... it seems like python3 + # treats a == b the same b == a + #self.assertNotEqual(-timedelta(days=10), -Duration(days=10)) + + def test_format(self): + ''' + Test various other strftime combinations. + ''' + self.assertEqual(duration_isoformat(Duration(0)), 'P0D') + self.assertEqual(duration_isoformat(-Duration(0)), 'P0D') + self.assertEqual(duration_isoformat(Duration(seconds=10)), 'PT10S') + self.assertEqual(duration_isoformat(Duration(years=-1, months=-1)), + '-P1Y1M') + self.assertEqual(duration_isoformat(-Duration(years=1, months=1)), + '-P1Y1M') + self.assertEqual(duration_isoformat(-Duration(years=-1, months=-1)), + 'P1Y1M') + self.assertEqual(duration_isoformat(-Duration(years=-1, months=-1)), + 'P1Y1M') + dur = Duration(years=3, months=7, days=23, hours=5, minutes=25, + milliseconds=330) + self.assertEqual(duration_isoformat(dur), 'P3Y7M23DT5H25M0.33S') + self.assertEqual(duration_isoformat(-dur), '-P3Y7M23DT5H25M0.33S') + + + def test_equal(self): + ''' + Test __eq__ and __ne__ methods. + ''' + self.assertEqual(Duration(years=1, months=1), + Duration(years=1, months=1)) + self.assertEqual(Duration(years=1, months=1), Duration(months=13)) + self.assertNotEqual(Duration(years=1, months=2), + Duration(years=1, months=1)) + self.assertNotEqual(Duration(years=1, months=1), Duration(months=14)) + self.assertNotEqual(Duration(years=1), timedelta(days=365)) + self.assertFalse(Duration(years=1, months=1) != + Duration(years=1, months=1)) + self.assertFalse(Duration(years=1, months=1) != Duration(months=13)) + self.assertTrue(Duration(years=1, months=2) != + Duration(years=1, months=1)) + self.assertTrue(Duration(years=1, months=1) != Duration(months=14)) + self.assertTrue(Duration(years=1) != timedelta(days=365)) + self.assertEqual(Duration(days=1), timedelta(days=1)) + # FIXME: this test fails in python 3... it seems like python3 + # treats a != b the same b != a + #self.assertNotEqual(timedelta(days=1), Duration(days=1)) + + +def create_parsetestcase(durationstring, expectation, format, altstr): + """ + Create a TestCase class for a specific test. + + This allows having a separate TestCase for each test tuple from the + PARSE_TEST_CASES list, so that a failed test won't stop other tests. + """ + + class TestParseDuration(unittest.TestCase): + ''' + A test case template to parse an ISO duration string into a + timedelta or Duration object. + ''' + + def test_parse(self): + ''' + Parse an ISO duration string and compare it to the expected value. + ''' + result = parse_duration(durationstring) + self.assertEqual(result, expectation) + + def test_format(self): + ''' + Take duration/timedelta object and create ISO string from it. + This is the reverse test to test_parse. + ''' + if altstr: + self.assertEqual(duration_isoformat(expectation, format), + altstr) + else: + # if durationstring == '-P2W': + # import pdb; pdb.set_trace() + self.assertEqual(duration_isoformat(expectation, format), + durationstring) + + return unittest.TestLoader().loadTestsFromTestCase(TestParseDuration) + + +def create_mathtestcase(dur1, dur2, resadd, ressub, resge): + """ + Create a TestCase class for a specific test. + + This allows having a separate TestCase for each test tuple from the + MATH_TEST_CASES list, so that a failed test won't stop other tests. + """ + + dur1 = parse_duration(dur1) + dur2 = parse_duration(dur2) + resadd = parse_duration(resadd) + ressub = parse_duration(ressub) + + class TestMathDuration(unittest.TestCase): + ''' + A test case template test addition, subtraction and > + operators for Duration objects. + ''' + + def test_add(self): + ''' + Test operator + (__add__, __radd__) + ''' + self.assertEqual(dur1 + dur2, resadd) + + def test_sub(self): + ''' + Test operator - (__sub__, __rsub__) + ''' + self.assertEqual(dur1 - dur2, ressub) + + def test_ge(self): + ''' + Test operator > and < + ''' + def dogetest(): + ''' Test greater than.''' + return dur1 > dur2 + + def doletest(): + ''' Test less than.''' + return dur1 < dur2 + if resge is None: + self.assertRaises(TypeError, dogetest) + self.assertRaises(TypeError, doletest) + else: + self.assertEqual(dogetest(), resge) + self.assertEqual(doletest(), not resge) + + return unittest.TestLoader().loadTestsFromTestCase(TestMathDuration) + + +def create_datetestcase(start, tdelta, duration): + """ + Create a TestCase class for a specific test. + + This allows having a separate TestCase for each test tuple from the + DATE_TEST_CASES list, so that a failed test won't stop other tests. + """ + + class TestDateCalc(unittest.TestCase): + ''' + A test case template test addition, subtraction + operators for Duration objects. + ''' + + def test_add(self): + ''' + Test operator +. + ''' + self.assertEqual(start + tdelta, start + duration) + + def test_sub(self): + ''' + Test operator -. + ''' + self.assertEqual(start - tdelta, start - duration) + + return unittest.TestLoader().loadTestsFromTestCase(TestDateCalc) + + +def create_datecalctestcase(start, duration, expectation): + """ + Create a TestCase class for a specific test. + + This allows having a separate TestCase for each test tuple from the + DATE_CALC_TEST_CASES list, so that a failed test won't stop other tests. + """ + + class TestDateCalc(unittest.TestCase): + ''' + A test case template test addition operators for Duration objects. + ''' + + def test_calc(self): + ''' + Test operator +. + ''' + if expectation is None: + self.assertRaises(TypeError, operator.add, start, duration) + else: + self.assertEqual(start + duration, expectation) + + return unittest.TestLoader().loadTestsFromTestCase(TestDateCalc) + + +def test_suite(): + ''' + Return a test suite containing all test defined above. + ''' + suite = unittest.TestSuite() + for durationstring, (expectation, format, altstr) in PARSE_TEST_CASES.items(): + suite.addTest(create_parsetestcase(durationstring, expectation, + format, altstr)) + for testdata in MATH_TEST_CASES: + suite.addTest(create_mathtestcase(*testdata)) + for testdata in DATE_TEST_CASES: + suite.addTest(create_datetestcase(*testdata)) + for testdata in DATE_CALC_TEST_CASES: + suite.addTest(create_datecalctestcase(*testdata)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase(DurationTest)) + return suite + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite') diff --git a/src/isodate/tests/test_time.py b/src/isodate/tests/test_time.py new file mode 100644 index 0000000..d71a3e2 --- /dev/null +++ b/src/isodate/tests/test_time.py @@ -0,0 +1,139 @@ +############################################################################## +# Copyright 2009, Gerhard Weis +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the authors nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT +############################################################################## +''' +Test cases for the isotime module. +''' +import unittest +from datetime import time + +from isodate import parse_time, UTC, FixedOffset, ISO8601Error, time_isoformat +from isodate import TIME_BAS_COMPLETE, TIME_BAS_MINUTE +from isodate import TIME_EXT_COMPLETE, TIME_EXT_MINUTE +from isodate import TIME_HOUR +from isodate import TZ_BAS, TZ_EXT, TZ_HOUR + +# the following list contains tuples of ISO time strings and the expected +# result from the parse_time method. A result of None means an ISO8601Error +# is expected. +TEST_CASES = [('232050', time(23, 20, 50), TIME_BAS_COMPLETE + TZ_BAS), + ('23:20:50', time(23, 20, 50), TIME_EXT_COMPLETE + TZ_EXT), + ('2320', time(23, 20), TIME_BAS_MINUTE), + ('23:20', time(23, 20), TIME_EXT_MINUTE), + ('23', time(23), TIME_HOUR), + ('232050,5', time(23, 20, 50, 500000), None), + ('23:20:50.5', time(23, 20, 50, 500000), None), + # test precision + ('15:33:42.123456', time(15, 33, 42, 123456), None), + ('15:33:42.1234564', time(15, 33, 42, 123456), None), + ('15:33:42.1234557', time(15, 33, 42, 123456), None), + ('2320,8', time(23, 20, 48), None), + ('23:20,8', time(23, 20, 48), None), + ('23,3', time(23, 18), None), + ('232030Z', time(23, 20, 30, tzinfo=UTC), + TIME_BAS_COMPLETE + TZ_BAS), + ('2320Z', time(23, 20, tzinfo=UTC), TIME_BAS_MINUTE + TZ_BAS), + ('23Z', time(23, tzinfo=UTC), TIME_HOUR + TZ_BAS), + ('23:20:30Z', time(23, 20, 30, tzinfo=UTC), + TIME_EXT_COMPLETE + TZ_EXT), + ('23:20Z', time(23, 20, tzinfo=UTC), TIME_EXT_MINUTE + TZ_EXT), + ('152746+0100', time(15, 27, 46, + tzinfo=FixedOffset(1, 0, '+0100')), + TIME_BAS_COMPLETE + TZ_BAS), + ('152746-0500', time(15, 27, 46, + tzinfo=FixedOffset(-5, 0, '-0500')), + TIME_BAS_COMPLETE + TZ_BAS), + ('152746+01', time(15, 27, 46, + tzinfo=FixedOffset(1, 0, '+01:00')), + TIME_BAS_COMPLETE + TZ_HOUR), + ('152746-05', time(15, 27, 46, + tzinfo=FixedOffset(-5, -0, '-05:00')), + TIME_BAS_COMPLETE + TZ_HOUR), + ('15:27:46+01:00', time(15, 27, 46, + tzinfo=FixedOffset(1, 0, '+01:00')), + TIME_EXT_COMPLETE + TZ_EXT), + ('15:27:46-05:00', time(15, 27, 46, + tzinfo=FixedOffset(-5, -0, '-05:00')), + TIME_EXT_COMPLETE + TZ_EXT), + ('15:27:46+01', time(15, 27, 46, + tzinfo=FixedOffset(1, 0, '+01:00')), + TIME_EXT_COMPLETE + TZ_HOUR), + ('15:27:46-05', time(15, 27, 46, + tzinfo=FixedOffset(-5, -0, '-05:00')), + TIME_EXT_COMPLETE + TZ_HOUR), + ('1:17:30', None, TIME_EXT_COMPLETE)] + + +def create_testcase(timestring, expectation, format): + """ + Create a TestCase class for a specific test. + + This allows having a separate TestCase for each test tuple from the + TEST_CASES list, so that a failed test won't stop other tests. + """ + + class TestTime(unittest.TestCase): + ''' + A test case template to parse an ISO time string into a time + object. + ''' + + def test_parse(self): + ''' + Parse an ISO time string and compare it to the expected value. + ''' + if expectation is None: + self.assertRaises(ISO8601Error, parse_time, timestring) + else: + result = parse_time(timestring) + self.assertEqual(result, expectation) + + def test_format(self): + ''' + Take time object and create ISO string from it. + This is the reverse test to test_parse. + ''' + if expectation is None: + self.assertRaises(AttributeError, + time_isoformat, expectation, format) + elif format is not None: + self.assertEqual(time_isoformat(expectation, format), + timestring) + + return unittest.TestLoader().loadTestsFromTestCase(TestTime) + + +def test_suite(): + ''' + Construct a TestSuite instance for all test cases. + ''' + suite = unittest.TestSuite() + for timestring, expectation, format in TEST_CASES: + suite.addTest(create_testcase(timestring, expectation, format)) + return suite + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite') diff --git a/src/tests/__init__.py b/src/tests/__init__.py deleted file mode 100644 index b9783f8..0000000 --- a/src/tests/__init__.py +++ /dev/null @@ -1,45 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -Collect all test suites into one TestSuite instance. -''' - -import unittest -from tests import test_date, test_time, test_datetime, test_duration - -def test_suite(): - ''' - Return a new TestSuite instance consisting of all available TestSuites. - ''' - return unittest.TestSuite([ - test_date.test_suite(), - test_time.test_suite(), - test_datetime.test_suite(), - test_duration.test_suite()]) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff --git a/src/tests/test_date.py b/src/tests/test_date.py deleted file mode 100644 index fb6ba8c..0000000 --- a/src/tests/test_date.py +++ /dev/null @@ -1,122 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -Test cases for the isodate module. -''' -import unittest -from datetime import date -from isodate import parse_date, ISO8601Error, date_isoformat -from isodate import DATE_CENTURY, DATE_YEAR, DATE_MONTH -from isodate import DATE_EXT_COMPLETE, DATE_BAS_COMPLETE -from isodate import DATE_BAS_ORD_COMPLETE, DATE_EXT_ORD_COMPLETE -from isodate import DATE_BAS_WEEK, DATE_BAS_WEEK_COMPLETE -from isodate import DATE_EXT_WEEK, DATE_EXT_WEEK_COMPLETE - -# the following list contains tuples of ISO date strings and the expected -# result from the parse_date method. A result of None means an ISO8601Error -# is expected. The test cases are grouped into dates with 4 digit years -# and 6 digit years. -TEST_CASES = {4: [('19', date(1901, 1, 1), DATE_CENTURY), - ('1985', date(1985, 1, 1), DATE_YEAR), - ('1985-04', date(1985, 4, 1), DATE_MONTH), - ('1985-04-12', date(1985, 4, 12), DATE_EXT_COMPLETE), - ('19850412', date(1985, 4, 12), DATE_BAS_COMPLETE), - ('1985102', date(1985, 4, 12), DATE_BAS_ORD_COMPLETE), - ('1985-102', date(1985, 4, 12), DATE_EXT_ORD_COMPLETE), - ('1985W155', date(1985, 4, 12), DATE_BAS_WEEK_COMPLETE), - ('1985-W15-5', date(1985, 4, 12), DATE_EXT_WEEK_COMPLETE), - ('1985W15', date(1985, 4, 8), DATE_BAS_WEEK), - ('1985-W15', date(1985, 4, 8), DATE_EXT_WEEK), - ('1989-W15', date(1989, 4, 10), DATE_EXT_WEEK), - ('1989-W15-5', date(1989, 4, 14), DATE_EXT_WEEK_COMPLETE), - ('1-W1-1', None, DATE_BAS_WEEK_COMPLETE)], - 6: [('+0019', date(1901, 1, 1), DATE_CENTURY), - ('+001985', date(1985, 1, 1), DATE_YEAR), - ('+001985-04', date(1985, 4, 1), DATE_MONTH), - ('+001985-04-12', date(1985, 4, 12), DATE_EXT_COMPLETE), - ('+0019850412', date(1985, 4, 12), DATE_BAS_COMPLETE), - ('+001985102', date(1985, 4, 12), DATE_BAS_ORD_COMPLETE), - ('+001985-102', date(1985, 4, 12), DATE_EXT_ORD_COMPLETE), - ('+001985W155', date(1985, 4, 12), DATE_BAS_WEEK_COMPLETE), - ('+001985-W15-5', date(1985, 4, 12), DATE_EXT_WEEK_COMPLETE), - ('+001985W15', date(1985, 4, 8), DATE_BAS_WEEK), - ('+001985-W15', date(1985, 4, 8), DATE_EXT_WEEK)]} - -def create_testcase(yeardigits, datestring, expectation, format): - ''' - Create a TestCase class for a specific test. - - This allows having a separate TestCase for each test tuple from the - TEST_CASES list, so that a failed test won't stop other tests. - ''' - - class TestDate(unittest.TestCase): - ''' - A test case template to parse an ISO date string into a date - object. - ''' - - def test_parse(self): - ''' - Parse an ISO date string and compare it to the expected value. - ''' - if expectation is None: - self.assertRaises(ISO8601Error, parse_date, datestring, - yeardigits) - else: - result = parse_date(datestring, yeardigits) - self.assertEqual(result, expectation) - - def test_format(self): - ''' - Take date object and create ISO string from it. - This is the reverse test to test_parse. - ''' - if expectation is None: - self.assertRaises(AttributeError, - date_isoformat, expectation, format, - yeardigits) - else: - self.assertEqual(date_isoformat(expectation, format, - yeardigits), - datestring) - - return unittest.TestLoader().loadTestsFromTestCase(TestDate) - -def test_suite(): - ''' - Construct a TestSuite instance for all test cases. - ''' - suite = unittest.TestSuite() - for yeardigits, tests in TEST_CASES.items(): - for datestring, expectation, format in tests: - suite.addTest(create_testcase(yeardigits, datestring, - expectation, format)) - return suite - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff --git a/src/tests/test_datetime.py b/src/tests/test_datetime.py deleted file mode 100644 index fd50039..0000000 --- a/src/tests/test_datetime.py +++ /dev/null @@ -1,110 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -Test cases for the isodatetime module. -''' -import unittest -from datetime import datetime - -from isodate import parse_datetime, UTC, FixedOffset, datetime_isoformat -from isodate import DATE_BAS_COMPLETE, TIME_BAS_MINUTE, TIME_BAS_COMPLETE -from isodate import DATE_EXT_COMPLETE, TIME_EXT_MINUTE -from isodate import TZ_BAS, TZ_EXT, TZ_HOUR -from isodate import DATE_BAS_ORD_COMPLETE, DATE_EXT_ORD_COMPLETE -from isodate import DATE_BAS_WEEK_COMPLETE, DATE_EXT_WEEK_COMPLETE - -# the following list contains tuples of ISO datetime strings and the expected -# result from the parse_datetime method. A result of None means an ISO8601Error -# is expected. -TEST_CASES = [('19850412T1015', datetime(1985, 4, 12, 10, 15), - DATE_BAS_COMPLETE + 'T' + TIME_BAS_MINUTE), - ('1985-04-12T10:15', datetime(1985, 4, 12, 10, 15), - DATE_EXT_COMPLETE + 'T' + TIME_EXT_MINUTE), - ('1985102T1015Z', datetime(1985, 4, 12, 10, 15, tzinfo=UTC), - DATE_BAS_ORD_COMPLETE + 'T' + TIME_BAS_MINUTE + TZ_BAS), - ('1985-102T10:15Z', datetime(1985, 4, 12, 10, 15, tzinfo=UTC), - DATE_EXT_ORD_COMPLETE + 'T' + TIME_EXT_MINUTE + TZ_EXT), - ('1985W155T1015+0400', datetime(1985, 4, 12, 10, 15, - tzinfo=FixedOffset(4, 0, - '+0400')), - DATE_BAS_WEEK_COMPLETE + 'T' + TIME_BAS_MINUTE + TZ_BAS), - ('1985-W15-5T10:15+04', datetime(1985, 4, 12, 10, 15, - tzinfo=FixedOffset(4, 0, - '+0400')), - DATE_EXT_WEEK_COMPLETE + 'T' + TIME_EXT_MINUTE + TZ_HOUR), - ('20110410T101225.123000Z', - datetime(2011, 4, 10, 10, 12, 25, 123000, tzinfo=UTC), - DATE_BAS_COMPLETE + 'T' + TIME_BAS_COMPLETE + ".%f" + TZ_BAS)] - - -def create_testcase(datetimestring, expectation, format): - """ - Create a TestCase class for a specific test. - - This allows having a separate TestCase for each test tuple from the - TEST_CASES list, so that a failed test won't stop other tests. - """ - - class TestDateTime(unittest.TestCase): - ''' - A test case template to parse an ISO datetime string into a - datetime object. - ''' - - def test_parse(self): - ''' - Parse an ISO datetime string and compare it to the expected value. - ''' - result = parse_datetime(datetimestring) - self.assertEqual(result, expectation) - - def test_format(self): - ''' - Take datetime object and create ISO string from it. - This is the reverse test to test_parse. - ''' - if expectation is None: - self.assertRaises(AttributeError, - datetime_isoformat, expectation, format) - else: - self.assertEqual(datetime_isoformat(expectation, format), - datetimestring) - - return unittest.TestLoader().loadTestsFromTestCase(TestDateTime) - - -def test_suite(): - ''' - Construct a TestSuite instance for all test cases. - ''' - suite = unittest.TestSuite() - for datetimestring, expectation, format in TEST_CASES: - suite.addTest(create_testcase(datetimestring, expectation, format)) - return suite - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff --git a/src/tests/test_duration.py b/src/tests/test_duration.py deleted file mode 100644 index bcc98eb..0000000 --- a/src/tests/test_duration.py +++ /dev/null @@ -1,473 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -Test cases for the isoduration module. -''' -import unittest -import operator -from datetime import timedelta, date, datetime - -from isodate import Duration, parse_duration, ISO8601Error -from isodate import D_DEFAULT, D_WEEK, D_ALT_EXT, duration_isoformat - -# the following list contains tuples of ISO duration strings and the expected -# result from the parse_duration method. A result of None means an ISO8601Error -# is expected. -PARSE_TEST_CASES = {'P18Y9M4DT11H9M8S': (Duration(4, 8, 0, 0, 9, 11, 0, 9, 18), - D_DEFAULT, None), - 'P2W': (timedelta(weeks=2), D_WEEK, None), - 'P3Y6M4DT12H30M5S': (Duration(4, 5, 0, 0, 30, 12, 0, 6, 3), - D_DEFAULT, None), - 'P23DT23H': (timedelta(hours=23, days=23), - D_DEFAULT, None), - 'P4Y': (Duration(years=4), D_DEFAULT, None), - 'P1M': (Duration(months=1), D_DEFAULT, None), - 'PT1M': (timedelta(minutes=1), D_DEFAULT, None), - 'P0.5Y': (Duration(years=0.5), D_DEFAULT, None), - 'PT36H': (timedelta(hours=36), D_DEFAULT, 'P1DT12H'), - 'P1DT12H': (timedelta(days=1, hours=12), D_DEFAULT, None), - '+P11D': (timedelta(days=11), D_DEFAULT, 'P11D'), - '-P2W': (timedelta(weeks=-2), D_WEEK, None), - '-P2.2W': (timedelta(weeks=-2.2), D_DEFAULT, - '-P15DT9H36M'), - 'P1DT2H3M4S': (timedelta(days=1, hours=2, minutes=3, - seconds=4), D_DEFAULT, None), - 'P1DT2H3M': (timedelta(days=1, hours=2, minutes=3), - D_DEFAULT, None), - 'P1DT2H': (timedelta(days=1, hours=2), D_DEFAULT, None), - 'PT2H': (timedelta(hours=2), D_DEFAULT, None), - 'PT2.3H': (timedelta(hours=2.3), D_DEFAULT, 'PT2H18M'), - 'PT2H3M4S': (timedelta(hours=2, minutes=3, seconds=4), - D_DEFAULT, None), - 'PT3M4S': (timedelta(minutes=3, seconds=4), D_DEFAULT, - None), - 'PT22S': (timedelta(seconds=22), D_DEFAULT, None), - 'PT22.22S': (timedelta(seconds=22.22), 'PT%S.%fS', - 'PT22.220000S'), - '-P2Y': (Duration(years=-2), D_DEFAULT, None), - '-P3Y6M4DT12H30M5S': (Duration(-4, -5, 0, 0, -30, -12, 0, - -6, -3), D_DEFAULT, None), - '-P1DT2H3M4S': (timedelta(days=-1, hours=-2, minutes=-3, - seconds=-4), D_DEFAULT, None), - # alternative format - 'P0018-09-04T11:09:08': (Duration(4, 8, 0, 0, 9, 11, 0, 9, - 18), D_ALT_EXT, None), - #'PT000022.22': timedelta(seconds=22.22), - } - -# d1 d2 '+', '-', '>' -# A list of test cases to test addition and subtraction between datetime and -# Duration objects. -# each tuple contains 2 duration strings, and a result string for addition and -# one for subtraction. The last value says, if the first duration is greater -# than the second. -MATH_TEST_CASES = (('P5Y7M1DT9H45M16.72S', 'PT27M24.68S', - 'P5Y7M1DT10H12M41.4S', 'P5Y7M1DT9H17M52.04S', None), - ('PT28M12.73S', 'PT56M29.92S', - 'PT1H24M42.65S', '-PT28M17.19S', False), - ('P3Y7M23DT5H25M0.33S', 'PT1H1.95S', - 'P3Y7M23DT6H25M2.28S', 'P3Y7M23DT4H24M58.38S', None), - ('PT1H1.95S', 'P3Y7M23DT5H25M0.33S', - 'P3Y7M23DT6H25M2.28S', '-P3Y7M23DT4H24M58.38S', None), - ('P1332DT55M0.33S', 'PT1H1.95S', - 'P1332DT1H55M2.28S', 'P1331DT23H54M58.38S', True), - ('PT1H1.95S', 'P1332DT55M0.33S', - 'P1332DT1H55M2.28S', '-P1331DT23H54M58.38S', False)) - -# A list of test cases to test addition and subtraction of date/datetime -# and Duration objects. They are tested against the results of an -# equal long timedelta duration. -DATE_TEST_CASES = ( (date(2008, 2, 29), - timedelta(days=10, hours=12, minutes=20), - Duration(days=10, hours=12, minutes=20)), - (date(2008, 1, 31), - timedelta(days=10, hours=12, minutes=20), - Duration(days=10, hours=12, minutes=20)), - (datetime(2008, 2, 29), - timedelta(days=10, hours=12, minutes=20), - Duration(days=10, hours=12, minutes=20)), - (datetime(2008, 1, 31), - timedelta(days=10, hours=12, minutes=20), - Duration(days=10, hours=12, minutes=20)), - (datetime(2008, 4, 21), - timedelta(days=10, hours=12, minutes=20), - Duration(days=10, hours=12, minutes=20)), - (datetime(2008, 5, 5), - timedelta(days=10, hours=12, minutes=20), - Duration(days=10, hours=12, minutes=20)), - (datetime(2000, 1, 1), - timedelta(hours=-33), - Duration(hours=-33)), - (datetime(2008, 5, 5), - Duration(years=1, months=1, days=10, hours=12, - minutes=20), - Duration(months=13, days=10, hours=12, minutes=20)), - (datetime(2000, 3, 30), - Duration(years=1, months=1, days=10, hours=12, - minutes=20), - Duration(months=13, days=10, hours=12, minutes=20)), - ) - -# A list of test cases of additon of date/datetime and Duration. The results -# are compared against a given expected result. -DATE_CALC_TEST_CASES = ( - (date(2000, 2, 1), - Duration(years=1, months=1), - date(2001, 3, 1)), - (date(2000, 2, 29), - Duration(years=1, months=1), - date(2001, 3, 29)), - (date(2000, 2, 29), - Duration(years=1), - date(2001, 2, 28)), - (date(1996, 2, 29), - Duration(years=4), - date(2000, 2, 29)), - (date(2096, 2, 29), - Duration(years=4), - date(2100, 2, 28)), - (date(2000, 2, 1), - Duration(years=-1, months=-1), - date(1999, 1, 1)), - (date(2000, 2, 29), - Duration(years=-1, months=-1), - date(1999, 1, 29)), - (date(2000, 2, 1), - Duration(years=1, months=1, days=1), - date(2001, 3, 2)), - (date(2000, 2, 29), - Duration(years=1, months=1, days=1), - date(2001, 3, 30)), - (date(2000, 2, 29), - Duration(years=1, days=1), - date(2001, 3, 1)), - (date(1996, 2, 29), - Duration(years=4, days=1), - date(2000, 3, 1)), - (date(2096, 2, 29), - Duration(years=4, days=1), - date(2100, 3, 1)), - (date(2000, 2, 1), - Duration(years=-1, months=-1, days=-1), - date(1998, 12, 31)), - (date(2000, 2, 29), - Duration(years=-1, months=-1, days=-1), - date(1999, 1, 28)), - (date(2001, 4, 1), - Duration(years=-1, months=-1, days=-1), - date(2000, 2, 29)), - (date(2000, 4, 1), - Duration(years=-1, months=-1, days=-1), - date(1999, 2, 28)), - (Duration(years=1, months=2), - Duration(years=0, months=0, days=1), - Duration(years=1, months=2, days=1)), - (Duration(years=-1, months=-1, days=-1), - date(2000, 4, 1), - date(1999, 2, 28)), - (Duration(years=1, months=1, weeks=5), - date(2000, 1, 30), - date(2001, 4, 4)), - (Duration(years=1, months=1, weeks=5), - 'raise exception', - None), - ('raise exception', - Duration(years=1, months=1, weeks=5), - None), - (Duration(years=1, months=2), - timedelta(days=1), - Duration(years=1, months=2, days=1)), - (timedelta(days=1), - Duration(years=1, months=2), - Duration(years=1, months=2, days=1)), - #(date(2000, 1, 1), - # Duration(years=1.5), - # date(2001, 6, 1)), - #(date(2000, 1, 1), - # Duration(years=1, months=1.5), - # date(2001, 2, 14)), - ) - - -class DurationTest(unittest.TestCase): - ''' - This class tests various other aspects of the isoduration module, - which are not covered with the test cases listed above. - ''' - - def test_associative(self): - ''' - Adding 2 durations to a date is not associative. - ''' - days1 = Duration(days=1) - months1 = Duration(months=1) - start = date(2000, 3, 30) - res1 = start + days1 + months1 - res2 = start + months1 + days1 - self.assertNotEqual(res1, res2) - - def test_typeerror(self): - ''' - Test if TypError is raised with certain parameters. - ''' - self.assertRaises(TypeError, parse_duration, date(2000, 1, 1)) - self.assertRaises(TypeError, operator.sub, Duration(years=1), - date(2000, 1, 1)) - self.assertRaises(TypeError, operator.sub, 'raise exc', - Duration(years=1)) - - def test_parseerror(self): - ''' - Test for unparseable duration string. - ''' - self.assertRaises(ISO8601Error, parse_duration, 'T10:10:10') - - def test_repr(self): - ''' - Test __repr__ and __str__ for Duration obqects. - ''' - dur = Duration(10, 10, years=10, months=10) - self.assertEqual('10 years, 10 months, 10 days, 0:00:10', str(dur)) - self.assertEqual('isodate.duration.Duration(10, 10, 0,' - ' years=10, months=10)', repr(dur)) - - def test_neg(self): - ''' - Test __neg__ for Duration objects. - ''' - self.assertEqual(-Duration(0), Duration(0)) - self.assertEqual(-Duration(years=1, months=1), - Duration(years=-1, months=-1)) - self.assertEqual(-Duration(years=1, months=1), Duration(months=-13)) - self.assertNotEqual(-Duration(years=1), timedelta(days=-365)) - self.assertNotEqual(-timedelta(days=365), Duration(years=-1)) - self.assertNotEqual(-timedelta(days=10), -Duration(days=10)) - - def test_format(self): - ''' - Test various other strftime combinations. - ''' - self.assertEqual(duration_isoformat(Duration(0)), 'P0D') - self.assertEqual(duration_isoformat(-Duration(0)), 'P0D') - self.assertEqual(duration_isoformat(Duration(seconds=10)), 'PT10S') - self.assertEqual(duration_isoformat(Duration(years=-1, months=-1)), - '-P1Y1M') - self.assertEqual(duration_isoformat(-Duration(years=1, months=1)), - '-P1Y1M') - self.assertEqual(duration_isoformat(-Duration(years=-1, months=-1)), - 'P1Y1M') - self.assertEqual(duration_isoformat(-Duration(years=-1, months=-1)), - 'P1Y1M') - dur = Duration(years=3, months=7, days=23, hours=5, minutes=25, - milliseconds=330) - self.assertEqual(duration_isoformat(dur), 'P3Y7M23DT5H25M0.33S') - self.assertEqual(duration_isoformat(-dur), '-P3Y7M23DT5H25M0.33S') - - - def test_equal(self): - ''' - Test __eq__ and __ne__ methods. - ''' - self.assertEqual(Duration(years=1, months=1), - Duration(years=1, months=1)) - self.assertEqual(Duration(years=1, months=1), Duration(months=13)) - self.assertNotEqual(Duration(years=1, months=2), - Duration(years=1, months=1)) - self.assertNotEqual(Duration(years=1, months=1), Duration(months=14)) - self.assertNotEqual(Duration(years=1), timedelta(days=365)) - self.assertFalse(Duration(years=1, months=1) != - Duration(years=1, months=1)) - self.assertFalse(Duration(years=1, months=1) != Duration(months=13)) - self.assertTrue(Duration(years=1, months=2) != - Duration(years=1, months=1)) - self.assertTrue(Duration(years=1, months=1) != Duration(months=14)) - self.assertTrue(Duration(years=1) != timedelta(days=365)) - self.assertEqual(Duration(days=1), timedelta(days=1)) - self.assertNotEqual(timedelta(days=1), Duration(days=1)) - - -def create_parsetestcase(durationstring, expectation, format, altstr): - """ - Create a TestCase class for a specific test. - - This allows having a separate TestCase for each test tuple from the - PARSE_TEST_CASES list, so that a failed test won't stop other tests. - """ - - class TestParseDuration(unittest.TestCase): - ''' - A test case template to parse an ISO duration string into a - timedelta or Duration object. - ''' - - def test_parse(self): - ''' - Parse an ISO duration string and compare it to the expected value. - ''' - result = parse_duration(durationstring) - self.assertEqual(result, expectation) - - def test_format(self): - ''' - Take duration/timedelta object and create ISO string from it. - This is the reverse test to test_parse. - ''' - if altstr: - self.assertEqual(duration_isoformat(expectation, format), - altstr) - else: - self.assertEqual(duration_isoformat(expectation, format), - durationstring) - - return unittest.TestLoader().loadTestsFromTestCase(TestParseDuration) - - -def create_mathtestcase(dur1, dur2, resadd, ressub, resge): - """ - Create a TestCase class for a specific test. - - This allows having a separate TestCase for each test tuple from the - MATH_TEST_CASES list, so that a failed test won't stop other tests. - """ - - dur1 = parse_duration(dur1) - dur2 = parse_duration(dur2) - resadd = parse_duration(resadd) - ressub = parse_duration(ressub) - - class TestMathDuration(unittest.TestCase): - ''' - A test case template test addition, subtraction and > - operators for Duration objects. - ''' - - def test_add(self): - ''' - Test operator + (__add__, __radd__) - ''' - self.assertEqual(dur1 + dur2, resadd) - - def test_sub(self): - ''' - Test operator - (__sub__, __rsub__) - ''' - self.assertEqual(dur1 - dur2, ressub) - - def test_ge(self): - ''' - Test operator > and < - ''' - def dogetest(): - ''' Test greater than.''' - return dur1 > dur2 - - def doletest(): - ''' Test less than.''' - return dur1 < dur2 - if resge is None: - self.assertRaises(TypeError, dogetest) - self.assertRaises(TypeError, doletest) - else: - self.assertEqual(dogetest(), resge) - self.assertEqual(doletest(), not resge) - - return unittest.TestLoader().loadTestsFromTestCase(TestMathDuration) - - -def create_datetestcase(start, tdelta, duration): - """ - Create a TestCase class for a specific test. - - This allows having a separate TestCase for each test tuple from the - DATE_TEST_CASES list, so that a failed test won't stop other tests. - """ - - class TestDateCalc(unittest.TestCase): - ''' - A test case template test addition, subtraction - operators for Duration objects. - ''' - - def test_add(self): - ''' - Test operator +. - ''' - self.assertEqual(start + tdelta, start + duration) - - def test_sub(self): - ''' - Test operator -. - ''' - self.assertEqual(start - tdelta, start - duration) - - return unittest.TestLoader().loadTestsFromTestCase(TestDateCalc) - - -def create_datecalctestcase(start, duration, expectation): - """ - Create a TestCase class for a specific test. - - This allows having a separate TestCase for each test tuple from the - DATE_CALC_TEST_CASES list, so that a failed test won't stop other tests. - """ - - class TestDateCalc(unittest.TestCase): - ''' - A test case template test addition operators for Duration objects. - ''' - - def test_calc(self): - ''' - Test operator +. - ''' - if expectation is None: - self.assertRaises(TypeError, operator.add, start, duration) - else: - self.assertEqual(start + duration, expectation) - - return unittest.TestLoader().loadTestsFromTestCase(TestDateCalc) - - -def test_suite(): - ''' - Return a test suite containing all test defined above. - ''' - suite = unittest.TestSuite() - for durationstring, (expectation, format, altstr) in PARSE_TEST_CASES.items(): - suite.addTest(create_parsetestcase(durationstring, expectation, - format, altstr)) - for testdata in MATH_TEST_CASES: - suite.addTest(create_mathtestcase(*testdata)) - for testdata in DATE_TEST_CASES: - suite.addTest(create_datetestcase(*testdata)) - for testdata in DATE_CALC_TEST_CASES: - suite.addTest(create_datecalctestcase(*testdata)) - suite.addTest(unittest.TestLoader().loadTestsFromTestCase(DurationTest)) - return suite - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff --git a/src/tests/test_time.py b/src/tests/test_time.py deleted file mode 100644 index d71a3e2..0000000 --- a/src/tests/test_time.py +++ /dev/null @@ -1,139 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -Test cases for the isotime module. -''' -import unittest -from datetime import time - -from isodate import parse_time, UTC, FixedOffset, ISO8601Error, time_isoformat -from isodate import TIME_BAS_COMPLETE, TIME_BAS_MINUTE -from isodate import TIME_EXT_COMPLETE, TIME_EXT_MINUTE -from isodate import TIME_HOUR -from isodate import TZ_BAS, TZ_EXT, TZ_HOUR - -# the following list contains tuples of ISO time strings and the expected -# result from the parse_time method. A result of None means an ISO8601Error -# is expected. -TEST_CASES = [('232050', time(23, 20, 50), TIME_BAS_COMPLETE + TZ_BAS), - ('23:20:50', time(23, 20, 50), TIME_EXT_COMPLETE + TZ_EXT), - ('2320', time(23, 20), TIME_BAS_MINUTE), - ('23:20', time(23, 20), TIME_EXT_MINUTE), - ('23', time(23), TIME_HOUR), - ('232050,5', time(23, 20, 50, 500000), None), - ('23:20:50.5', time(23, 20, 50, 500000), None), - # test precision - ('15:33:42.123456', time(15, 33, 42, 123456), None), - ('15:33:42.1234564', time(15, 33, 42, 123456), None), - ('15:33:42.1234557', time(15, 33, 42, 123456), None), - ('2320,8', time(23, 20, 48), None), - ('23:20,8', time(23, 20, 48), None), - ('23,3', time(23, 18), None), - ('232030Z', time(23, 20, 30, tzinfo=UTC), - TIME_BAS_COMPLETE + TZ_BAS), - ('2320Z', time(23, 20, tzinfo=UTC), TIME_BAS_MINUTE + TZ_BAS), - ('23Z', time(23, tzinfo=UTC), TIME_HOUR + TZ_BAS), - ('23:20:30Z', time(23, 20, 30, tzinfo=UTC), - TIME_EXT_COMPLETE + TZ_EXT), - ('23:20Z', time(23, 20, tzinfo=UTC), TIME_EXT_MINUTE + TZ_EXT), - ('152746+0100', time(15, 27, 46, - tzinfo=FixedOffset(1, 0, '+0100')), - TIME_BAS_COMPLETE + TZ_BAS), - ('152746-0500', time(15, 27, 46, - tzinfo=FixedOffset(-5, 0, '-0500')), - TIME_BAS_COMPLETE + TZ_BAS), - ('152746+01', time(15, 27, 46, - tzinfo=FixedOffset(1, 0, '+01:00')), - TIME_BAS_COMPLETE + TZ_HOUR), - ('152746-05', time(15, 27, 46, - tzinfo=FixedOffset(-5, -0, '-05:00')), - TIME_BAS_COMPLETE + TZ_HOUR), - ('15:27:46+01:00', time(15, 27, 46, - tzinfo=FixedOffset(1, 0, '+01:00')), - TIME_EXT_COMPLETE + TZ_EXT), - ('15:27:46-05:00', time(15, 27, 46, - tzinfo=FixedOffset(-5, -0, '-05:00')), - TIME_EXT_COMPLETE + TZ_EXT), - ('15:27:46+01', time(15, 27, 46, - tzinfo=FixedOffset(1, 0, '+01:00')), - TIME_EXT_COMPLETE + TZ_HOUR), - ('15:27:46-05', time(15, 27, 46, - tzinfo=FixedOffset(-5, -0, '-05:00')), - TIME_EXT_COMPLETE + TZ_HOUR), - ('1:17:30', None, TIME_EXT_COMPLETE)] - - -def create_testcase(timestring, expectation, format): - """ - Create a TestCase class for a specific test. - - This allows having a separate TestCase for each test tuple from the - TEST_CASES list, so that a failed test won't stop other tests. - """ - - class TestTime(unittest.TestCase): - ''' - A test case template to parse an ISO time string into a time - object. - ''' - - def test_parse(self): - ''' - Parse an ISO time string and compare it to the expected value. - ''' - if expectation is None: - self.assertRaises(ISO8601Error, parse_time, timestring) - else: - result = parse_time(timestring) - self.assertEqual(result, expectation) - - def test_format(self): - ''' - Take time object and create ISO string from it. - This is the reverse test to test_parse. - ''' - if expectation is None: - self.assertRaises(AttributeError, - time_isoformat, expectation, format) - elif format is not None: - self.assertEqual(time_isoformat(expectation, format), - timestring) - - return unittest.TestLoader().loadTestsFromTestCase(TestTime) - - -def test_suite(): - ''' - Construct a TestSuite instance for all test cases. - ''' - suite = unittest.TestSuite() - for timestring, expectation, format in TEST_CASES: - suite.addTest(create_testcase(timestring, expectation, format)) - return suite - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') -- cgit v1.2.1