diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index fd9d419..caa60b0 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -9,7 +9,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: install requirements for python3 - run: pip3 install -r requirements-3.txt + run: pip3 install -r requirements.txt - name: package and upload python3 env: TWINE_USERNAME: __token__ diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index f979c69..f95128b 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -14,7 +14,7 @@ jobs: - name: print python version run: python3 --version - name: install requirements - run: pip3 install -r requirements-3.txt + run: pip3 install -r requirements.txt - name: run the tests run: python3 tests.py - name: verify type hints diff --git a/CHANGELOG.md b/CHANGELOG.md index 49e9a40..a4213dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.0.2] - 2024-08-27 +### added +- Feat: Complete typing with strict type-checking [#43](https://github.com/nickmaccarthy/python-datemath/pull/43) Thank you @Avasam! + +### fixed +- Fix: removed legacy-tests.py since we no longer support python2.x +- Fix: removed requirements-2.txt from manifest due to deprecation of python2 support +- Fix: renamed requirements-3.txt to requirements.txt to support python3 going forward + - also modifed to `release.yaml` and `tests.yaml` workflows to support this +- Fix: long_description should now show up in pypi https://github.com/nickmaccarthy/python-datemath/issues/33 + ## [3.0.1] - 2024-08-23 ### fixed - Fix: Race condition in timezone tests: https://github.com/nickmaccarthy/python-datemath/issues/36 @@ -41,14 +52,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### fixed - FIX: [Issue #21](https://github.com/nickmaccarthy/python-datemath/issues/21) - Fixed an issue where if timezone offset was in a datetime string (ISO8601), the timezone of the returned datemath object would be UTC and not the timezone as specified in the datetime string. -## 1.5.1 (2020-03-25) +## [1.5.1] - 2020-03-25 ### fixed - FIX: [Issue #15](https://github.com/nickmaccarthy/python-datemath/issues/15) - Fixed issue with parser finding invalid timeunits and throwing correct errors ### added - Feat: [Issue #16](https://github.com/nickmaccarthy/python-datemath/issues/16) - Added support for parser to accecpt a epoch/unix timestamp but throw an error on epoch milli's since arrow can't support that. -## 1.5.0 - 2019-11-09 +## [1.5.0] - 2019-11-09 ### fixed - [Issue #12](https://github.com/nickmaccarthy/python-datemath/issues/12) - missing VERSION.txt. Added MANIFEST.in for sdist build diff --git a/MANIFEST.in b/MANIFEST.in index 3552d4e..32329a5 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,5 +2,4 @@ include VERSION.txt include README.md include CHANGELOG.md include LICENSE -include requirements-2.txt include requirements-3.txt \ No newline at end of file diff --git a/VERSION.txt b/VERSION.txt index cb2b00e..b502146 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -3.0.1 +3.0.2 diff --git a/requirements-3.txt b/requirements-3.txt index 257a732..fa6d05c 100644 --- a/requirements-3.txt +++ b/requirements-3.txt @@ -7,20 +7,20 @@ chardet==3.0.4 clint==0.5.1 docutils==0.15.2 freezegun==1.2.2 -idna==2.7 +idna==3.7 linecache2==1.0.0 mypy==1.7.1 packaging==16.8 pkginfo==1.4.2 -Pygments==2.7.4 +Pygments==2.15.0 pyparsing==2.2.0 python-dateutil==2.8.2 pytz==2023.3 readme-renderer==24.0 -requests==2.20.0 +requests==2.32.2 requests-toolbelt==0.9.1 six==1.10.0 -tqdm==4.36.1 +tqdm==4.66.3 traceback2==1.4.0 twine==2.0.0 types-python-dateutil==2.8.19.20240311 @@ -28,5 +28,6 @@ types-setuptools==73.0.0.20240822 types-pytz==2023.3.1.1 typing_extensions==4.7.1 tzdata==2024.1 -urllib3==1.24.3 +urllib3==1.26.19 webencodings==0.5.1 + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..33b01bd --- /dev/null +++ b/requirements.txt @@ -0,0 +1,32 @@ +appdirs==1.4.3 +args==0.1.0 +arrow==1.2.3 +bleach==3.3.0 +certifi==2024.7.4 +chardet==3.0.4 +clint==0.5.1 +docutils==0.15.2 +freezegun==1.2.2 +idna==3.7 +linecache2==1.0.0 +mypy==1.7.1 +packaging==16.8 +pkginfo==1.4.2 +Pygments==2.15.0 +pyparsing==2.2.0 +python-dateutil==2.8.2 +pytz==2023.3 +readme-renderer==24.0 +requests==2.32.2 +requests-toolbelt==0.9.1 +six==1.10.0 +tqdm==4.66.3 +traceback2==1.4.0 +twine==2.0.0 +types-python-dateutil==2.8.19.20240311 +types-setuptools==73.0.0.20240822 +types-pytz==2023.3.1.1 +typing_extensions==4.7.1 +tzdata==2024.1 +urllib3==1.26.19 +webencodings==0.5.1 diff --git a/setup.cfg b/setup.cfg index 5eeb289..ac06c3e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,11 @@ [metadata] -description-file = ./README.md +name = python-datemath +description = "A python module to emulate the date math used in SOLR and Elasticsearch" +long_description = file: README.md +long_description_content_type = text/markdown +author = Nick MacCarthy +author_email = nickmaccarthy@gmail.com + [bdist_wheel] universal=1 diff --git a/setup.py b/setup.py index 38af6db..169b06f 100644 --- a/setup.py +++ b/setup.py @@ -31,6 +31,9 @@ description='A python module to emulate the date math used in SOLR and Elasticsearch', + long_description=long_description, + long_description_content_type='text/markdown', + # The project's main homepage. url='https://github.com/nickmaccarthy/python-datemath', @@ -48,7 +51,7 @@ # 3 - Alpha # 4 - Beta # 5 - Production/Stable - 'Development Status :: 4 - Beta', + 'Development Status :: 5 - Production/Stable', # Indicate who your project is intended for 'Intended Audience :: Developers', diff --git a/tests-legacy.py b/tests-legacy.py deleted file mode 100644 index 8c13993..0000000 --- a/tests-legacy.py +++ /dev/null @@ -1,128 +0,0 @@ -import unittest -import arrow -from datetime import datetime as pydatetime -from datemath import dm -from datemath import datemath -from dateutil import tz - -iso8601 = 'YYYY-MM-DDTHH:mm:ssZZ' -class TestDM(unittest.TestCase): - - def testParse(self) -> None: - - # Baisc dates - self.assertEqual(dm('2016.01.02').format(iso8601), '2016-01-02T00:00:00-00:00') - self.assertEqual(dm('2016-01-02').format(iso8601), '2016-01-02T00:00:00-00:00') - self.assertEqual(dm('2016-01-02 01:00:00').format(iso8601), '2016-01-02T01:00:00-00:00') - - # Rounding Tests - self.assertEqual(dm('2016-01-01||/d').format('YYYY-MM-DDTHH:mm:ssZZ'), '2016-01-01T00:00:00-00:00') - self.assertEqual(dm('2014-11-18||/y').format('YYYY-MM-DDTHH:mm:ssZZ'), '2014-01-01T00:00:00-00:00') - self.assertEqual(dm('2016-01-01 14:00:00||/w').format('YYYY-MM-DDTHH:mm:ssZZ'), '2015-12-28T00:00:00-00:00') - self.assertEqual(dm('2014-11||/M').format('YYYY-MM-DDTHH:mm:ssZZ'), '2014-11-01T00:00:00-00:00') - self.assertEqual(dm('2016-01-02||/M+1h+1m').format(iso8601), '2016-01-01T01:01:00-00:00') - self.assertEqual(dm('2016-01-02||/d+1h').format(iso8601), '2016-01-02T01:00:00-00:00') - self.assertEqual(dm('2016-01-02T14:02:00||/h').format(iso8601), '2016-01-02T14:00:00-00:00') - self.assertEqual(dm('2016-01-02T14:02:00||/H').format(iso8601), '2016-01-02T14:00:00-00:00') - - # Rounding Up Tests - self.assertEqual(dm('2016-01-01||/d', roundDown=False).format('YYYY-MM-DDTHH:mm:ssZZ'), '2016-01-01T23:59:59-00:00') - self.assertEqual(dm('2014-11-18||/y', roundDown=False).format('YYYY-MM-DDTHH:mm:ssZZ'), '2014-12-31T23:59:59-00:00') - - # Timezone Tests - self.assertEqual(dm('now', tz='US/Pacific').format(iso8601), arrow.utcnow().to('US/Pacific').format(iso8601)) - self.assertEqual(dm('2017-09-22 10:20:00', tz='US/Pacific').datetime, pydatetime(2017, 9, 22, 10, 20, 00, tzinfo=tz.gettz('US/Pacific'))) - self.assertEqual(dm('2016-01-01', tz='UTC'), arrow.get('2016-01-01').to('UTC')) - self.assertEqual(dm('2016-01-01', tz='US/Eastern'), pydatetime(2016, 1, 1, tzinfo=tz.gettz('US/Eastern'))) - self.assertEqual(datemath('2016-01-01T01:00:00', tz='US/Central'), pydatetime(2016, 1, 1, 1, 0, 0, tzinfo=tz.gettz('US/Central'))) - - # relitive formats - # addition - self.assertEqual(dm('+1s').format(iso8601), arrow.utcnow().replace(seconds=+1).format(iso8601)) - self.assertEqual(dm('+1m').format(iso8601), arrow.utcnow().replace(minutes=+1).format(iso8601)) - self.assertEqual(dm('+1h').format(iso8601), arrow.utcnow().replace(hours=+1).format(iso8601)) - self.assertEqual(dm('+1d').format(iso8601), arrow.utcnow().replace(days=+1).format(iso8601)) - self.assertEqual(dm('+1w').format(iso8601), arrow.utcnow().replace(weeks=+1).format(iso8601)) - self.assertEqual(dm('+1M').format(iso8601), arrow.utcnow().replace(months=+1).format(iso8601)) - self.assertEqual(dm('+1Y').format(iso8601), arrow.utcnow().replace(years=+1).format(iso8601)) - self.assertEqual(dm('+1y').format(iso8601), arrow.utcnow().replace(years=+1).format(iso8601)) - # subtraction - self.assertEqual(dm('-1s').format(iso8601), arrow.utcnow().replace(seconds=-1).format(iso8601)) - self.assertEqual(dm('-1m').format(iso8601), arrow.utcnow().replace(minutes=-1).format(iso8601)) - self.assertEqual(dm('-1h').format(iso8601), arrow.utcnow().replace(hours=-1).format(iso8601)) - self.assertEqual(dm('-1d').format(iso8601), arrow.utcnow().replace(days=-1).format(iso8601)) - self.assertEqual(dm('-1w').format(iso8601), arrow.utcnow().replace(weeks=-1).format(iso8601)) - self.assertEqual(dm('-1M').format(iso8601), arrow.utcnow().replace(months=-1).format(iso8601)) - self.assertEqual(dm('-1Y').format(iso8601), arrow.utcnow().replace(years=-1).format(iso8601)) - self.assertEqual(dm('-1y').format(iso8601), arrow.utcnow().replace(years=-1).format(iso8601)) - # rounding - self.assertEqual(dm('/s').format(iso8601), arrow.utcnow().floor('second').format(iso8601)) - self.assertEqual(dm('/m').format(iso8601), arrow.utcnow().floor('minute').format(iso8601)) - self.assertEqual(dm('/h').format(iso8601), arrow.utcnow().floor('hour').format(iso8601)) - self.assertEqual(dm('/d').format(iso8601), arrow.utcnow().floor('day').format(iso8601)) - self.assertEqual(dm('/w').format(iso8601), arrow.utcnow().floor('week').format(iso8601)) - self.assertEqual(dm('/M').format(iso8601), arrow.utcnow().floor('month').format(iso8601)) - self.assertEqual(dm('/Y').format(iso8601), arrow.utcnow().floor('year').format(iso8601)) - self.assertEqual(dm('/y').format(iso8601), arrow.utcnow().floor('year').format(iso8601)) - # rounding up - self.assertEqual(dm('/s', roundDown=False).format(iso8601), arrow.utcnow().ceil('second').format(iso8601)) - self.assertEqual(dm('/m', roundDown=False).format(iso8601), arrow.utcnow().ceil('minute').format(iso8601)) - self.assertEqual(dm('/h', roundDown=False).format(iso8601), arrow.utcnow().ceil('hour').format(iso8601)) - self.assertEqual(dm('/d', roundDown=False).format(iso8601), arrow.utcnow().ceil('day').format(iso8601)) - self.assertEqual(dm('/w', roundDown=False).format(iso8601), arrow.utcnow().ceil('week').format(iso8601)) - self.assertEqual(dm('/M', roundDown=False).format(iso8601), arrow.utcnow().ceil('month').format(iso8601)) - self.assertEqual(dm('/Y', roundDown=False).format(iso8601), arrow.utcnow().ceil('year').format(iso8601)) - self.assertEqual(dm('/y', roundDown=False).format(iso8601), arrow.utcnow().ceil('year').format(iso8601)) - - - # roundDown option tests - self.assertEqual(dm('2016-01-01T14:00:00||/d').format(iso8601), '2016-01-01T00:00:00-00:00') - self.assertEqual(dm('2016-01-01T14:00:00||/d', roundDown=False).format(iso8601), '2016-01-01T23:59:59-00:00') - - # complicated date math - self.assertEqual(dm('now/d-1h').format(iso8601), arrow.utcnow().floor('day').replace(hours=-1).format(iso8601)) - self.assertEqual(dm('+1h').format(iso8601), arrow.utcnow().replace(hours=+1).format(iso8601)) - self.assertEqual(dm('/M+2d').format(iso8601), arrow.utcnow().floor('month').replace(days=+2).format(iso8601)) - self.assertEqual(dm('now/w+2d-2h').format(iso8601), arrow.utcnow().floor('week').replace(days=+2, hours=-2).format(iso8601)) - self.assertEqual(dm('now/M+1w-2h+10s').format(iso8601), arrow.utcnow().floor('month').replace(weeks=+1, hours=-2, seconds=+10).format(iso8601)) - self.assertEqual(dm('now-1d/d').format(iso8601), arrow.utcnow().replace(days=-1).floor('day').format(iso8601)) - self.assertEqual(dm('now+1d/d').format(iso8601), arrow.utcnow().replace(days=1).floor('day').format(iso8601)) - self.assertEqual(dm('now-10d/d').format(iso8601), arrow.utcnow().replace(days=-10).floor('day').format(iso8601)) - self.assertEqual(dm('now+10d/d').format(iso8601), arrow.utcnow().replace(days=10).floor('day').format(iso8601)) - - - # future - self.assertEqual(dm('+1s').format(iso8601), arrow.utcnow().replace(seconds=+1).format(iso8601)) - self.assertEqual(dm('+1s+2m+3h').format(iso8601), arrow.utcnow().replace(seconds=+1, minutes=+2, hours=+3).format(iso8601)) - self.assertEqual(dm('+1m').format(iso8601), arrow.utcnow().replace(minutes=+1).format(iso8601)) - self.assertEqual(dm('+1m+5h').format(iso8601), arrow.utcnow().replace(minutes=+1, hours=+5).format(iso8601)) - self.assertEqual(dm('/d+1m+5h').format(iso8601), arrow.utcnow().floor('day').replace(minutes=+1, hours=+5).format(iso8601)) - self.assertEqual(dm('+1h').format(iso8601), arrow.utcnow().replace(hours=+1).format(iso8601)) - self.assertEqual(dm('+1w').format(iso8601), arrow.utcnow().replace(weeks=+1).format(iso8601)) - self.assertEqual(dm('+1w+12d').format(iso8601), arrow.utcnow().replace(weeks=+1, days=+12).format(iso8601)) - self.assertEqual(dm('+2y').format(iso8601), arrow.utcnow().replace(years=+2).format(iso8601)) - self.assertEqual(dm('+2y+22d+4h').format(iso8601), arrow.utcnow().replace(years=+2, days=+22, hours=+4).format(iso8601)) - - # past - self.assertEqual(dm('-3w').format(iso8601), arrow.utcnow().replace(weeks=-3).format(iso8601)) - self.assertEqual(dm('-3W').format(iso8601), arrow.utcnow().replace(weeks=-3).format(iso8601)) - self.assertEqual(dm('-3w-2d-6h').format(iso8601), arrow.utcnow().replace(weeks=-3, days=-2, hours=-6).format(iso8601)) - self.assertEqual(dm('-3w-2d-22h-36s').format(iso8601), arrow.utcnow().replace(weeks=-3, days=-2, hours=-22, seconds=-36).format(iso8601)) - self.assertEqual(dm('-6y-3w-2d-22h-36s').format(iso8601), arrow.utcnow().replace(years=-6, weeks=-3, days=-2, hours=-22, seconds=-36).format(iso8601)) - - - import datetime - delta = datetime.timedelta(seconds=1) - # datetime objects - self.assertAlmostEqual(dm('now').datetime, arrow.utcnow().datetime, delta=delta) - self.assertAlmostEqual(dm('now+1d').datetime, arrow.utcnow().replace(days=+1).datetime, delta=delta) - self.assertAlmostEqual(dm('/w').datetime, arrow.utcnow().floor('week').datetime, delta=delta) - - - # Floats - self.assertEqual(dm('now-2.5h').format(iso8601), arrow.utcnow().replace(hours=-2.5).format(iso8601)) - self.assertEqual(dm('now-2.5d').format(iso8601), arrow.utcnow().replace(days=-2.5).format(iso8601)) - - -if __name__ == "__main__": - unittest.main() \ No newline at end of file