diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
commit | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (patch) | |
tree | 012bb94d777798f1f56ac1cec429509766d05181 /contrib/python/dateutil | |
parent | 6751af0b0c1b952fede40b19b71da8025b5d8bcf (diff) | |
download | ydb-2598ef1d0aee359b4b6d5fdd1758916d5907d04f.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/python/dateutil')
35 files changed, 2309 insertions, 2309 deletions
diff --git a/contrib/python/dateutil/.dist-info/METADATA b/contrib/python/dateutil/.dist-info/METADATA index 1e46c96a44..2c5c2c523a 100644 --- a/contrib/python/dateutil/.dist-info/METADATA +++ b/contrib/python/dateutil/.dist-info/METADATA @@ -1,204 +1,204 @@ -Metadata-Version: 2.1 -Name: python-dateutil -Version: 2.8.2 -Summary: Extensions to the standard Python datetime module -Home-page: https://github.com/dateutil/dateutil -Author: Gustavo Niemeyer -Author-email: gustavo@niemeyer.net -Maintainer: Paul Ganssle -Maintainer-email: dateutil@python.org -License: Dual License -Project-URL: Documentation, https://dateutil.readthedocs.io/en/stable/ -Project-URL: Source, https://github.com/dateutil/dateutil -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: License :: OSI Approved :: Apache Software License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Topic :: Software Development :: Libraries -Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,>=2.7 -Description-Content-Type: text/x-rst -License-File: LICENSE -Requires-Dist: six (>=1.5) - -dateutil - powerful extensions to datetime -========================================== - -|pypi| |support| |licence| - -|gitter| |readthedocs| - -|travis| |appveyor| |pipelines| |coverage| - -.. |pypi| image:: https://img.shields.io/pypi/v/python-dateutil.svg?style=flat-square - :target: https://pypi.org/project/python-dateutil/ - :alt: pypi version - -.. |support| image:: https://img.shields.io/pypi/pyversions/python-dateutil.svg?style=flat-square - :target: https://pypi.org/project/python-dateutil/ - :alt: supported Python version - -.. |travis| image:: https://img.shields.io/travis/dateutil/dateutil/master.svg?style=flat-square&label=Travis%20Build - :target: https://travis-ci.org/dateutil/dateutil - :alt: travis build status - -.. |appveyor| image:: https://img.shields.io/appveyor/ci/dateutil/dateutil/master.svg?style=flat-square&logo=appveyor - :target: https://ci.appveyor.com/project/dateutil/dateutil - :alt: appveyor build status - -.. |pipelines| image:: https://dev.azure.com/pythondateutilazure/dateutil/_apis/build/status/dateutil.dateutil?branchName=master - :target: https://dev.azure.com/pythondateutilazure/dateutil/_build/latest?definitionId=1&branchName=master - :alt: azure pipelines build status - -.. |coverage| image:: https://codecov.io/gh/dateutil/dateutil/branch/master/graphs/badge.svg?branch=master - :target: https://codecov.io/gh/dateutil/dateutil?branch=master - :alt: Code coverage - -.. |gitter| image:: https://badges.gitter.im/dateutil/dateutil.svg - :alt: Join the chat at https://gitter.im/dateutil/dateutil - :target: https://gitter.im/dateutil/dateutil - -.. |licence| image:: https://img.shields.io/pypi/l/python-dateutil.svg?style=flat-square - :target: https://pypi.org/project/python-dateutil/ - :alt: licence - -.. |readthedocs| image:: https://img.shields.io/readthedocs/dateutil/latest.svg?style=flat-square&label=Read%20the%20Docs - :alt: Read the documentation at https://dateutil.readthedocs.io/en/latest/ - :target: https://dateutil.readthedocs.io/en/latest/ - -The `dateutil` module provides powerful extensions to -the standard `datetime` module, available in Python. - -Installation -============ -`dateutil` can be installed from PyPI using `pip` (note that the package name is -different from the importable name):: - - pip install python-dateutil - -Download -======== -dateutil is available on PyPI -https://pypi.org/project/python-dateutil/ - -The documentation is hosted at: -https://dateutil.readthedocs.io/en/stable/ - -Code -==== -The code and issue tracker are hosted on GitHub: -https://github.com/dateutil/dateutil/ - -Features -======== - -* Computing of relative deltas (next month, next year, - next Monday, last week of month, etc); -* Computing of relative deltas between two given - date and/or datetime objects; -* Computing of dates based on very flexible recurrence rules, - using a superset of the `iCalendar <https://www.ietf.org/rfc/rfc2445.txt>`_ - specification. Parsing of RFC strings is supported as well. -* Generic parsing of dates in almost any string format; -* Timezone (tzinfo) implementations for tzfile(5) format - files (/etc/localtime, /usr/share/zoneinfo, etc), TZ - environment string (in all known formats), iCalendar - format files, given ranges (with help from relative deltas), - local machine timezone, fixed offset timezone, UTC timezone, - and Windows registry-based time zones. -* Internal up-to-date world timezone information based on - Olson's database. -* Computing of Easter Sunday dates for any given year, - using Western, Orthodox or Julian algorithms; -* A comprehensive test suite. - -Quick example -============= -Here's a snapshot, just to give an idea about the power of the -package. For more examples, look at the documentation. - -Suppose you want to know how much time is left, in -years/months/days/etc, before the next easter happening on a -year with a Friday 13th in August, and you want to get today's -date out of the "date" unix system command. Here is the code: - -.. code-block:: python3 - - >>> from dateutil.relativedelta import * - >>> from dateutil.easter import * - >>> from dateutil.rrule import * - >>> from dateutil.parser import * - >>> from datetime import * - >>> now = parse("Sat Oct 11 17:13:46 UTC 2003") - >>> today = now.date() - >>> year = rrule(YEARLY,dtstart=now,bymonth=8,bymonthday=13,byweekday=FR)[0].year - >>> rdelta = relativedelta(easter(year), today) - >>> print("Today is: %s" % today) - Today is: 2003-10-11 - >>> print("Year with next Aug 13th on a Friday is: %s" % year) - Year with next Aug 13th on a Friday is: 2004 - >>> print("How far is the Easter of that year: %s" % rdelta) - How far is the Easter of that year: relativedelta(months=+6) - >>> print("And the Easter of that year is: %s" % (today+rdelta)) - And the Easter of that year is: 2004-04-11 - -Being exactly 6 months ahead was **really** a coincidence :) - -Contributing -============ - -We welcome many types of contributions - bug reports, pull requests (code, infrastructure or documentation fixes). For more information about how to contribute to the project, see the ``CONTRIBUTING.md`` file in the repository. - - -Author -====== -The dateutil module was written by Gustavo Niemeyer <gustavo@niemeyer.net> -in 2003. - -It is maintained by: - -* Gustavo Niemeyer <gustavo@niemeyer.net> 2003-2011 -* Tomi Pieviläinen <tomi.pievilainen@iki.fi> 2012-2014 -* Yaron de Leeuw <me@jarondl.net> 2014-2016 -* Paul Ganssle <paul@ganssle.io> 2015- - -Starting with version 2.4.1 and running until 2.8.2, all source and binary -distributions will be signed by a PGP key that has, at the very least, been -signed by the key which made the previous release. A table of release signing -keys can be found below: - -=========== ============================ -Releases Signing key fingerprint -=========== ============================ -2.4.1-2.8.2 `6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB`_ -=========== ============================ - -New releases *may* have signed tags, but binary and source distributions -uploaded to PyPI will no longer have GPG signatures attached. - -Contact -======= -Our mailing list is available at `dateutil@python.org <https://mail.python.org/mailman/listinfo/dateutil>`_. As it is hosted by the PSF, it is subject to the `PSF code of -conduct <https://www.python.org/psf/conduct/>`_. - -License -======= - -All contributions after December 1, 2017 released under dual license - either `Apache 2.0 License <https://www.apache.org/licenses/LICENSE-2.0>`_ or the `BSD 3-Clause License <https://opensource.org/licenses/BSD-3-Clause>`_. Contributions before December 1, 2017 - except those those explicitly relicensed - are released only under the BSD 3-Clause License. - - -.. _6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB: - https://pgp.mit.edu/pks/lookup?op=vindex&search=0xCD54FCE3D964BEFB - - +Metadata-Version: 2.1 +Name: python-dateutil +Version: 2.8.2 +Summary: Extensions to the standard Python datetime module +Home-page: https://github.com/dateutil/dateutil +Author: Gustavo Niemeyer +Author-email: gustavo@niemeyer.net +Maintainer: Paul Ganssle +Maintainer-email: dateutil@python.org +License: Dual License +Project-URL: Documentation, https://dateutil.readthedocs.io/en/stable/ +Project-URL: Source, https://github.com/dateutil/dateutil +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Topic :: Software Development :: Libraries +Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,>=2.7 +Description-Content-Type: text/x-rst +License-File: LICENSE +Requires-Dist: six (>=1.5) + +dateutil - powerful extensions to datetime +========================================== + +|pypi| |support| |licence| + +|gitter| |readthedocs| + +|travis| |appveyor| |pipelines| |coverage| + +.. |pypi| image:: https://img.shields.io/pypi/v/python-dateutil.svg?style=flat-square + :target: https://pypi.org/project/python-dateutil/ + :alt: pypi version + +.. |support| image:: https://img.shields.io/pypi/pyversions/python-dateutil.svg?style=flat-square + :target: https://pypi.org/project/python-dateutil/ + :alt: supported Python version + +.. |travis| image:: https://img.shields.io/travis/dateutil/dateutil/master.svg?style=flat-square&label=Travis%20Build + :target: https://travis-ci.org/dateutil/dateutil + :alt: travis build status + +.. |appveyor| image:: https://img.shields.io/appveyor/ci/dateutil/dateutil/master.svg?style=flat-square&logo=appveyor + :target: https://ci.appveyor.com/project/dateutil/dateutil + :alt: appveyor build status + +.. |pipelines| image:: https://dev.azure.com/pythondateutilazure/dateutil/_apis/build/status/dateutil.dateutil?branchName=master + :target: https://dev.azure.com/pythondateutilazure/dateutil/_build/latest?definitionId=1&branchName=master + :alt: azure pipelines build status + +.. |coverage| image:: https://codecov.io/gh/dateutil/dateutil/branch/master/graphs/badge.svg?branch=master + :target: https://codecov.io/gh/dateutil/dateutil?branch=master + :alt: Code coverage + +.. |gitter| image:: https://badges.gitter.im/dateutil/dateutil.svg + :alt: Join the chat at https://gitter.im/dateutil/dateutil + :target: https://gitter.im/dateutil/dateutil + +.. |licence| image:: https://img.shields.io/pypi/l/python-dateutil.svg?style=flat-square + :target: https://pypi.org/project/python-dateutil/ + :alt: licence + +.. |readthedocs| image:: https://img.shields.io/readthedocs/dateutil/latest.svg?style=flat-square&label=Read%20the%20Docs + :alt: Read the documentation at https://dateutil.readthedocs.io/en/latest/ + :target: https://dateutil.readthedocs.io/en/latest/ + +The `dateutil` module provides powerful extensions to +the standard `datetime` module, available in Python. + +Installation +============ +`dateutil` can be installed from PyPI using `pip` (note that the package name is +different from the importable name):: + + pip install python-dateutil + +Download +======== +dateutil is available on PyPI +https://pypi.org/project/python-dateutil/ + +The documentation is hosted at: +https://dateutil.readthedocs.io/en/stable/ + +Code +==== +The code and issue tracker are hosted on GitHub: +https://github.com/dateutil/dateutil/ + +Features +======== + +* Computing of relative deltas (next month, next year, + next Monday, last week of month, etc); +* Computing of relative deltas between two given + date and/or datetime objects; +* Computing of dates based on very flexible recurrence rules, + using a superset of the `iCalendar <https://www.ietf.org/rfc/rfc2445.txt>`_ + specification. Parsing of RFC strings is supported as well. +* Generic parsing of dates in almost any string format; +* Timezone (tzinfo) implementations for tzfile(5) format + files (/etc/localtime, /usr/share/zoneinfo, etc), TZ + environment string (in all known formats), iCalendar + format files, given ranges (with help from relative deltas), + local machine timezone, fixed offset timezone, UTC timezone, + and Windows registry-based time zones. +* Internal up-to-date world timezone information based on + Olson's database. +* Computing of Easter Sunday dates for any given year, + using Western, Orthodox or Julian algorithms; +* A comprehensive test suite. + +Quick example +============= +Here's a snapshot, just to give an idea about the power of the +package. For more examples, look at the documentation. + +Suppose you want to know how much time is left, in +years/months/days/etc, before the next easter happening on a +year with a Friday 13th in August, and you want to get today's +date out of the "date" unix system command. Here is the code: + +.. code-block:: python3 + + >>> from dateutil.relativedelta import * + >>> from dateutil.easter import * + >>> from dateutil.rrule import * + >>> from dateutil.parser import * + >>> from datetime import * + >>> now = parse("Sat Oct 11 17:13:46 UTC 2003") + >>> today = now.date() + >>> year = rrule(YEARLY,dtstart=now,bymonth=8,bymonthday=13,byweekday=FR)[0].year + >>> rdelta = relativedelta(easter(year), today) + >>> print("Today is: %s" % today) + Today is: 2003-10-11 + >>> print("Year with next Aug 13th on a Friday is: %s" % year) + Year with next Aug 13th on a Friday is: 2004 + >>> print("How far is the Easter of that year: %s" % rdelta) + How far is the Easter of that year: relativedelta(months=+6) + >>> print("And the Easter of that year is: %s" % (today+rdelta)) + And the Easter of that year is: 2004-04-11 + +Being exactly 6 months ahead was **really** a coincidence :) + +Contributing +============ + +We welcome many types of contributions - bug reports, pull requests (code, infrastructure or documentation fixes). For more information about how to contribute to the project, see the ``CONTRIBUTING.md`` file in the repository. + + +Author +====== +The dateutil module was written by Gustavo Niemeyer <gustavo@niemeyer.net> +in 2003. + +It is maintained by: + +* Gustavo Niemeyer <gustavo@niemeyer.net> 2003-2011 +* Tomi Pieviläinen <tomi.pievilainen@iki.fi> 2012-2014 +* Yaron de Leeuw <me@jarondl.net> 2014-2016 +* Paul Ganssle <paul@ganssle.io> 2015- + +Starting with version 2.4.1 and running until 2.8.2, all source and binary +distributions will be signed by a PGP key that has, at the very least, been +signed by the key which made the previous release. A table of release signing +keys can be found below: + +=========== ============================ +Releases Signing key fingerprint +=========== ============================ +2.4.1-2.8.2 `6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB`_ +=========== ============================ + +New releases *may* have signed tags, but binary and source distributions +uploaded to PyPI will no longer have GPG signatures attached. + +Contact +======= +Our mailing list is available at `dateutil@python.org <https://mail.python.org/mailman/listinfo/dateutil>`_. As it is hosted by the PSF, it is subject to the `PSF code of +conduct <https://www.python.org/psf/conduct/>`_. + +License +======= + +All contributions after December 1, 2017 released under dual license - either `Apache 2.0 License <https://www.apache.org/licenses/LICENSE-2.0>`_ or the `BSD 3-Clause License <https://opensource.org/licenses/BSD-3-Clause>`_. Contributions before December 1, 2017 - except those those explicitly relicensed - are released only under the BSD 3-Clause License. + + +.. _6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB: + https://pgp.mit.edu/pks/lookup?op=vindex&search=0xCD54FCE3D964BEFB + + diff --git a/contrib/python/dateutil/.dist-info/top_level.txt b/contrib/python/dateutil/.dist-info/top_level.txt index 66501480ba..629459ea16 100644 --- a/contrib/python/dateutil/.dist-info/top_level.txt +++ b/contrib/python/dateutil/.dist-info/top_level.txt @@ -1 +1 @@ -dateutil +dateutil diff --git a/contrib/python/dateutil/AUTHORS.md b/contrib/python/dateutil/AUTHORS.md index fa9184207f..19668e2268 100644 --- a/contrib/python/dateutil/AUTHORS.md +++ b/contrib/python/dateutil/AUTHORS.md @@ -1,130 +1,130 @@ -This is a (possibly incomplete) list of all the contributors to python-dateutil, -initially generated from the git author metadata. The details of their specific -contributions can be found in the git history. - -Prior to 2017-12-01, the library was licensed solely under the BSD 3-clause -license, all contributions on or after 2017-12-01 are dual-licensed between -Apache 2.0 and BSD 3-clause. In the list below, anyone whose name is marked with -**R** has agreed to re-license their previously submitted code under Apache 2.0. -Anyone whose name is marked with a **D** has only made contributions since the -switch, and thus all their contributions are dual-licensed. - -## Contributors (alphabetical order) - -- Adam Chainz <adam@MASKED> -- Adrien Cossa <cossa@MASKED> -- Alec Nikolas Reiter <alecreiter@MASKED> -- Alec Reiter <areiter@MASKED> -- Alex Chamberlain (gh: @alexchamberlain) **D** -- Alex Verdyan <verdyan@MASKED> -- Alex Willmer <alex@moreati.org.uk> (gh: @moreati) **R** -- Alexander Brugh <alexander.brugh@MASKED> (gh: @abrugh) -- Alexander Shadchin <alexandr.shadchin@gmail.com> (gh: @shadchin) **D** -- Alistair McMaster <alistair@MASKED> (gh: @alimcmaster1 ) **D** -- Allison Quinlan <aquinlan82@gmail.com> (gh: @aquinlan) **D** -- Andrew Bennett (gh: @andrewcbennett) **D** -- Andrew Murray <radarhere@MASKED> -- Arclight <arclight@MASKED> (gh: @arclightslavik) -- Aritro Nandi <gurgenz221@gmail.com> (gh: @gurgenz221) **D** -- Bernat Gabor <bgabor8@bloomberg.net> (gh: @gaborbernat) **D** -- Bradlee Speice <bradlee@speice.io> (gh: @bspeice) **D** -- Brandon W Maister <quodlibetor@MASKED> -- Brock Mendel <jbrockmendel@MASKED> (gh: @jbrockmendel) **R** -- Brook Li (gh: @absreim) **D** -- Carlos <carlosxl@MASKED> -- Cheuk Ting Ho <cheukting.ho@gmail.com> (gh: @cheukting) **D** -- Chris van den Berg (gh: bergvca) **D** -- Christopher Cordero <ccordero@pm.me> (gh: cs-cordero) **D** -- Christopher Corley <cscorley@MASKED> -- Claudio Canepa <ccanepacc@MASKED> -- Corey Girard <corey.r.girard@gmail.com> (gh: @coreygirard) **D** -- Cosimo Lupo <cosimo@anthrotype.com> (gh: @anthrotype) **D** -- Daniel Lemm (gh: @ffe4) **D** -- Daniel Lepage <dplepage@MASKED> -- David Lehrian <david@MASKED> -- Dean Allsopp (gh: @daplantagenet) **D** -- Dominik Kozaczko <dominik@MASKED> -- Elliot Hughes <elliot.hughes@gmail.com> (gh: @ElliotJH) **D** -- Elvis Pranskevichus <el@MASKED> -- Fan Huang <fanhuang.scb@gmail.com>(gh: @fhuang5) **D** -- Florian Rathgeber (gh: @kynan) **D** -- Gabriel Bianconi <gabriel@MASKED> (gh: @GabrielBianconi) **D** -- Gabriel Poesia <gabriel.poesia@MASKED> -- Gökçen Nurlu <gnurlu1@bloomberg.net> (gh: @gokcennurlu) **D** -- Grant Garrett-Grossman <grantlycee@gmail.com> (gh: @FakeNameSE) **D** -- Gustavo Niemeyer <gustavo@niemeyer.net> (gh: @niemeyer) -- Holger Joukl <holger.joukl@MASKED> (gh: @hjoukl) -- Hugo van Kemenade (gh: @hugovk) **D** -- Igor <mrigor83@MASKED> -- Ionuț Ciocîrlan <jdxlark@MASKED> -- Jacqueline Chen <jacqueline415@outlook.com> (gh: @jachen20) **D** -- Jake Chorley (gh: @jakec-github) **D** -- Jan Studený <jendas1@MASKED> -- Jay Weisskopf <jay@jayschwa.net> (gh: @jayschwa) **D** -- Jitesh <jitesh@MASKED> -- John Purviance <jpurviance@MASKED> (gh @jpurviance) **D** -- Jon Dufresne <jon.dufresne@MASKED> (gh: @jdufresne) **R** -- Jonas Neubert <jonas@MASKED> (gh: @jonemo) **R** -- Kevin Nguyen <kvn219@MASKED> **D** -- Kirit Thadaka <kirit.thadaka@gmail.com> (gh: @kirit93) **D** -- Kubilay Kocak <koobs@MASKED> -- Laszlo Kiss Kollar <kiss.kollar.laszlo@MASKED> (gh: @lkollar) **D** -- Lauren Oldja <oldja@MASKED> (gh: @loldja) **D** -- Luca Ferocino <luca.ferox@MASKED> (gh: @lucaferocino) **D** -- Mario Corchero <mcorcherojim@MASKED> (gh: @mariocj89) **R** -- Mark Bailey <msb@MASKED> **D** -- Mateusz Dziedzic (gh: @m-dz) **D** -- Matt Cooper <vtbassmatt@MASKED> (gh: @vtbassmatt) **D** -- Matthew Schinckel <matt@MASKED> -- Max Shenfield <shenfieldmax@MASKED> -- Maxime Lorant <maxime.lorant@MASKED> -- Michael Aquilina <michaelaquilina@MASKED> (gh: @MichaelAquilina) -- Michael J. Schultz <mjschultz@MASKED> -- Michael Käufl (gh: @michael-k) -- Mike Gilbert <floppym@MASKED> -- Nicholas Herrriot <Nicholas.Herriot@gmail.com> **D** -- Nicolas Évrard (gh: @nicoe) **D** -- Nick Smith <nick.smith@MASKED> -- Orson Adams <orson.network@MASKED> (gh: @parsethis) **D** -- Paul Brown (gh: @pawl) **D** -- Paul Dickson (gh @prdickson) **D** -- Paul Ganssle <paul@ganssle.io> (gh: @pganssle) **R** -- Pascal van Kooten <kootenpv@MASKED> (gh: @kootenpv) **R** -- Pavel Ponomarev <comrad.awsum@MASKED> -- Peter Bieringer <pb@MASKED> -- Pierre Gergondet <pierre.gergondet@MASKED> (gh: @gergondet) **D** -- Quentin Pradet <quentin@MASKED> -- Raymond Cha (gh: @weatherpattern) **D** -- Ridhi Mahajan <ridhikmahajan@MASKED> **D** -- Robin Henriksson Törnström <gh: @MrRawbin> **D** -- Roy Williams <rwilliams@MASKED> -- Rustem Saiargaliev (gh: @amureki) **D** -- Satyabrat Bhol <satyabrat35@MASKED> (gh: @Satyabrat35) **D** -- Savraj <savraj@MASKED> -- Sergey Vishnikin <armicron@MASKED> -- Sherry Zhou (gh: @cssherry) **D** -- Siping Meng (gh: @smeng10) **D** -- Stefan Bonchev **D** -- Thierry Bastian <thierryb@MASKED> -- Thomas A Caswell <tcaswell@MASKED> (gh: @tacaswell) **R** -- Thomas Achtemichuk <tom@MASKED> -- Thomas Kluyver <takowl@MASKED> (gh: @takluyver) -- Tim Gates <tim.gates@iress.com> (gh: timgates42) -- Tomasz Kluczkowski (gh: @Tomasz-Kluczkowski) **D** -- Tomi Pieviläinen <tomi.pievilainen@iki.fi> -- Unrud <Unrud@MASKED> (gh: @unrud) -- Xavier Lapointe <lapointe.xavier@MASKED> (gh: @lapointexavier) **D** -- X O <xo@MASKED> -- Yaron de Leeuw <me@jarondl.net> (gh: @jarondl) -- Yoney <alper_yoney@hotmail.com> **D** -- Yuan Huang <huangy22@gmail.com> (gh: @huangy22) **D** -- Zbigniew Jędrzejewski-Szmek <zbyszek@MASKED> -- bachmann <bachmann.matt@MASKED> -- bjv <brandon.vanvaerenbergh@MASKED> (@bjamesvERT) -- gl <gl@MASKED> -- gfyoung <gfyoung17@gmail.com> **D** -- Labrys <labrys.git@gmail.com> (gh: @labrys) **R** -- ms-boom <ms-boom@MASKED> -- ryanss <ryanssdev@MASKED> (gh: @ryanss) **R** - -Unless someone has deliberately given permission to publish their e-mail, I have masked the domain names. If you are not on this list and believe you should be, or you *are* on this list and your information is inaccurate, please e-mail the current maintainer or the mailing list (dateutil@python.org) with your name, e-mail (if desired) and GitHub (if desired / applicable), as you would like them displayed. Additionally, please indicate if you are willing to dual license your old contributions under Apache 2.0. +This is a (possibly incomplete) list of all the contributors to python-dateutil, +initially generated from the git author metadata. The details of their specific +contributions can be found in the git history. + +Prior to 2017-12-01, the library was licensed solely under the BSD 3-clause +license, all contributions on or after 2017-12-01 are dual-licensed between +Apache 2.0 and BSD 3-clause. In the list below, anyone whose name is marked with +**R** has agreed to re-license their previously submitted code under Apache 2.0. +Anyone whose name is marked with a **D** has only made contributions since the +switch, and thus all their contributions are dual-licensed. + +## Contributors (alphabetical order) + +- Adam Chainz <adam@MASKED> +- Adrien Cossa <cossa@MASKED> +- Alec Nikolas Reiter <alecreiter@MASKED> +- Alec Reiter <areiter@MASKED> +- Alex Chamberlain (gh: @alexchamberlain) **D** +- Alex Verdyan <verdyan@MASKED> +- Alex Willmer <alex@moreati.org.uk> (gh: @moreati) **R** +- Alexander Brugh <alexander.brugh@MASKED> (gh: @abrugh) +- Alexander Shadchin <alexandr.shadchin@gmail.com> (gh: @shadchin) **D** +- Alistair McMaster <alistair@MASKED> (gh: @alimcmaster1 ) **D** +- Allison Quinlan <aquinlan82@gmail.com> (gh: @aquinlan) **D** +- Andrew Bennett (gh: @andrewcbennett) **D** +- Andrew Murray <radarhere@MASKED> +- Arclight <arclight@MASKED> (gh: @arclightslavik) +- Aritro Nandi <gurgenz221@gmail.com> (gh: @gurgenz221) **D** +- Bernat Gabor <bgabor8@bloomberg.net> (gh: @gaborbernat) **D** +- Bradlee Speice <bradlee@speice.io> (gh: @bspeice) **D** +- Brandon W Maister <quodlibetor@MASKED> +- Brock Mendel <jbrockmendel@MASKED> (gh: @jbrockmendel) **R** +- Brook Li (gh: @absreim) **D** +- Carlos <carlosxl@MASKED> +- Cheuk Ting Ho <cheukting.ho@gmail.com> (gh: @cheukting) **D** +- Chris van den Berg (gh: bergvca) **D** +- Christopher Cordero <ccordero@pm.me> (gh: cs-cordero) **D** +- Christopher Corley <cscorley@MASKED> +- Claudio Canepa <ccanepacc@MASKED> +- Corey Girard <corey.r.girard@gmail.com> (gh: @coreygirard) **D** +- Cosimo Lupo <cosimo@anthrotype.com> (gh: @anthrotype) **D** +- Daniel Lemm (gh: @ffe4) **D** +- Daniel Lepage <dplepage@MASKED> +- David Lehrian <david@MASKED> +- Dean Allsopp (gh: @daplantagenet) **D** +- Dominik Kozaczko <dominik@MASKED> +- Elliot Hughes <elliot.hughes@gmail.com> (gh: @ElliotJH) **D** +- Elvis Pranskevichus <el@MASKED> +- Fan Huang <fanhuang.scb@gmail.com>(gh: @fhuang5) **D** +- Florian Rathgeber (gh: @kynan) **D** +- Gabriel Bianconi <gabriel@MASKED> (gh: @GabrielBianconi) **D** +- Gabriel Poesia <gabriel.poesia@MASKED> +- Gökçen Nurlu <gnurlu1@bloomberg.net> (gh: @gokcennurlu) **D** +- Grant Garrett-Grossman <grantlycee@gmail.com> (gh: @FakeNameSE) **D** +- Gustavo Niemeyer <gustavo@niemeyer.net> (gh: @niemeyer) +- Holger Joukl <holger.joukl@MASKED> (gh: @hjoukl) +- Hugo van Kemenade (gh: @hugovk) **D** +- Igor <mrigor83@MASKED> +- Ionuț Ciocîrlan <jdxlark@MASKED> +- Jacqueline Chen <jacqueline415@outlook.com> (gh: @jachen20) **D** +- Jake Chorley (gh: @jakec-github) **D** +- Jan Studený <jendas1@MASKED> +- Jay Weisskopf <jay@jayschwa.net> (gh: @jayschwa) **D** +- Jitesh <jitesh@MASKED> +- John Purviance <jpurviance@MASKED> (gh @jpurviance) **D** +- Jon Dufresne <jon.dufresne@MASKED> (gh: @jdufresne) **R** +- Jonas Neubert <jonas@MASKED> (gh: @jonemo) **R** +- Kevin Nguyen <kvn219@MASKED> **D** +- Kirit Thadaka <kirit.thadaka@gmail.com> (gh: @kirit93) **D** +- Kubilay Kocak <koobs@MASKED> +- Laszlo Kiss Kollar <kiss.kollar.laszlo@MASKED> (gh: @lkollar) **D** +- Lauren Oldja <oldja@MASKED> (gh: @loldja) **D** +- Luca Ferocino <luca.ferox@MASKED> (gh: @lucaferocino) **D** +- Mario Corchero <mcorcherojim@MASKED> (gh: @mariocj89) **R** +- Mark Bailey <msb@MASKED> **D** +- Mateusz Dziedzic (gh: @m-dz) **D** +- Matt Cooper <vtbassmatt@MASKED> (gh: @vtbassmatt) **D** +- Matthew Schinckel <matt@MASKED> +- Max Shenfield <shenfieldmax@MASKED> +- Maxime Lorant <maxime.lorant@MASKED> +- Michael Aquilina <michaelaquilina@MASKED> (gh: @MichaelAquilina) +- Michael J. Schultz <mjschultz@MASKED> +- Michael Käufl (gh: @michael-k) +- Mike Gilbert <floppym@MASKED> +- Nicholas Herrriot <Nicholas.Herriot@gmail.com> **D** +- Nicolas Évrard (gh: @nicoe) **D** +- Nick Smith <nick.smith@MASKED> +- Orson Adams <orson.network@MASKED> (gh: @parsethis) **D** +- Paul Brown (gh: @pawl) **D** +- Paul Dickson (gh @prdickson) **D** +- Paul Ganssle <paul@ganssle.io> (gh: @pganssle) **R** +- Pascal van Kooten <kootenpv@MASKED> (gh: @kootenpv) **R** +- Pavel Ponomarev <comrad.awsum@MASKED> +- Peter Bieringer <pb@MASKED> +- Pierre Gergondet <pierre.gergondet@MASKED> (gh: @gergondet) **D** +- Quentin Pradet <quentin@MASKED> +- Raymond Cha (gh: @weatherpattern) **D** +- Ridhi Mahajan <ridhikmahajan@MASKED> **D** +- Robin Henriksson Törnström <gh: @MrRawbin> **D** +- Roy Williams <rwilliams@MASKED> +- Rustem Saiargaliev (gh: @amureki) **D** +- Satyabrat Bhol <satyabrat35@MASKED> (gh: @Satyabrat35) **D** +- Savraj <savraj@MASKED> +- Sergey Vishnikin <armicron@MASKED> +- Sherry Zhou (gh: @cssherry) **D** +- Siping Meng (gh: @smeng10) **D** +- Stefan Bonchev **D** +- Thierry Bastian <thierryb@MASKED> +- Thomas A Caswell <tcaswell@MASKED> (gh: @tacaswell) **R** +- Thomas Achtemichuk <tom@MASKED> +- Thomas Kluyver <takowl@MASKED> (gh: @takluyver) +- Tim Gates <tim.gates@iress.com> (gh: timgates42) +- Tomasz Kluczkowski (gh: @Tomasz-Kluczkowski) **D** +- Tomi Pieviläinen <tomi.pievilainen@iki.fi> +- Unrud <Unrud@MASKED> (gh: @unrud) +- Xavier Lapointe <lapointe.xavier@MASKED> (gh: @lapointexavier) **D** +- X O <xo@MASKED> +- Yaron de Leeuw <me@jarondl.net> (gh: @jarondl) +- Yoney <alper_yoney@hotmail.com> **D** +- Yuan Huang <huangy22@gmail.com> (gh: @huangy22) **D** +- Zbigniew Jędrzejewski-Szmek <zbyszek@MASKED> +- bachmann <bachmann.matt@MASKED> +- bjv <brandon.vanvaerenbergh@MASKED> (@bjamesvERT) +- gl <gl@MASKED> +- gfyoung <gfyoung17@gmail.com> **D** +- Labrys <labrys.git@gmail.com> (gh: @labrys) **R** +- ms-boom <ms-boom@MASKED> +- ryanss <ryanssdev@MASKED> (gh: @ryanss) **R** + +Unless someone has deliberately given permission to publish their e-mail, I have masked the domain names. If you are not on this list and believe you should be, or you *are* on this list and your information is inaccurate, please e-mail the current maintainer or the mailing list (dateutil@python.org) with your name, e-mail (if desired) and GitHub (if desired / applicable), as you would like them displayed. Additionally, please indicate if you are willing to dual license your old contributions under Apache 2.0. diff --git a/contrib/python/dateutil/LICENSE b/contrib/python/dateutil/LICENSE index 1e65815cf0..50e6fe0257 100644 --- a/contrib/python/dateutil/LICENSE +++ b/contrib/python/dateutil/LICENSE @@ -1,54 +1,54 @@ -Copyright 2017- Paul Ganssle <paul@ganssle.io> -Copyright 2017- dateutil contributors (see AUTHORS file) - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -The above license applies to all contributions after 2017-12-01, as well as -all contributions that have been re-licensed (see AUTHORS file for the list of -contributors who have re-licensed their code). --------------------------------------------------------------------------------- -dateutil - Extensions to the standard Python datetime module. - -Copyright (c) 2003-2011 - Gustavo Niemeyer <gustavo@niemeyer.net> -Copyright (c) 2012-2014 - Tomi Pieviläinen <tomi.pievilainen@iki.fi> -Copyright (c) 2014-2016 - Yaron de Leeuw <me@jarondl.net> -Copyright (c) 2015- - Paul Ganssle <paul@ganssle.io> -Copyright (c) 2015- - dateutil contributors (see AUTHORS file) - -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 copyright holder 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 (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The above BSD License Applies to all code, even that also covered by Apache 2.0.
\ No newline at end of file +Copyright 2017- Paul Ganssle <paul@ganssle.io> +Copyright 2017- dateutil contributors (see AUTHORS file) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +The above license applies to all contributions after 2017-12-01, as well as +all contributions that have been re-licensed (see AUTHORS file for the list of +contributors who have re-licensed their code). +-------------------------------------------------------------------------------- +dateutil - Extensions to the standard Python datetime module. + +Copyright (c) 2003-2011 - Gustavo Niemeyer <gustavo@niemeyer.net> +Copyright (c) 2012-2014 - Tomi Pieviläinen <tomi.pievilainen@iki.fi> +Copyright (c) 2014-2016 - Yaron de Leeuw <me@jarondl.net> +Copyright (c) 2015- - Paul Ganssle <paul@ganssle.io> +Copyright (c) 2015- - dateutil contributors (see AUTHORS file) + +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 copyright holder 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 (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The above BSD License Applies to all code, even that also covered by Apache 2.0.
\ No newline at end of file diff --git a/contrib/python/dateutil/README.rst b/contrib/python/dateutil/README.rst index 106023b324..b7461b951f 100644 --- a/contrib/python/dateutil/README.rst +++ b/contrib/python/dateutil/README.rst @@ -1,11 +1,11 @@ dateutil - powerful extensions to datetime ========================================== -|pypi| |support| |licence| +|pypi| |support| |licence| |gitter| |readthedocs| -|travis| |appveyor| |pipelines| |coverage| +|travis| |appveyor| |pipelines| |coverage| .. |pypi| image:: https://img.shields.io/pypi/v/python-dateutil.svg?style=flat-square :target: https://pypi.org/project/python-dateutil/ @@ -23,12 +23,12 @@ dateutil - powerful extensions to datetime :target: https://ci.appveyor.com/project/dateutil/dateutil :alt: appveyor build status -.. |pipelines| image:: https://dev.azure.com/pythondateutilazure/dateutil/_apis/build/status/dateutil.dateutil?branchName=master - :target: https://dev.azure.com/pythondateutilazure/dateutil/_build/latest?definitionId=1&branchName=master - :alt: azure pipelines build status - -.. |coverage| image:: https://codecov.io/gh/dateutil/dateutil/branch/master/graphs/badge.svg?branch=master - :target: https://codecov.io/gh/dateutil/dateutil?branch=master +.. |pipelines| image:: https://dev.azure.com/pythondateutilazure/dateutil/_apis/build/status/dateutil.dateutil?branchName=master + :target: https://dev.azure.com/pythondateutilazure/dateutil/_build/latest?definitionId=1&branchName=master + :alt: azure pipelines build status + +.. |coverage| image:: https://codecov.io/gh/dateutil/dateutil/branch/master/graphs/badge.svg?branch=master + :target: https://codecov.io/gh/dateutil/dateutil?branch=master :alt: Code coverage .. |gitter| image:: https://badges.gitter.im/dateutil/dateutil.svg @@ -46,13 +46,13 @@ dateutil - powerful extensions to datetime The `dateutil` module provides powerful extensions to the standard `datetime` module, available in Python. -Installation -============ -`dateutil` can be installed from PyPI using `pip` (note that the package name is -different from the importable name):: - - pip install python-dateutil +Installation +============ +`dateutil` can be installed from PyPI using `pip` (note that the package name is +different from the importable name):: + pip install python-dateutil + Download ======== dateutil is available on PyPI @@ -63,14 +63,14 @@ https://dateutil.readthedocs.io/en/stable/ Code ==== -The code and issue tracker are hosted on GitHub: +The code and issue tracker are hosted on GitHub: https://github.com/dateutil/dateutil/ Features ======== * Computing of relative deltas (next month, next year, - next Monday, last week of month, etc); + next Monday, last week of month, etc); * Computing of relative deltas between two given date and/or datetime objects; * Computing of dates based on very flexible recurrence rules, @@ -139,24 +139,24 @@ It is maintained by: * Yaron de Leeuw <me@jarondl.net> 2014-2016 * Paul Ganssle <paul@ganssle.io> 2015- -Starting with version 2.4.1 and running until 2.8.2, all source and binary -distributions will be signed by a PGP key that has, at the very least, been -signed by the key which made the previous release. A table of release signing -keys can be found below: +Starting with version 2.4.1 and running until 2.8.2, all source and binary +distributions will be signed by a PGP key that has, at the very least, been +signed by the key which made the previous release. A table of release signing +keys can be found below: =========== ============================ Releases Signing key fingerprint =========== ============================ -2.4.1-2.8.2 `6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB`_ +2.4.1-2.8.2 `6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB`_ =========== ============================ -New releases *may* have signed tags, but binary and source distributions -uploaded to PyPI will no longer have GPG signatures attached. +New releases *may* have signed tags, but binary and source distributions +uploaded to PyPI will no longer have GPG signatures attached. Contact ======= Our mailing list is available at `dateutil@python.org <https://mail.python.org/mailman/listinfo/dateutil>`_. As it is hosted by the PSF, it is subject to the `PSF code of -conduct <https://www.python.org/psf/conduct/>`_. +conduct <https://www.python.org/psf/conduct/>`_. License ======= diff --git a/contrib/python/dateutil/dateutil/_version.py b/contrib/python/dateutil/dateutil/_version.py index b723056a75..1f875d99b3 100644 --- a/contrib/python/dateutil/dateutil/_version.py +++ b/contrib/python/dateutil/dateutil/_version.py @@ -1,5 +1,5 @@ # coding: utf-8 # file generated by setuptools_scm # don't change, don't track in version control -version = '2.8.2' -version_tuple = (2, 8, 2) +version = '2.8.2' +version_tuple = (2, 8, 2) diff --git a/contrib/python/dateutil/dateutil/easter.py b/contrib/python/dateutil/dateutil/easter.py index f74d1f7442..9a200a7021 100644 --- a/contrib/python/dateutil/dateutil/easter.py +++ b/contrib/python/dateutil/dateutil/easter.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ -This module offers a generic Easter computing method for any given year, using +This module offers a generic Easter computing method for any given year, using Western, Orthodox or Julian algorithms. """ @@ -21,15 +21,15 @@ def easter(year, method=EASTER_WESTERN): quoted in "Explanatory Supplement to the Astronomical Almanac", P. Kenneth Seidelmann, editor. - This algorithm implements three different Easter + This algorithm implements three different Easter calculation methods: - 1. Original calculation in Julian calendar, valid in - dates after 326 AD - 2. Original method, with date converted to Gregorian - calendar, valid in years 1583 to 4099 - 3. Revised method, in Gregorian calendar, valid in - years 1583 to 4099 as well + 1. Original calculation in Julian calendar, valid in + dates after 326 AD + 2. Original method, with date converted to Gregorian + calendar, valid in years 1583 to 4099 + 3. Revised method, in Gregorian calendar, valid in + years 1583 to 4099 as well These methods are represented by the constants: diff --git a/contrib/python/dateutil/dateutil/parser/__init__.py b/contrib/python/dateutil/dateutil/parser/__init__.py index d174b0e4dc..676f701184 100644 --- a/contrib/python/dateutil/dateutil/parser/__init__.py +++ b/contrib/python/dateutil/dateutil/parser/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from ._parser import parse, parser, parserinfo, ParserError +from ._parser import parse, parser, parserinfo, ParserError from ._parser import DEFAULTPARSER, DEFAULTTZPARSER from ._parser import UnknownTimezoneWarning @@ -9,7 +9,7 @@ from .isoparser import isoparser, isoparse __all__ = ['parse', 'parser', 'parserinfo', 'isoparse', 'isoparser', - 'ParserError', + 'ParserError', 'UnknownTimezoneWarning'] @@ -52,8 +52,8 @@ def __deprecate_private_class(c): return private_class -from ._parser import _timelex, _resultbase -from ._parser import _tzparser, _parsetz +from ._parser import _timelex, _resultbase +from ._parser import _tzparser, _parsetz _timelex = __deprecate_private_class(_timelex) _tzparser = __deprecate_private_class(_tzparser) diff --git a/contrib/python/dateutil/dateutil/parser/_parser.py b/contrib/python/dateutil/dateutil/parser/_parser.py index 37d1663b2f..4436fd363e 100644 --- a/contrib/python/dateutil/dateutil/parser/_parser.py +++ b/contrib/python/dateutil/dateutil/parser/_parser.py @@ -20,11 +20,11 @@ value falls back to the end of the month. Additional resources about date/time string formats can be found below: - `A summary of the international standard date and time notation - <https://www.cl.cam.ac.uk/~mgk25/iso-time.html>`_ -- `W3C Date and Time Formats <https://www.w3.org/TR/NOTE-datetime>`_ + <https://www.cl.cam.ac.uk/~mgk25/iso-time.html>`_ +- `W3C Date and Time Formats <https://www.w3.org/TR/NOTE-datetime>`_ - `Time Formats (Planetary Rings Node) <https://pds-rings.seti.org:443/tools/time_formats.html>`_ - `CPAN ParseDate module - <https://metacpan.org/pod/release/MUIR/Time-modules-2013.0912/lib/Time/ParseDate.pm>`_ + <https://metacpan.org/pod/release/MUIR/Time-modules-2013.0912/lib/Time/ParseDate.pm>`_ - `Java SimpleDateFormat Class <https://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html>`_ """ @@ -40,7 +40,7 @@ from calendar import monthrange from io import StringIO import six -from six import integer_types, text_type +from six import integer_types, text_type from decimal import Decimal @@ -49,7 +49,7 @@ from warnings import warn from .. import relativedelta from .. import tz -__all__ = ["parse", "parserinfo", "ParserError"] +__all__ = ["parse", "parserinfo", "ParserError"] # TODO: pandas.core.tools.datetimes imports this explicitly. Might be worth @@ -60,8 +60,8 @@ class _timelex(object): _split_decimal = re.compile("([.,])") def __init__(self, instream): - if isinstance(instream, (bytes, bytearray)): - instream = instream.decode() + if isinstance(instream, (bytes, bytearray)): + instream = instream.decode() if isinstance(instream, text_type): instream = StringIO(instream) @@ -285,7 +285,7 @@ class parserinfo(object): ("s", "second", "seconds")] AMPM = [("am", "a"), ("pm", "p")] - UTCZONE = ["UTC", "GMT", "Z", "z"] + UTCZONE = ["UTC", "GMT", "Z", "z"] PERTAIN = ["of"] TZOFFSET = {} # TODO: ERA = ["AD", "BC", "CE", "BCE", "Stardate", @@ -382,8 +382,8 @@ class parserinfo(object): if res.year is not None: res.year = self.convertyear(res.year, res.century_specified) - if ((res.tzoffset == 0 and not res.tzname) or - (res.tzname == 'Z' or res.tzname == 'z')): + if ((res.tzoffset == 0 and not res.tzname) or + (res.tzname == 'Z' or res.tzname == 'z')): res.tzname = "UTC" res.tzoffset = 0 elif res.tzoffset != 0 and res.tzname and self.utczone(res.tzname): @@ -417,7 +417,7 @@ class _ymd(list): elif not self.has_month: return 1 <= value <= 31 elif not self.has_year: - # Be permissive, assume leap year + # Be permissive, assume leap year month = self[self.mstridx] return 1 <= value <= monthrange(2000, month)[1] else: @@ -533,7 +533,7 @@ class _ymd(list): year, month, day = self else: # 01-Jan-01 - # Give precedence to day-first, since + # Give precedence to day-first, since # two-digit years is usually hand-written. day, month, year = self @@ -620,7 +620,7 @@ class parser(object): first element being a :class:`datetime.datetime` object, the second a tuple containing the fuzzy tokens. - :raises ParserError: + :raises ParserError: Raised for invalid or unknown string format, if the provided :class:`tzinfo` is not in a valid format, or if an invalid date would be created. @@ -640,15 +640,15 @@ class parser(object): res, skipped_tokens = self._parse(timestr, **kwargs) if res is None: - raise ParserError("Unknown string format: %s", timestr) + raise ParserError("Unknown string format: %s", timestr) if len(res) == 0: - raise ParserError("String does not contain a date: %s", timestr) + raise ParserError("String does not contain a date: %s", timestr) - try: - ret = self._build_naive(res, default) - except ValueError as e: - six.raise_from(ParserError(str(e) + ": %s", timestr), e) + try: + ret = self._build_naive(res, default) + except ValueError as e: + six.raise_from(ParserError(str(e) + ": %s", timestr), e) if not ignoretz: ret = self._build_tzaware(ret, res, tzinfos) @@ -1019,7 +1019,7 @@ class parser(object): hms_idx = idx + 2 elif idx > 0 and info.hms(tokens[idx-1]) is not None: - # There is a "h", "m", or "s" preceding this token. Since neither + # There is a "h", "m", or "s" preceding this token. Since neither # of the previous cases was hit, there is no label following this # token, so we use the previous label. # e.g. the "04" in "12h04" @@ -1058,8 +1058,8 @@ class parser(object): tzname is None and tzoffset is None and len(token) <= 5 and - (all(x in string.ascii_uppercase for x in token) - or token in self.info.UTCZONE)) + (all(x in string.ascii_uppercase for x in token) + or token in self.info.UTCZONE)) def _ampm_valid(self, hour, ampm, fuzzy): """ @@ -1099,7 +1099,7 @@ class parser(object): def _parse_min_sec(self, value): # TODO: Every usage of this function sets res.second to the return # value. Are there any cases where second will be returned as None and - # we *don't* want to set res.second = None? + # we *don't* want to set res.second = None? minute = int(value) second = None @@ -1126,36 +1126,36 @@ class parser(object): return (new_idx, hms) - # ------------------------------------------------------------------ - # Handling for individual tokens. These are kept as methods instead - # of functions for the sake of customizability via subclassing. - - def _parsems(self, value): - """Parse a I[.F] seconds value into (seconds, microseconds).""" - if "." not in value: - return int(value), 0 - else: - i, f = value.split(".") - return int(i), int(f.ljust(6, "0")[:6]) - - def _to_decimal(self, val): - try: - decimal_value = Decimal(val) - # See GH 662, edge case, infinite value should not be converted - # via `_to_decimal` - if not decimal_value.is_finite(): - raise ValueError("Converted decimal value is infinite or NaN") - except Exception as e: - msg = "Could not convert %s to decimal" % val - six.raise_from(ValueError(msg), e) - else: - return decimal_value - - # ------------------------------------------------------------------ - # Post-Parsing construction of datetime output. These are kept as - # methods instead of functions for the sake of customizability via - # subclassing. - + # ------------------------------------------------------------------ + # Handling for individual tokens. These are kept as methods instead + # of functions for the sake of customizability via subclassing. + + def _parsems(self, value): + """Parse a I[.F] seconds value into (seconds, microseconds).""" + if "." not in value: + return int(value), 0 + else: + i, f = value.split(".") + return int(i), int(f.ljust(6, "0")[:6]) + + def _to_decimal(self, val): + try: + decimal_value = Decimal(val) + # See GH 662, edge case, infinite value should not be converted + # via `_to_decimal` + if not decimal_value.is_finite(): + raise ValueError("Converted decimal value is infinite or NaN") + except Exception as e: + msg = "Could not convert %s to decimal" % val + six.raise_from(ValueError(msg), e) + else: + return decimal_value + + # ------------------------------------------------------------------ + # Post-Parsing construction of datetime output. These are kept as + # methods instead of functions for the sake of customizability via + # subclassing. + def _build_tzinfo(self, tzinfos, tzname, tzoffset): if callable(tzinfos): tzdata = tzinfos(tzname, tzoffset) @@ -1169,9 +1169,9 @@ class parser(object): tzinfo = tz.tzstr(tzdata) elif isinstance(tzdata, integer_types): tzinfo = tz.tzoffset(tzname, tzdata) - else: - raise TypeError("Offset must be tzinfo subclass, tz string, " - "or int offset.") + else: + raise TypeError("Offset must be tzinfo subclass, tz string, " + "or int offset.") return tzinfo def _build_tzaware(self, naive, res, tzinfos): @@ -1189,10 +1189,10 @@ class parser(object): # This is mostly relevant for winter GMT zones parsed in the UK if (aware.tzname() != res.tzname and res.tzname in self.info.UTCZONE): - aware = aware.replace(tzinfo=tz.UTC) + aware = aware.replace(tzinfo=tz.UTC) elif res.tzoffset == 0: - aware = naive.replace(tzinfo=tz.UTC) + aware = naive.replace(tzinfo=tz.UTC) elif res.tzoffset: aware = naive.replace(tzinfo=tz.tzoffset(res.tzname, res.tzoffset)) @@ -1247,23 +1247,23 @@ class parser(object): return dt - def _recombine_skipped(self, tokens, skipped_idxs): - """ - >>> tokens = ["foo", " ", "bar", " ", "19June2000", "baz"] - >>> skipped_idxs = [0, 1, 2, 5] - >>> _recombine_skipped(tokens, skipped_idxs) - ["foo bar", "baz"] - """ - skipped_tokens = [] - for i, idx in enumerate(sorted(skipped_idxs)): - if i > 0 and idx - 1 == skipped_idxs[i - 1]: - skipped_tokens[-1] = skipped_tokens[-1] + tokens[idx] - else: - skipped_tokens.append(tokens[idx]) - - return skipped_tokens - - + def _recombine_skipped(self, tokens, skipped_idxs): + """ + >>> tokens = ["foo", " ", "bar", " ", "19June2000", "baz"] + >>> skipped_idxs = [0, 1, 2, 5] + >>> _recombine_skipped(tokens, skipped_idxs) + ["foo bar", "baz"] + """ + skipped_tokens = [] + for i, idx in enumerate(sorted(skipped_idxs)): + if i > 0 and idx - 1 == skipped_idxs[i - 1]: + skipped_tokens[-1] = skipped_tokens[-1] + tokens[idx] + else: + skipped_tokens.append(tokens[idx]) + + return skipped_tokens + + DEFAULTPARSER = parser() @@ -1353,10 +1353,10 @@ def parse(timestr, parserinfo=None, **kwargs): first element being a :class:`datetime.datetime` object, the second a tuple containing the fuzzy tokens. - :raises ParserError: - Raised for invalid or unknown string formats, if the provided - :class:`tzinfo` is not in a valid format, or if an invalid date would - be created. + :raises ParserError: + Raised for invalid or unknown string formats, if the provided + :class:`tzinfo` is not in a valid format, or if an invalid date would + be created. :raises OverflowError: Raised if the parsed date exceeds the largest valid C integer on @@ -1585,29 +1585,29 @@ DEFAULTTZPARSER = _tzparser() def _parsetz(tzstr): return DEFAULTTZPARSER.parse(tzstr) - -class ParserError(ValueError): - """Exception subclass used for any failure to parse a datetime string. - - This is a subclass of :py:exc:`ValueError`, and should be raised any time - earlier versions of ``dateutil`` would have raised ``ValueError``. - - .. versionadded:: 2.8.1 - """ - def __str__(self): - try: - return self.args[0] % self.args[1:] - except (TypeError, IndexError): - return super(ParserError, self).__str__() - - def __repr__(self): - args = ", ".join("'%s'" % arg for arg in self.args) - return "%s(%s)" % (self.__class__.__name__, args) - - + +class ParserError(ValueError): + """Exception subclass used for any failure to parse a datetime string. + + This is a subclass of :py:exc:`ValueError`, and should be raised any time + earlier versions of ``dateutil`` would have raised ``ValueError``. + + .. versionadded:: 2.8.1 + """ + def __str__(self): + try: + return self.args[0] % self.args[1:] + except (TypeError, IndexError): + return super(ParserError, self).__str__() + + def __repr__(self): + args = ", ".join("'%s'" % arg for arg in self.args) + return "%s(%s)" % (self.__class__.__name__, args) + + class UnknownTimezoneWarning(RuntimeWarning): - """Raised when the parser finds a timezone it cannot parse into a tzinfo. - - .. versionadded:: 2.7.0 - """ + """Raised when the parser finds a timezone it cannot parse into a tzinfo. + + .. versionadded:: 2.7.0 + """ # vim:ts=4:sw=4:et diff --git a/contrib/python/dateutil/dateutil/parser/isoparser.py b/contrib/python/dateutil/dateutil/parser/isoparser.py index 5d7bee3800..3c5fd07b22 100644 --- a/contrib/python/dateutil/dateutil/parser/isoparser.py +++ b/contrib/python/dateutil/dateutil/parser/isoparser.py @@ -88,13 +88,13 @@ class isoparser(object): - ``hh`` - ``hh:mm`` or ``hhmm`` - ``hh:mm:ss`` or ``hhmmss`` - - ``hh:mm:ss.ssssss`` (Up to 6 sub-second digits) + - ``hh:mm:ss.ssssss`` (Up to 6 sub-second digits) Midnight is a special case for `hh`, as the standard supports both - 00:00 and 24:00 as a representation. The decimal separator can be - either a dot or a comma. - + 00:00 and 24:00 as a representation. The decimal separator can be + either a dot or a comma. + .. caution:: Support for fractional components other than seconds is part of the @@ -139,10 +139,10 @@ class isoparser(object): else: raise ValueError('String contains unknown ISO components') - if len(components) > 3 and components[3] == 24: - components[3] = 0 - return datetime(*components) + timedelta(days=1) - + if len(components) > 3 and components[3] == 24: + components[3] = 0 + return datetime(*components) + timedelta(days=1) + return datetime(*components) @_takes_ascii @@ -159,7 +159,7 @@ class isoparser(object): components, pos = self._parse_isodate(datestr) if pos < len(datestr): raise ValueError('String contains unknown ISO ' + - 'components: {!r}'.format(datestr.decode('ascii'))) + 'components: {!r}'.format(datestr.decode('ascii'))) return date(*components) @_takes_ascii @@ -173,10 +173,10 @@ class isoparser(object): :return: Returns a :class:`datetime.time` object """ - components = self._parse_isotime(timestr) - if components[0] == 24: - components[0] = 0 - return time(*components) + components = self._parse_isotime(timestr) + if components[0] == 24: + components[0] = 0 + return time(*components) @_takes_ascii def parse_tzstr(self, tzstr, zero_as_utc=True): @@ -201,7 +201,7 @@ class isoparser(object): # Constants _DATE_SEP = b'-' _TIME_SEP = b':' - _FRACTION_REGEX = re.compile(b'[\\.,]([0-9]+)') + _FRACTION_REGEX = re.compile(b'[\\.,]([0-9]+)') def _parse_isodate(self, dt_str): try: @@ -333,42 +333,42 @@ class isoparser(object): pos = 0 comp = -1 - if len_str < 2: + if len_str < 2: raise ValueError('ISO time too short') - has_sep = False + has_sep = False while pos < len_str and comp < 5: comp += 1 - if timestr[pos:pos + 1] in b'-+Zz': + if timestr[pos:pos + 1] in b'-+Zz': # Detect time zone boundary components[-1] = self._parse_tzstr(timestr[pos:]) pos = len_str break - if comp == 1 and timestr[pos:pos+1] == self._TIME_SEP: - has_sep = True - pos += 1 - elif comp == 2 and has_sep: - if timestr[pos:pos+1] != self._TIME_SEP: - raise ValueError('Inconsistent use of colon separator') - pos += 1 - + if comp == 1 and timestr[pos:pos+1] == self._TIME_SEP: + has_sep = True + pos += 1 + elif comp == 2 and has_sep: + if timestr[pos:pos+1] != self._TIME_SEP: + raise ValueError('Inconsistent use of colon separator') + pos += 1 + if comp < 3: # Hour, minute, second components[comp] = int(timestr[pos:pos + 2]) pos += 2 if comp == 3: - # Fraction of a second - frac = self._FRACTION_REGEX.match(timestr[pos:]) - if not frac: + # Fraction of a second + frac = self._FRACTION_REGEX.match(timestr[pos:]) + if not frac: continue - us_str = frac.group(1)[:6] # Truncate to microseconds + us_str = frac.group(1)[:6] # Truncate to microseconds components[comp] = int(us_str) * 10**(6 - len(us_str)) - pos += len(frac.group()) + pos += len(frac.group()) if pos < len_str: raise ValueError('Unused components in ISO string') @@ -381,8 +381,8 @@ class isoparser(object): return components def _parse_tzstr(self, tzstr, zero_as_utc=True): - if tzstr == b'Z' or tzstr == b'z': - return tz.UTC + if tzstr == b'Z' or tzstr == b'z': + return tz.UTC if len(tzstr) not in {3, 5, 6}: raise ValueError('Time zone offset must be 1, 3, 5 or 6 characters') @@ -401,7 +401,7 @@ class isoparser(object): minutes = int(tzstr[(4 if tzstr[3:4] == self._TIME_SEP else 3):]) if zero_as_utc and hours == 0 and minutes == 0: - return tz.UTC + return tz.UTC else: if minutes > 59: raise ValueError('Invalid minutes in time zone offset') diff --git a/contrib/python/dateutil/dateutil/relativedelta.py b/contrib/python/dateutil/dateutil/relativedelta.py index a9e85f7e6c..2791a42477 100644 --- a/contrib/python/dateutil/dateutil/relativedelta.py +++ b/contrib/python/dateutil/dateutil/relativedelta.py @@ -17,12 +17,12 @@ __all__ = ["relativedelta", "MO", "TU", "WE", "TH", "FR", "SA", "SU"] class relativedelta(object): """ - The relativedelta type is designed to be applied to an existing datetime and - can replace specific components of that datetime, or represents an interval - of time. - - It is based on the specification of the excellent work done by M.-A. Lemburg - in his + The relativedelta type is designed to be applied to an existing datetime and + can replace specific components of that datetime, or represents an interval + of time. + + It is based on the specification of the excellent work done by M.-A. Lemburg + in his `mx.DateTime <https://www.egenix.com/products/python/mxBase/mxDateTime/>`_ extension. However, notice that this type does *NOT* implement the same algorithm as his work. Do *NOT* expect it to behave like mx.DateTime's counterpart. @@ -45,19 +45,19 @@ class relativedelta(object): years, months, weeks, days, hours, minutes, seconds, microseconds: Relative information, may be negative (argument is plural); adding or subtracting a relativedelta with relative information performs - the corresponding arithmetic operation on the original datetime value + the corresponding arithmetic operation on the original datetime value with the information in the relativedelta. weekday: - One of the weekday instances (MO, TU, etc) available in the - relativedelta module. These instances may receive a parameter N, - specifying the Nth weekday, which could be positive or negative - (like MO(+1) or MO(-2)). Not specifying it is the same as specifying - +1. You can also use an integer, where 0=MO. This argument is always - relative e.g. if the calculated date is already Monday, using MO(1) - or MO(-1) won't change the day. To effectively make it absolute, use - it in combination with the day argument (e.g. day=1, MO(1) for first - Monday of the month). + One of the weekday instances (MO, TU, etc) available in the + relativedelta module. These instances may receive a parameter N, + specifying the Nth weekday, which could be positive or negative + (like MO(+1) or MO(-2)). Not specifying it is the same as specifying + +1. You can also use an integer, where 0=MO. This argument is always + relative e.g. if the calculated date is already Monday, using MO(1) + or MO(-1) won't change the day. To effectively make it absolute, use + it in combination with the day argument (e.g. day=1, MO(1) for first + Monday of the month). leapdays: Will add given days to the date found, if year is a leap @@ -88,12 +88,12 @@ class relativedelta(object): For example - >>> from datetime import datetime - >>> from dateutil.relativedelta import relativedelta, MO + >>> from datetime import datetime + >>> from dateutil.relativedelta import relativedelta, MO >>> dt = datetime(2018, 4, 9, 13, 37, 0) >>> delta = relativedelta(hours=25, day=1, weekday=MO(1)) - >>> dt + delta - datetime.datetime(2018, 4, 2, 14, 37) + >>> dt + delta + datetime.datetime(2018, 4, 2, 14, 37) First, the day is set to 1 (the first of the month), then 25 hours are added, to get to the 2nd day and 14th hour, finally the @@ -285,7 +285,7 @@ class relativedelta(object): values for the relative attributes. >>> relativedelta(days=1.5, hours=2).normalized() - relativedelta(days=+1, hours=+14) + relativedelta(days=+1, hours=+14) :return: Returns a :class:`dateutil.relativedelta.relativedelta` object. diff --git a/contrib/python/dateutil/dateutil/rrule.py b/contrib/python/dateutil/dateutil/rrule.py index b3203393c6..ca3b7d7e28 100644 --- a/contrib/python/dateutil/dateutil/rrule.py +++ b/contrib/python/dateutil/dateutil/rrule.py @@ -5,26 +5,26 @@ the recurrence rules documented in the `iCalendar RFC <https://tools.ietf.org/html/rfc5545>`_, including support for caching of results. """ -import calendar -import datetime -import heapq +import calendar +import datetime +import heapq import itertools import re import sys -from functools import wraps -# For warning about deprecation of until and count -from warnings import warn +from functools import wraps +# For warning about deprecation of until and count +from warnings import warn -from six import advance_iterator, integer_types +from six import advance_iterator, integer_types from six.moves import _thread, range from ._common import weekday as weekdaybase -try: - from math import gcd -except ImportError: - from fractions import gcd +try: + from math import gcd +except ImportError: + from fractions import gcd __all__ = ["rrule", "rruleset", "rrulestr", "YEARLY", "MONTHLY", "WEEKLY", "DAILY", @@ -82,7 +82,7 @@ def _invalidates_cache(f): Decorator for rruleset methods which may invalidate the cached length. """ - @wraps(f) + @wraps(f) def inner_func(self, *args, **kwargs): rv = f(self, *args, **kwargs) self._invalidate_cache() @@ -179,7 +179,7 @@ class rrulebase(object): return False return False - # __len__() introduces a large performance penalty. + # __len__() introduces a large performance penalty. def count(self): """ Returns the number of recurrences in this set. It will have go trough the whole recurrence, if this hasn't been done before. """ @@ -354,26 +354,26 @@ class rrule(rrulebase): from calendar.firstweekday(), and may be modified by calendar.setfirstweekday(). :param count: - If given, this determines how many occurrences will be generated. + If given, this determines how many occurrences will be generated. .. note:: - As of version 2.5.0, the use of the keyword ``until`` in conjunction - with ``count`` is deprecated, to make sure ``dateutil`` is fully - compliant with `RFC-5545 Sec. 3.3.10 <https://tools.ietf.org/ - html/rfc5545#section-3.3.10>`_. Therefore, ``until`` and ``count`` - **must not** occur in the same call to ``rrule``. + As of version 2.5.0, the use of the keyword ``until`` in conjunction + with ``count`` is deprecated, to make sure ``dateutil`` is fully + compliant with `RFC-5545 Sec. 3.3.10 <https://tools.ietf.org/ + html/rfc5545#section-3.3.10>`_. Therefore, ``until`` and ``count`` + **must not** occur in the same call to ``rrule``. :param until: - If given, this must be a datetime instance specifying the upper-bound + If given, this must be a datetime instance specifying the upper-bound limit of the recurrence. The last recurrence in the rule is the greatest datetime that is less than or equal to the value specified in the ``until`` parameter. .. note:: - As of version 2.5.0, the use of the keyword ``until`` in conjunction - with ``count`` is deprecated, to make sure ``dateutil`` is fully - compliant with `RFC-5545 Sec. 3.3.10 <https://tools.ietf.org/ - html/rfc5545#section-3.3.10>`_. Therefore, ``until`` and ``count`` - **must not** occur in the same call to ``rrule``. + As of version 2.5.0, the use of the keyword ``until`` in conjunction + with ``count`` is deprecated, to make sure ``dateutil`` is fully + compliant with `RFC-5545 Sec. 3.3.10 <https://tools.ietf.org/ + html/rfc5545#section-3.3.10>`_. Therefore, ``until`` and ``count`` + **must not** occur in the same call to ``rrule``. :param bysetpos: If given, it must be either an integer, or a sequence of integers, positive or negative. Each given integer will specify an occurrence @@ -436,7 +436,7 @@ class rrule(rrulebase): if not dtstart: if until and until.tzinfo: dtstart = datetime.datetime.now(tz=until.tzinfo).replace(microsecond=0) - else: + else: dtstart = datetime.datetime.now().replace(microsecond=0) elif not isinstance(dtstart, datetime.datetime): dtstart = datetime.datetime.fromordinal(dtstart.toordinal()) @@ -1413,53 +1413,53 @@ class rruleset(rrulebase): self._len = total - - + + class _rrulestr(object): - """ Parses a string representation of a recurrence rule or set of - recurrence rules. - - :param s: - Required, a string defining one or more recurrence rules. - - :param dtstart: - If given, used as the default recurrence start if not specified in the - rule string. - - :param cache: - If set ``True`` caching of results will be enabled, improving - performance of multiple queries considerably. - - :param unfold: - If set ``True`` indicates that a rule string is split over more - than one line and should be joined before processing. - - :param forceset: - If set ``True`` forces a :class:`dateutil.rrule.rruleset` to - be returned. - - :param compatible: - If set ``True`` forces ``unfold`` and ``forceset`` to be ``True``. - - :param ignoretz: - If set ``True``, time zones in parsed strings are ignored and a naive - :class:`datetime.datetime` object is returned. - - :param tzids: - If given, a callable or mapping used to retrieve a - :class:`datetime.tzinfo` from a string representation. - Defaults to :func:`dateutil.tz.gettz`. - - :param tzinfos: - Additional time zone names / aliases which may be present in a string - representation. See :func:`dateutil.parser.parse` for more - information. - - :return: - Returns a :class:`dateutil.rrule.rruleset` or - :class:`dateutil.rrule.rrule` - """ - + """ Parses a string representation of a recurrence rule or set of + recurrence rules. + + :param s: + Required, a string defining one or more recurrence rules. + + :param dtstart: + If given, used as the default recurrence start if not specified in the + rule string. + + :param cache: + If set ``True`` caching of results will be enabled, improving + performance of multiple queries considerably. + + :param unfold: + If set ``True`` indicates that a rule string is split over more + than one line and should be joined before processing. + + :param forceset: + If set ``True`` forces a :class:`dateutil.rrule.rruleset` to + be returned. + + :param compatible: + If set ``True`` forces ``unfold`` and ``forceset`` to be ``True``. + + :param ignoretz: + If set ``True``, time zones in parsed strings are ignored and a naive + :class:`datetime.datetime` object is returned. + + :param tzids: + If given, a callable or mapping used to retrieve a + :class:`datetime.tzinfo` from a string representation. + Defaults to :func:`dateutil.tz.gettz`. + + :param tzinfos: + Additional time zone names / aliases which may be present in a string + representation. See :func:`dateutil.parser.parse` for more + information. + + :return: + Returns a :class:`dateutil.rrule.rruleset` or + :class:`dateutil.rrule.rrule` + """ + _freq_map = {"YEARLY": YEARLY, "MONTHLY": MONTHLY, "WEEKLY": WEEKLY, @@ -1560,58 +1560,58 @@ class _rrulestr(object): raise ValueError("invalid '%s': %s" % (name, value)) return rrule(dtstart=dtstart, cache=cache, **rrkwargs) - def _parse_date_value(self, date_value, parms, rule_tzids, - ignoretz, tzids, tzinfos): - global parser - if not parser: - from dateutil import parser - - datevals = [] - value_found = False - TZID = None - - for parm in parms: - if parm.startswith("TZID="): - try: - tzkey = rule_tzids[parm.split('TZID=')[-1]] - except KeyError: - continue - if tzids is None: - from . import tz - tzlookup = tz.gettz - elif callable(tzids): - tzlookup = tzids - else: - tzlookup = getattr(tzids, 'get', None) - if tzlookup is None: - msg = ('tzids must be a callable, mapping, or None, ' - 'not %s' % tzids) - raise ValueError(msg) - - TZID = tzlookup(tzkey) - continue - - # RFC 5445 3.8.2.4: The VALUE parameter is optional, but may be found - # only once. - if parm not in {"VALUE=DATE-TIME", "VALUE=DATE"}: - raise ValueError("unsupported parm: " + parm) - else: - if value_found: - msg = ("Duplicate value parameter found in: " + parm) - raise ValueError(msg) - value_found = True - - for datestr in date_value.split(','): - date = parser.parse(datestr, ignoretz=ignoretz, tzinfos=tzinfos) - if TZID is not None: - if date.tzinfo is None: - date = date.replace(tzinfo=TZID) - else: - raise ValueError('DTSTART/EXDATE specifies multiple timezone') - datevals.append(date) - - return datevals - + def _parse_date_value(self, date_value, parms, rule_tzids, + ignoretz, tzids, tzinfos): + global parser + if not parser: + from dateutil import parser + + datevals = [] + value_found = False + TZID = None + + for parm in parms: + if parm.startswith("TZID="): + try: + tzkey = rule_tzids[parm.split('TZID=')[-1]] + except KeyError: + continue + if tzids is None: + from . import tz + tzlookup = tz.gettz + elif callable(tzids): + tzlookup = tzids + else: + tzlookup = getattr(tzids, 'get', None) + if tzlookup is None: + msg = ('tzids must be a callable, mapping, or None, ' + 'not %s' % tzids) + raise ValueError(msg) + + TZID = tzlookup(tzkey) + continue + + # RFC 5445 3.8.2.4: The VALUE parameter is optional, but may be found + # only once. + if parm not in {"VALUE=DATE-TIME", "VALUE=DATE"}: + raise ValueError("unsupported parm: " + parm) + else: + if value_found: + msg = ("Duplicate value parameter found in: " + parm) + raise ValueError(msg) + value_found = True + + for datestr in date_value.split(','): + date = parser.parse(datestr, ignoretz=ignoretz, tzinfos=tzinfos) + if TZID is not None: + if date.tzinfo is None: + date = date.replace(tzinfo=TZID) + else: + raise ValueError('DTSTART/EXDATE specifies multiple timezone') + datevals.append(date) + + return datevals + def _parse_rfc(self, s, dtstart=None, cache=False, @@ -1684,18 +1684,18 @@ class _rrulestr(object): raise ValueError("unsupported EXRULE parm: "+parm) exrulevals.append(value) elif name == "EXDATE": - exdatevals.extend( - self._parse_date_value(value, parms, - TZID_NAMES, ignoretz, - tzids, tzinfos) - ) + exdatevals.extend( + self._parse_date_value(value, parms, + TZID_NAMES, ignoretz, + tzids, tzinfos) + ) elif name == "DTSTART": - dtvals = self._parse_date_value(value, parms, TZID_NAMES, - ignoretz, tzids, tzinfos) - if len(dtvals) != 1: - raise ValueError("Multiple DTSTART values specified:" + - value) - dtstart = dtvals[0] + dtvals = self._parse_date_value(value, parms, TZID_NAMES, + ignoretz, tzids, tzinfos) + if len(dtvals) != 1: + raise ValueError("Multiple DTSTART values specified:" + + value) + dtstart = dtvals[0] else: raise ValueError("unsupported property: "+name) if (forceset or len(rrulevals) > 1 or rdatevals @@ -1717,7 +1717,7 @@ class _rrulestr(object): ignoretz=ignoretz, tzinfos=tzinfos)) for value in exdatevals: - rset.exdate(value) + rset.exdate(value) if compatible and dtstart: rset.rdate(dtstart) return rset diff --git a/contrib/python/dateutil/dateutil/test/_common.py b/contrib/python/dateutil/dateutil/test/_common.py index b8d2047374..dddd8dc9e7 100644 --- a/contrib/python/dateutil/dateutil/test/_common.py +++ b/contrib/python/dateutil/dateutil/test/_common.py @@ -6,7 +6,7 @@ import warnings import tempfile import pickle -import pytest +import pytest class PicklableMixin(object): @@ -69,12 +69,12 @@ class TZContextBase(object): Class method used to query whether or not this class allows time zone changes. """ - guard = bool(os.environ.get(cls._guard_var_name, False)) + guard = bool(os.environ.get(cls._guard_var_name, False)) # _guard_allows_change gives the "default" behavior - if True, the # guard is overcoming a block. If false, the guard is causing a block. # Whether tz_change is allowed is therefore the XNOR of the two. - return guard == cls._guard_allows_change + return guard == cls._guard_allows_change @classmethod def tz_change_disallowed_message(cls): @@ -87,12 +87,12 @@ class TZContextBase(object): def __enter__(self): if not self.tz_change_allowed(): - msg = self.tz_change_disallowed_message() - pytest.skip(msg) - - # If this is used outside of a test suite, we still want an error. - raise ValueError(msg) # pragma: no cover + msg = self.tz_change_disallowed_message() + pytest.skip(msg) + # If this is used outside of a test suite, we still want an error. + raise ValueError(msg) # pragma: no cover + self._old_tz = self.get_current_tz() self.set_current_tz(self.tzval) diff --git a/contrib/python/dateutil/dateutil/test/conftest.py b/contrib/python/dateutil/dateutil/test/conftest.py index 78ed70acb3..a7e4a27bf1 100644 --- a/contrib/python/dateutil/dateutil/test/conftest.py +++ b/contrib/python/dateutil/dateutil/test/conftest.py @@ -1,41 +1,41 @@ -import os -import pytest - - -# Configure pytest to ignore xfailing tests -# See: https://stackoverflow.com/a/53198349/467366 -def pytest_collection_modifyitems(items): - for item in items: - marker_getter = getattr(item, 'get_closest_marker', None) - - # Python 3.3 support - if marker_getter is None: - marker_getter = item.get_marker - - marker = marker_getter('xfail') - - # Need to query the args because conditional xfail tests still have - # the xfail mark even if they are not expected to fail - if marker and (not marker.args or marker.args[0]): - item.add_marker(pytest.mark.no_cover) - - -def set_tzpath(): - """ - Sets the TZPATH variable if it's specified in an environment variable. - """ - tzpath = os.environ.get('DATEUTIL_TZPATH', None) - - if tzpath is None: - return - - path_components = tzpath.split(':') - - print("Setting TZPATH to {}".format(path_components)) - - from dateutil import tz - tz.TZPATHS.clear() - tz.TZPATHS.extend(path_components) - - -set_tzpath() +import os +import pytest + + +# Configure pytest to ignore xfailing tests +# See: https://stackoverflow.com/a/53198349/467366 +def pytest_collection_modifyitems(items): + for item in items: + marker_getter = getattr(item, 'get_closest_marker', None) + + # Python 3.3 support + if marker_getter is None: + marker_getter = item.get_marker + + marker = marker_getter('xfail') + + # Need to query the args because conditional xfail tests still have + # the xfail mark even if they are not expected to fail + if marker and (not marker.args or marker.args[0]): + item.add_marker(pytest.mark.no_cover) + + +def set_tzpath(): + """ + Sets the TZPATH variable if it's specified in an environment variable. + """ + tzpath = os.environ.get('DATEUTIL_TZPATH', None) + + if tzpath is None: + return + + path_components = tzpath.split(':') + + print("Setting TZPATH to {}".format(path_components)) + + from dateutil import tz + tz.TZPATHS.clear() + tz.TZPATHS.extend(path_components) + + +set_tzpath() diff --git a/contrib/python/dateutil/dateutil/test/property/test_isoparse_prop.py b/contrib/python/dateutil/dateutil/test/property/test_isoparse_prop.py index f8e288f3d6..ec81ba5d22 100644 --- a/contrib/python/dateutil/dateutil/test/property/test_isoparse_prop.py +++ b/contrib/python/dateutil/dateutil/test/property/test_isoparse_prop.py @@ -7,7 +7,7 @@ from dateutil.parser import isoparse import pytest # Strategies -TIME_ZONE_STRATEGY = st.sampled_from([None, tz.UTC] + +TIME_ZONE_STRATEGY = st.sampled_from([None, tz.UTC] + [tz.gettz(zname) for zname in ('US/Eastern', 'US/Pacific', 'Australia/Sydney', 'Europe/London')]) ASCII_STRATEGY = st.characters(max_codepoint=127) diff --git a/contrib/python/dateutil/dateutil/test/property/test_tz_prop.py b/contrib/python/dateutil/dateutil/test/property/test_tz_prop.py index ec6d271dcf..2966c99fa0 100644 --- a/contrib/python/dateutil/dateutil/test/property/test_tz_prop.py +++ b/contrib/python/dateutil/dateutil/test/property/test_tz_prop.py @@ -1,35 +1,35 @@ -from datetime import datetime, timedelta - -import pytest -import six -from hypothesis import assume, given -from hypothesis import strategies as st - -from dateutil import tz as tz - -EPOCHALYPSE = datetime.fromtimestamp(2147483647) -NEGATIVE_EPOCHALYPSE = datetime.fromtimestamp(0) - timedelta(seconds=2147483648) - - -@pytest.mark.gettz -@pytest.mark.parametrize("gettz_arg", [None, ""]) -# TODO: Remove bounds when GH #590 is resolved -@given( - dt=st.datetimes( - min_value=NEGATIVE_EPOCHALYPSE, max_value=EPOCHALYPSE, timezones=st.just(tz.UTC), - ) -) -def test_gettz_returns_local(gettz_arg, dt): - act_tz = tz.gettz(gettz_arg) - if isinstance(act_tz, tz.tzlocal): - return - - dt_act = dt.astimezone(tz.gettz(gettz_arg)) - if six.PY2: - dt_exp = dt.astimezone(tz.tzlocal()) - else: - dt_exp = dt.astimezone() - - assert dt_act == dt_exp - assert dt_act.tzname() == dt_exp.tzname() - assert dt_act.utcoffset() == dt_exp.utcoffset() +from datetime import datetime, timedelta + +import pytest +import six +from hypothesis import assume, given +from hypothesis import strategies as st + +from dateutil import tz as tz + +EPOCHALYPSE = datetime.fromtimestamp(2147483647) +NEGATIVE_EPOCHALYPSE = datetime.fromtimestamp(0) - timedelta(seconds=2147483648) + + +@pytest.mark.gettz +@pytest.mark.parametrize("gettz_arg", [None, ""]) +# TODO: Remove bounds when GH #590 is resolved +@given( + dt=st.datetimes( + min_value=NEGATIVE_EPOCHALYPSE, max_value=EPOCHALYPSE, timezones=st.just(tz.UTC), + ) +) +def test_gettz_returns_local(gettz_arg, dt): + act_tz = tz.gettz(gettz_arg) + if isinstance(act_tz, tz.tzlocal): + return + + dt_act = dt.astimezone(tz.gettz(gettz_arg)) + if six.PY2: + dt_exp = dt.astimezone(tz.tzlocal()) + else: + dt_exp = dt.astimezone() + + assert dt_act == dt_exp + assert dt_act.tzname() == dt_exp.tzname() + assert dt_act.utcoffset() == dt_exp.utcoffset() diff --git a/contrib/python/dateutil/dateutil/test/test_easter.py b/contrib/python/dateutil/dateutil/test/test_easter.py index cf2ec7f287..688d802c0f 100644 --- a/contrib/python/dateutil/dateutil/test/test_easter.py +++ b/contrib/python/dateutil/dateutil/test/test_easter.py @@ -2,7 +2,7 @@ from dateutil.easter import easter from dateutil.easter import EASTER_WESTERN, EASTER_ORTHODOX, EASTER_JULIAN from datetime import date -import pytest +import pytest # List of easters between 1990 and 2050 western_easter_dates = [ @@ -73,21 +73,21 @@ julian_easter_dates = [ ] -@pytest.mark.parametrize("easter_date", western_easter_dates) -def test_easter_western(easter_date): - assert easter_date == easter(easter_date.year, EASTER_WESTERN) +@pytest.mark.parametrize("easter_date", western_easter_dates) +def test_easter_western(easter_date): + assert easter_date == easter(easter_date.year, EASTER_WESTERN) -@pytest.mark.parametrize("easter_date", orthodox_easter_dates) -def test_easter_orthodox(easter_date): - assert easter_date == easter(easter_date.year, EASTER_ORTHODOX) +@pytest.mark.parametrize("easter_date", orthodox_easter_dates) +def test_easter_orthodox(easter_date): + assert easter_date == easter(easter_date.year, EASTER_ORTHODOX) - -@pytest.mark.parametrize("easter_date", julian_easter_dates) -def test_easter_julian(easter_date): - assert easter_date == easter(easter_date.year, EASTER_JULIAN) - - -def test_easter_bad_method(): - with pytest.raises(ValueError): - easter(1975, 4) + +@pytest.mark.parametrize("easter_date", julian_easter_dates) +def test_easter_julian(easter_date): + assert easter_date == easter(easter_date.year, EASTER_JULIAN) + + +def test_easter_bad_method(): + with pytest.raises(ValueError): + easter(1975, 4) diff --git a/contrib/python/dateutil/dateutil/test/test_import_star.py b/contrib/python/dateutil/dateutil/test/test_import_star.py index 2fb7098128..247fe911ce 100644 --- a/contrib/python/dateutil/dateutil/test/test_import_star.py +++ b/contrib/python/dateutil/dateutil/test/test_import_star.py @@ -1,8 +1,8 @@ """Test for the "import *" functionality. -As import * can be only done at module level, it has been added in a separate file +As import * can be only done at module level, it has been added in a separate file """ -import pytest +import pytest prev_locals = list(locals()) from dateutil import * @@ -11,23 +11,23 @@ new_locals = {name:value for name,value in locals().items() new_locals.pop('prev_locals') -@pytest.mark.import_star -def test_imported_modules(): - """ Test that `from dateutil import *` adds modules in __all__ locally """ - import dateutil.easter - import dateutil.parser - import dateutil.relativedelta - import dateutil.rrule - import dateutil.tz - import dateutil.utils - import dateutil.zoneinfo +@pytest.mark.import_star +def test_imported_modules(): + """ Test that `from dateutil import *` adds modules in __all__ locally """ + import dateutil.easter + import dateutil.parser + import dateutil.relativedelta + import dateutil.rrule + import dateutil.tz + import dateutil.utils + import dateutil.zoneinfo - assert dateutil.easter == new_locals.pop("easter") - assert dateutil.parser == new_locals.pop("parser") - assert dateutil.relativedelta == new_locals.pop("relativedelta") - assert dateutil.rrule == new_locals.pop("rrule") - assert dateutil.tz == new_locals.pop("tz") - assert dateutil.utils == new_locals.pop("utils") - assert dateutil.zoneinfo == new_locals.pop("zoneinfo") + assert dateutil.easter == new_locals.pop("easter") + assert dateutil.parser == new_locals.pop("parser") + assert dateutil.relativedelta == new_locals.pop("relativedelta") + assert dateutil.rrule == new_locals.pop("rrule") + assert dateutil.tz == new_locals.pop("tz") + assert dateutil.utils == new_locals.pop("utils") + assert dateutil.zoneinfo == new_locals.pop("zoneinfo") - assert not new_locals + assert not new_locals diff --git a/contrib/python/dateutil/dateutil/test/test_imports.py b/contrib/python/dateutil/dateutil/test/test_imports.py index 60b86005ca..351ee41e86 100644 --- a/contrib/python/dateutil/dateutil/test/test_imports.py +++ b/contrib/python/dateutil/dateutil/test/test_imports.py @@ -1,176 +1,176 @@ import sys -import pytest +import pytest - -HOST_IS_WINDOWS = sys.platform.startswith('win') - - -def test_import_version_str(): + +HOST_IS_WINDOWS = sys.platform.startswith('win') + + +def test_import_version_str(): """ Test that dateutil.__version__ can be imported""" - from dateutil import __version__ - - -def test_import_version_root(): - import dateutil - assert hasattr(dateutil, '__version__') - - -# Test that dateutil.easter-related imports work properly -def test_import_easter_direct(): - import dateutil.easter - - -def test_import_easter_from(): - from dateutil import easter - - -def test_import_easter_start(): - from dateutil.easter import easter - - -# Test that dateutil.parser-related imports work properly -def test_import_parser_direct(): - import dateutil.parser - - -def test_import_parser_from(): - from dateutil import parser - - -def test_import_parser_all(): - # All interface - from dateutil.parser import parse - from dateutil.parser import parserinfo - - # Other public classes - from dateutil.parser import parser - - for var in (parse, parserinfo, parser): - assert var is not None + from dateutil import __version__ -# Test that dateutil.relativedelta-related imports work properly -def test_import_relative_delta_direct(): - import dateutil.relativedelta +def test_import_version_root(): + import dateutil + assert hasattr(dateutil, '__version__') -def test_import_relative_delta_from(): - from dateutil import relativedelta +# Test that dateutil.easter-related imports work properly +def test_import_easter_direct(): + import dateutil.easter -def test_import_relative_delta_all(): - from dateutil.relativedelta import relativedelta - from dateutil.relativedelta import MO, TU, WE, TH, FR, SA, SU - for var in (relativedelta, MO, TU, WE, TH, FR, SA, SU): - assert var is not None +def test_import_easter_from(): + from dateutil import easter - # In the public interface but not in all - from dateutil.relativedelta import weekday - assert weekday is not None +def test_import_easter_start(): + from dateutil.easter import easter -# Test that dateutil.rrule related imports work properly -def test_import_rrule_direct(): - import dateutil.rrule +# Test that dateutil.parser-related imports work properly +def test_import_parser_direct(): + import dateutil.parser -def test_import_rrule_from(): - from dateutil import rrule +def test_import_parser_from(): + from dateutil import parser -def test_import_rrule_all(): - from dateutil.rrule import rrule - from dateutil.rrule import rruleset - from dateutil.rrule import rrulestr - from dateutil.rrule import YEARLY, MONTHLY, WEEKLY, DAILY - from dateutil.rrule import HOURLY, MINUTELY, SECONDLY - from dateutil.rrule import MO, TU, WE, TH, FR, SA, SU - rr_all = (rrule, rruleset, rrulestr, - YEARLY, MONTHLY, WEEKLY, DAILY, - HOURLY, MINUTELY, SECONDLY, - MO, TU, WE, TH, FR, SA, SU) +def test_import_parser_all(): + # All interface + from dateutil.parser import parse + from dateutil.parser import parserinfo - for var in rr_all: - assert var is not None + # Other public classes + from dateutil.parser import parser - # In the public interface but not in all - from dateutil.rrule import weekday - assert weekday is not None + for var in (parse, parserinfo, parser): + assert var is not None -# Test that dateutil.tz related imports work properly -def test_import_tztest_direct(): - import dateutil.tz +# Test that dateutil.relativedelta-related imports work properly +def test_import_relative_delta_direct(): + import dateutil.relativedelta -def test_import_tz_from(): - from dateutil import tz +def test_import_relative_delta_from(): + from dateutil import relativedelta +def test_import_relative_delta_all(): + from dateutil.relativedelta import relativedelta + from dateutil.relativedelta import MO, TU, WE, TH, FR, SA, SU -def test_import_tz_all(): - from dateutil.tz import tzutc - from dateutil.tz import tzoffset - from dateutil.tz import tzlocal - from dateutil.tz import tzfile - from dateutil.tz import tzrange - from dateutil.tz import tzstr - from dateutil.tz import tzical - from dateutil.tz import gettz - from dateutil.tz import tzwin - from dateutil.tz import tzwinlocal - from dateutil.tz import UTC - from dateutil.tz import datetime_ambiguous - from dateutil.tz import datetime_exists - from dateutil.tz import resolve_imaginary + for var in (relativedelta, MO, TU, WE, TH, FR, SA, SU): + assert var is not None - tz_all = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange", - "tzstr", "tzical", "gettz", "datetime_ambiguous", - "datetime_exists", "resolve_imaginary", "UTC"] + # In the public interface but not in all + from dateutil.relativedelta import weekday + assert weekday is not None - tz_all += ["tzwin", "tzwinlocal"] if sys.platform.startswith("win") else [] - lvars = locals() - for var in tz_all: - assert lvars[var] is not None +# Test that dateutil.rrule related imports work properly +def test_import_rrule_direct(): + import dateutil.rrule -# Test that dateutil.tzwin related imports work properly -@pytest.mark.skipif(not HOST_IS_WINDOWS, reason="Requires Windows") -def test_import_tz_windows_direct(): - import dateutil.tzwin +def test_import_rrule_from(): + from dateutil import rrule -@pytest.mark.skipif(not HOST_IS_WINDOWS, reason="Requires Windows") -def test_import_tz_windows_from(): - from dateutil import tzwin +def test_import_rrule_all(): + from dateutil.rrule import rrule + from dateutil.rrule import rruleset + from dateutil.rrule import rrulestr + from dateutil.rrule import YEARLY, MONTHLY, WEEKLY, DAILY + from dateutil.rrule import HOURLY, MINUTELY, SECONDLY + from dateutil.rrule import MO, TU, WE, TH, FR, SA, SU -@pytest.mark.skipif(not HOST_IS_WINDOWS, reason="Requires Windows") -def test_import_tz_windows_star(): - from dateutil.tzwin import tzwin - from dateutil.tzwin import tzwinlocal + rr_all = (rrule, rruleset, rrulestr, + YEARLY, MONTHLY, WEEKLY, DAILY, + HOURLY, MINUTELY, SECONDLY, + MO, TU, WE, TH, FR, SA, SU) - tzwin_all = [tzwin, tzwinlocal] + for var in rr_all: + assert var is not None - for var in tzwin_all: - assert var is not None + # In the public interface but not in all + from dateutil.rrule import weekday + assert weekday is not None -# Test imports of Zone Info -def test_import_zone_info_direct(): - import dateutil.zoneinfo +# Test that dateutil.tz related imports work properly +def test_import_tztest_direct(): + import dateutil.tz -def test_import_zone_info_from(): - from dateutil import zoneinfo +def test_import_tz_from(): + from dateutil import tz -def test_import_zone_info_star(): - from dateutil.zoneinfo import gettz - from dateutil.zoneinfo import gettz_db_metadata - from dateutil.zoneinfo import rebuild +def test_import_tz_all(): + from dateutil.tz import tzutc + from dateutil.tz import tzoffset + from dateutil.tz import tzlocal + from dateutil.tz import tzfile + from dateutil.tz import tzrange + from dateutil.tz import tzstr + from dateutil.tz import tzical + from dateutil.tz import gettz + from dateutil.tz import tzwin + from dateutil.tz import tzwinlocal + from dateutil.tz import UTC + from dateutil.tz import datetime_ambiguous + from dateutil.tz import datetime_exists + from dateutil.tz import resolve_imaginary - zi_all = (gettz, gettz_db_metadata, rebuild) + tz_all = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange", + "tzstr", "tzical", "gettz", "datetime_ambiguous", + "datetime_exists", "resolve_imaginary", "UTC"] - for var in zi_all: - assert var is not None + tz_all += ["tzwin", "tzwinlocal"] if sys.platform.startswith("win") else [] + lvars = locals() + + for var in tz_all: + assert lvars[var] is not None + +# Test that dateutil.tzwin related imports work properly +@pytest.mark.skipif(not HOST_IS_WINDOWS, reason="Requires Windows") +def test_import_tz_windows_direct(): + import dateutil.tzwin + + +@pytest.mark.skipif(not HOST_IS_WINDOWS, reason="Requires Windows") +def test_import_tz_windows_from(): + from dateutil import tzwin + + +@pytest.mark.skipif(not HOST_IS_WINDOWS, reason="Requires Windows") +def test_import_tz_windows_star(): + from dateutil.tzwin import tzwin + from dateutil.tzwin import tzwinlocal + + tzwin_all = [tzwin, tzwinlocal] + + for var in tzwin_all: + assert var is not None + + +# Test imports of Zone Info +def test_import_zone_info_direct(): + import dateutil.zoneinfo + + +def test_import_zone_info_from(): + from dateutil import zoneinfo + + +def test_import_zone_info_star(): + from dateutil.zoneinfo import gettz + from dateutil.zoneinfo import gettz_db_metadata + from dateutil.zoneinfo import rebuild + + zi_all = (gettz, gettz_db_metadata, rebuild) + + for var in zi_all: + assert var is not None diff --git a/contrib/python/dateutil/dateutil/test/test_internals.py b/contrib/python/dateutil/dateutil/test/test_internals.py index 530813147d..f1d0bdee89 100644 --- a/contrib/python/dateutil/dateutil/test/test_internals.py +++ b/contrib/python/dateutil/dateutil/test/test_internals.py @@ -16,31 +16,31 @@ from dateutil import tz IS_PY32 = sys.version_info[0:2] == (3, 2) -@pytest.mark.smoke -def test_YMD_could_be_day(): - ymd = _ymd('foo bar 124 baz') - - ymd.append(2, 'M') - assert ymd.has_month - assert not ymd.has_year - assert ymd.could_be_day(4) - assert not ymd.could_be_day(-6) - assert not ymd.could_be_day(32) - - # Assumes leap year - assert ymd.could_be_day(29) - - ymd.append(1999) - assert ymd.has_year - assert not ymd.could_be_day(29) - - ymd.append(16, 'D') - assert ymd.has_day - assert not ymd.could_be_day(1) - - ymd = _ymd('foo bar 124 baz') - ymd.append(1999) - assert ymd.could_be_day(31) +@pytest.mark.smoke +def test_YMD_could_be_day(): + ymd = _ymd('foo bar 124 baz') + + ymd.append(2, 'M') + assert ymd.has_month + assert not ymd.has_year + assert ymd.could_be_day(4) + assert not ymd.could_be_day(-6) + assert not ymd.could_be_day(32) + + # Assumes leap year + assert ymd.could_be_day(29) + + ymd.append(1999) + assert ymd.has_year + assert not ymd.could_be_day(29) + + ymd.append(16, 'D') + assert ymd.has_day + assert not ymd.could_be_day(1) + + ymd = _ymd('foo bar 124 baz') + ymd.append(1999) + assert ymd.could_be_day(31) ### diff --git a/contrib/python/dateutil/dateutil/test/test_isoparser.py b/contrib/python/dateutil/dateutil/test/test_isoparser.py index 35899ab9b1..3705d124b1 100644 --- a/contrib/python/dateutil/dateutil/test/test_isoparser.py +++ b/contrib/python/dateutil/dateutil/test/test_isoparser.py @@ -4,8 +4,8 @@ from __future__ import unicode_literals from datetime import datetime, timedelta, date, time import itertools as it -from dateutil import tz -from dateutil.tz import UTC +from dateutil import tz +from dateutil.tz import UTC from dateutil.parser import isoparser, isoparse import pytest @@ -36,7 +36,7 @@ def _generate_tzoffsets(limited): out += [_mkoffset(hm, fmt) for hm in hm_out for fmt in fmts] # Also add in UTC and naive - out.append((UTC, 'Z')) + out.append((UTC, 'Z')) out.append((None, '')) return out @@ -77,13 +77,13 @@ def _isoparse_date_and_time(dt, date_fmt, time_fmt, tzoffset, dtstr = dt.strftime(fmt) if microsecond_precision is not None: - if not fmt.endswith('%f'): # pragma: nocover + if not fmt.endswith('%f'): # pragma: nocover raise ValueError('Time format has no microseconds!') - if microsecond_precision != 6: + if microsecond_precision != 6: dtstr = dtstr[:-(6 - microsecond_precision)] - elif microsecond_precision > 6: # pragma: nocover - raise ValueError('Precision must be 1-6') + elif microsecond_precision > 6: # pragma: nocover + raise ValueError('Precision must be 1-6') dtstr += offset_str @@ -120,8 +120,8 @@ def test_ymd_hms(dt, date_fmt, time_fmt, tzoffset): DATETIMES = [datetime(2017, 11, 27, 6, 14, 30, 123456)] @pytest.mark.parametrize('dt', tuple(DATETIMES)) @pytest.mark.parametrize('date_fmt', YMD_FMTS) -@pytest.mark.parametrize('time_fmt', (x + sep + '%f' for x in HMS_FMTS - for sep in '.,')) +@pytest.mark.parametrize('time_fmt', (x + sep + '%f' for x in HMS_FMTS + for sep in '.,')) @pytest.mark.parametrize('tzoffset', TZOFFSETS) @pytest.mark.parametrize('precision', list(range(3, 7))) def test_ymd_hms_micro(dt, date_fmt, time_fmt, tzoffset, precision): @@ -130,15 +130,15 @@ def test_ymd_hms_micro(dt, date_fmt, time_fmt, tzoffset, precision): _isoparse_date_and_time(dt, date_fmt, time_fmt, tzoffset, precision) -### -# Truncation of extra digits beyond microsecond precision -@pytest.mark.parametrize('dt_str', [ - '2018-07-03T14:07:00.123456000001', - '2018-07-03T14:07:00.123456999999', -]) -def test_extra_subsecond_digits(dt_str): - assert isoparse(dt_str) == datetime(2018, 7, 3, 14, 7, 0, 123456) - +### +# Truncation of extra digits beyond microsecond precision +@pytest.mark.parametrize('dt_str', [ + '2018-07-03T14:07:00.123456000001', + '2018-07-03T14:07:00.123456999999', +]) +def test_extra_subsecond_digits(dt_str): + assert isoparse(dt_str) == datetime(2018, 7, 3, 14, 7, 0, 123456) + @pytest.mark.parametrize('tzoffset', FULL_TZOFFSETS) def test_full_tzoffsets(tzoffset): dt = datetime(2017, 11, 27, 6, 14, 30, 123456) @@ -149,15 +149,15 @@ def test_full_tzoffsets(tzoffset): @pytest.mark.parametrize('dt_str', [ '2014-04-11T00', - '2014-04-10T24', + '2014-04-10T24', '2014-04-11T00:00', - '2014-04-10T24:00', + '2014-04-10T24:00', '2014-04-11T00:00:00', - '2014-04-10T24:00:00', + '2014-04-10T24:00:00', '2014-04-11T00:00:00.000', - '2014-04-10T24:00:00.000', + '2014-04-10T24:00:00.000', '2014-04-11T00:00:00.000000', - '2014-04-10T24:00:00.000000'] + '2014-04-10T24:00:00.000000'] ) def test_datetime_midnight(dt_str): assert isoparse(dt_str) == datetime(2014, 4, 11, 0, 0, 0, 0) @@ -227,9 +227,9 @@ def test_iso_ordinal(isoord, dt_expected): (b'2014-02-04T12:30:15.224', datetime(2014, 2, 4, 12, 30, 15, 224000)), (b'20140204T123015.224', datetime(2014, 2, 4, 12, 30, 15, 224000)), (b'2014-02-04T12:30:15.224Z', datetime(2014, 2, 4, 12, 30, 15, 224000, - UTC)), - (b'2014-02-04T12:30:15.224z', datetime(2014, 2, 4, 12, 30, 15, 224000, - UTC)), + UTC)), + (b'2014-02-04T12:30:15.224z', datetime(2014, 2, 4, 12, 30, 15, 224000, + UTC)), (b'2014-02-04T12:30:15.224+05:00', datetime(2014, 2, 4, 12, 30, 15, 224000, tzinfo=tz.tzoffset(None, timedelta(hours=5))))]) @@ -244,8 +244,8 @@ def test_bytes(isostr, dt): ('2012-0425', ValueError), # Inconsistent date separators ('201204-25', ValueError), # Inconsistent date separators ('20120425T0120:00', ValueError), # Inconsistent time separators - ('20120425T01:2000', ValueError), # Inconsistent time separators - ('14:3015', ValueError), # Inconsistent time separator + ('20120425T01:2000', ValueError), # Inconsistent time separators + ('14:3015', ValueError), # Inconsistent time separator ('20120425T012500-334', ValueError), # Wrong microsecond separator ('2001-1', ValueError), # YYYY-M not valid ('2012-04-9', ValueError), # YYYY-MM-D not valid @@ -277,15 +277,15 @@ def test_iso_raises(isostr, exception): isoparse(isostr) -@pytest.mark.parametrize('sep_act, valid_sep, exception', [ - ('T', 'C', ValueError), - ('C', 'T', ValueError), +@pytest.mark.parametrize('sep_act, valid_sep, exception', [ + ('T', 'C', ValueError), + ('C', 'T', ValueError), ]) -def test_iso_with_sep_raises(sep_act, valid_sep, exception): - parser = isoparser(sep=valid_sep) +def test_iso_with_sep_raises(sep_act, valid_sep, exception): + parser = isoparser(sep=valid_sep) isostr = '2012-04-25' + sep_act + '01:25:00' - with pytest.raises(exception): - parser.isoparse(isostr) + with pytest.raises(exception): + parser.isoparse(isostr) ### @@ -297,7 +297,7 @@ def test_isoparser_invalid_sep(sep): # This only fails on Python 3 -@pytest.mark.xfail(not six.PY2, reason="Fails on Python 3 only") +@pytest.mark.xfail(not six.PY2, reason="Fails on Python 3 only") def test_isoparser_byte_sep(): dt = datetime(2017, 12, 6, 12, 30, 45) dt_str = dt.isoformat(sep=str('T')) @@ -324,7 +324,7 @@ def test_parse_tzstr(tzoffset): @pytest.mark.parametrize('zero_as_utc', [True, False]) def test_parse_tzstr_zero_as_utc(tzstr, zero_as_utc): tzi = isoparser().parse_tzstr(tzstr, zero_as_utc=zero_as_utc) - assert tzi == UTC + assert tzi == UTC assert (type(tzi) == tz.tzutc) == zero_as_utc @@ -347,7 +347,7 @@ def __make_date_examples(): date(2016, 2, 1) ] - if not six.PY2: + if not six.PY2: # strftime does not support dates before 1900 in Python 2 dates_no_day.append(date(1000, 11, 1)) @@ -373,7 +373,7 @@ def test_parse_isodate(d, dt_fmt, as_bytes): d_str = d.strftime(dt_fmt) if isinstance(d_str, six.text_type) and as_bytes: d_str = d_str.encode('ascii') - elif isinstance(d_str, bytes) and not as_bytes: + elif isinstance(d_str, bytes) and not as_bytes: d_str = d_str.decode('ascii') iparser = isoparser() @@ -388,25 +388,25 @@ def test_parse_isodate(d, dt_fmt, as_bytes): ('2013-02-29', ValueError), # Not a leap year ('2014/12/03', ValueError), # Wrong separators ('2014-04-19T', ValueError), # Unknown components - ('201202', ValueError), # Invalid format + ('201202', ValueError), # Invalid format ]) def test_isodate_raises(isostr, exception): with pytest.raises(exception): isoparser().parse_isodate(isostr) -def test_parse_isodate_error_text(): - with pytest.raises(ValueError) as excinfo: - isoparser().parse_isodate('2014-0423') - - # ensure the error message does not contain b' prefixes - if six.PY2: - expected_error = "String contains unknown ISO components: u'2014-0423'" - else: - expected_error = "String contains unknown ISO components: '2014-0423'" - assert expected_error == str(excinfo.value) - - +def test_parse_isodate_error_text(): + with pytest.raises(ValueError) as excinfo: + isoparser().parse_isodate('2014-0423') + + # ensure the error message does not contain b' prefixes + if six.PY2: + expected_error = "String contains unknown ISO components: u'2014-0423'" + else: + expected_error = "String contains unknown ISO components: '2014-0423'" + assert expected_error == str(excinfo.value) + + ### # Test parse_isotime def __make_time_examples(): @@ -458,31 +458,31 @@ def __make_time_examples(): @pytest.mark.parametrize('as_bytes', [True, False]) def test_isotime(time_val, time_fmt, as_bytes): tstr = time_val.strftime(time_fmt) - if isinstance(tstr, six.text_type) and as_bytes: + if isinstance(tstr, six.text_type) and as_bytes: tstr = tstr.encode('ascii') - elif isinstance(tstr, bytes) and not as_bytes: + elif isinstance(tstr, bytes) and not as_bytes: tstr = tstr.decode('ascii') iparser = isoparser() assert iparser.parse_isotime(tstr) == time_val - -@pytest.mark.parametrize('isostr', [ - '24:00', - '2400', - '24:00:00', - '240000', - '24:00:00.000', - '24:00:00,000', - '24:00:00.000000', - '24:00:00,000000', -]) -def test_isotime_midnight(isostr): - iparser = isoparser() - assert iparser.parse_isotime(isostr) == time(0, 0, 0, 0) - - + +@pytest.mark.parametrize('isostr', [ + '24:00', + '2400', + '24:00:00', + '240000', + '24:00:00.000', + '24:00:00,000', + '24:00:00.000000', + '24:00:00,000000', +]) +def test_isotime_midnight(isostr): + iparser = isoparser() + assert iparser.parse_isotime(isostr) == time(0, 0, 0, 0) + + @pytest.mark.parametrize('isostr,exception', [ ('3', ValueError), # ISO string too short ('14時30分15秒', ValueError), # Not ASCII @@ -492,16 +492,16 @@ def test_isotime_midnight(isostr): ('25:15', ValueError), # Invalid hours ('14:60', ValueError), # Invalid minutes ('14:59:61', ValueError), # Invalid seconds - ('14:30:15.34468305:00', ValueError), # No sign in time zone + ('14:30:15.34468305:00', ValueError), # No sign in time zone ('14:30:15+', ValueError), # Time zone too short ('14:30:15+1234567', ValueError), # Time zone invalid ('14:59:59+25:00', ValueError), # Invalid tz hours ('14:59:59+12:62', ValueError), # Invalid tz minutes ('14:59:30_344583', ValueError), # Invalid microsecond separator - ('24:01', ValueError), # 24 used for non-midnight time - ('24:00:01', ValueError), # 24 used for non-midnight time - ('24:00:00.001', ValueError), # 24 used for non-midnight time - ('24:00:00.000001', ValueError), # 24 used for non-midnight time + ('24:01', ValueError), # 24 used for non-midnight time + ('24:00:01', ValueError), # 24 used for non-midnight time + ('24:00:00.001', ValueError), # 24 used for non-midnight time + ('24:00:00.000001', ValueError), # 24 used for non-midnight time ]) def test_isotime_raises(isostr, exception): iparser = isoparser() diff --git a/contrib/python/dateutil/dateutil/test/test_parser.py b/contrib/python/dateutil/dateutil/test/test_parser.py index 08a34dafbc..3241a39553 100644 --- a/contrib/python/dateutil/dateutil/test/test_parser.py +++ b/contrib/python/dateutil/dateutil/test/test_parser.py @@ -9,222 +9,222 @@ import sys from dateutil import tz from dateutil.tz import tzoffset from dateutil.parser import parse, parserinfo -from dateutil.parser import ParserError +from dateutil.parser import ParserError from dateutil.parser import UnknownTimezoneWarning from ._common import TZEnvContext -from six import assertRaisesRegex, PY2 -from io import StringIO +from six import assertRaisesRegex, PY2 +from io import StringIO import pytest # Platform info IS_WIN = sys.platform.startswith('win') -PLATFORM_HAS_DASH_D = False +PLATFORM_HAS_DASH_D = False try: - if datetime.now().strftime('%-d'): - PLATFORM_HAS_DASH_D = True + if datetime.now().strftime('%-d'): + PLATFORM_HAS_DASH_D = True except ValueError: - pass - - -@pytest.fixture(params=[True, False]) -def fuzzy(request): - """Fixture to pass fuzzy=True or fuzzy=False to parse""" - return request.param - - -# Parser test cases using no keyword arguments. Format: (parsable_text, expected_datetime, assertion_message) -PARSER_TEST_CASES = [ - ("Thu Sep 25 10:36:28 2003", datetime(2003, 9, 25, 10, 36, 28), "date command format strip"), - ("Thu Sep 25 2003", datetime(2003, 9, 25), "date command format strip"), - ("2003-09-25T10:49:41", datetime(2003, 9, 25, 10, 49, 41), "iso format strip"), - ("2003-09-25T10:49", datetime(2003, 9, 25, 10, 49), "iso format strip"), - ("2003-09-25T10", datetime(2003, 9, 25, 10), "iso format strip"), - ("2003-09-25", datetime(2003, 9, 25), "iso format strip"), - ("20030925T104941", datetime(2003, 9, 25, 10, 49, 41), "iso stripped format strip"), - ("20030925T1049", datetime(2003, 9, 25, 10, 49, 0), "iso stripped format strip"), - ("20030925T10", datetime(2003, 9, 25, 10), "iso stripped format strip"), - ("20030925", datetime(2003, 9, 25), "iso stripped format strip"), - ("2003-09-25 10:49:41,502", datetime(2003, 9, 25, 10, 49, 41, 502000), "python logger format"), - ("199709020908", datetime(1997, 9, 2, 9, 8), "no separator"), - ("19970902090807", datetime(1997, 9, 2, 9, 8, 7), "no separator"), - ("09-25-2003", datetime(2003, 9, 25), "date with dash"), - ("25-09-2003", datetime(2003, 9, 25), "date with dash"), - ("10-09-2003", datetime(2003, 10, 9), "date with dash"), - ("10-09-03", datetime(2003, 10, 9), "date with dash"), - ("2003.09.25", datetime(2003, 9, 25), "date with dot"), - ("09.25.2003", datetime(2003, 9, 25), "date with dot"), - ("25.09.2003", datetime(2003, 9, 25), "date with dot"), - ("10.09.2003", datetime(2003, 10, 9), "date with dot"), - ("10.09.03", datetime(2003, 10, 9), "date with dot"), - ("2003/09/25", datetime(2003, 9, 25), "date with slash"), - ("09/25/2003", datetime(2003, 9, 25), "date with slash"), - ("25/09/2003", datetime(2003, 9, 25), "date with slash"), - ("10/09/2003", datetime(2003, 10, 9), "date with slash"), - ("10/09/03", datetime(2003, 10, 9), "date with slash"), - ("2003 09 25", datetime(2003, 9, 25), "date with space"), - ("09 25 2003", datetime(2003, 9, 25), "date with space"), - ("25 09 2003", datetime(2003, 9, 25), "date with space"), - ("10 09 2003", datetime(2003, 10, 9), "date with space"), - ("10 09 03", datetime(2003, 10, 9), "date with space"), - ("25 09 03", datetime(2003, 9, 25), "date with space"), - ("03 25 Sep", datetime(2003, 9, 25), "strangely ordered date"), - ("25 03 Sep", datetime(2025, 9, 3), "strangely ordered date"), - (" July 4 , 1976 12:01:02 am ", datetime(1976, 7, 4, 0, 1, 2), "extra space"), - ("Wed, July 10, '96", datetime(1996, 7, 10, 0, 0), "random format"), - ("1996.July.10 AD 12:08 PM", datetime(1996, 7, 10, 12, 8), "random format"), - ("July 4, 1976", datetime(1976, 7, 4), "random format"), - ("7 4 1976", datetime(1976, 7, 4), "random format"), - ("4 jul 1976", datetime(1976, 7, 4), "random format"), - ("4 Jul 1976", datetime(1976, 7, 4), "'%-d %b %Y' format"), - ("7-4-76", datetime(1976, 7, 4), "random format"), - ("19760704", datetime(1976, 7, 4), "random format"), - ("0:01:02 on July 4, 1976", datetime(1976, 7, 4, 0, 1, 2), "random format"), - ("July 4, 1976 12:01:02 am", datetime(1976, 7, 4, 0, 1, 2), "random format"), - ("Mon Jan 2 04:24:27 1995", datetime(1995, 1, 2, 4, 24, 27), "random format"), - ("04.04.95 00:22", datetime(1995, 4, 4, 0, 22), "random format"), - ("Jan 1 1999 11:23:34.578", datetime(1999, 1, 1, 11, 23, 34, 578000), "random format"), - ("950404 122212", datetime(1995, 4, 4, 12, 22, 12), "random format"), - ("3rd of May 2001", datetime(2001, 5, 3), "random format"), - ("5th of March 2001", datetime(2001, 3, 5), "random format"), - ("1st of May 2003", datetime(2003, 5, 1), "random format"), - ('0099-01-01T00:00:00', datetime(99, 1, 1, 0, 0), "99 ad"), - ('0031-01-01T00:00:00', datetime(31, 1, 1, 0, 0), "31 ad"), - ("20080227T21:26:01.123456789", datetime(2008, 2, 27, 21, 26, 1, 123456), "high precision seconds"), - ('13NOV2017', datetime(2017, 11, 13), "dBY (See GH360)"), - ('0003-03-04', datetime(3, 3, 4), "pre 12 year same month (See GH PR #293)"), - ('December.0031.30', datetime(31, 12, 30), "BYd corner case (GH#687)"), - - # Cases with legacy h/m/s format, candidates for deprecation (GH#886) - ("2016-12-21 04.2h", datetime(2016, 12, 21, 4, 12), "Fractional Hours"), -] -# Check that we don't have any duplicates -assert len(set([x[0] for x in PARSER_TEST_CASES])) == len(PARSER_TEST_CASES) - - -@pytest.mark.parametrize("parsable_text,expected_datetime,assertion_message", PARSER_TEST_CASES) -def test_parser(parsable_text, expected_datetime, assertion_message): - assert parse(parsable_text) == expected_datetime, assertion_message - - -# Parser test cases using datetime(2003, 9, 25) as a default. -# Format: (parsable_text, expected_datetime, assertion_message) -PARSER_DEFAULT_TEST_CASES = [ - ("Thu Sep 25 10:36:28", datetime(2003, 9, 25, 10, 36, 28), "date command format strip"), - ("Thu Sep 10:36:28", datetime(2003, 9, 25, 10, 36, 28), "date command format strip"), - ("Thu 10:36:28", datetime(2003, 9, 25, 10, 36, 28), "date command format strip"), - ("Sep 10:36:28", datetime(2003, 9, 25, 10, 36, 28), "date command format strip"), - ("10:36:28", datetime(2003, 9, 25, 10, 36, 28), "date command format strip"), - ("10:36", datetime(2003, 9, 25, 10, 36), "date command format strip"), - ("Sep 2003", datetime(2003, 9, 25), "date command format strip"), - ("Sep", datetime(2003, 9, 25), "date command format strip"), - ("2003", datetime(2003, 9, 25), "date command format strip"), - ("10h36m28.5s", datetime(2003, 9, 25, 10, 36, 28, 500000), "hour with letters"), - ("10h36m28s", datetime(2003, 9, 25, 10, 36, 28), "hour with letters strip"), - ("10h36m", datetime(2003, 9, 25, 10, 36), "hour with letters strip"), - ("10h", datetime(2003, 9, 25, 10), "hour with letters strip"), - ("10 h 36", datetime(2003, 9, 25, 10, 36), "hour with letters strip"), - ("10 h 36.5", datetime(2003, 9, 25, 10, 36, 30), "hour with letter strip"), - ("36 m 5", datetime(2003, 9, 25, 0, 36, 5), "hour with letters spaces"), - ("36 m 5 s", datetime(2003, 9, 25, 0, 36, 5), "minute with letters spaces"), - ("36 m 05", datetime(2003, 9, 25, 0, 36, 5), "minute with letters spaces"), - ("36 m 05 s", datetime(2003, 9, 25, 0, 36, 5), "minutes with letters spaces"), - ("10h am", datetime(2003, 9, 25, 10), "hour am pm"), - ("10h pm", datetime(2003, 9, 25, 22), "hour am pm"), - ("10am", datetime(2003, 9, 25, 10), "hour am pm"), - ("10pm", datetime(2003, 9, 25, 22), "hour am pm"), - ("10:00 am", datetime(2003, 9, 25, 10), "hour am pm"), - ("10:00 pm", datetime(2003, 9, 25, 22), "hour am pm"), - ("10:00am", datetime(2003, 9, 25, 10), "hour am pm"), - ("10:00pm", datetime(2003, 9, 25, 22), "hour am pm"), - ("10:00a.m", datetime(2003, 9, 25, 10), "hour am pm"), - ("10:00p.m", datetime(2003, 9, 25, 22), "hour am pm"), - ("10:00a.m.", datetime(2003, 9, 25, 10), "hour am pm"), - ("10:00p.m.", datetime(2003, 9, 25, 22), "hour am pm"), - ("Wed", datetime(2003, 10, 1), "weekday alone"), - ("Wednesday", datetime(2003, 10, 1), "long weekday"), - ("October", datetime(2003, 10, 25), "long month"), - ("31-Dec-00", datetime(2000, 12, 31), "zero year"), - ("0:01:02", datetime(2003, 9, 25, 0, 1, 2), "random format"), - ("12h 01m02s am", datetime(2003, 9, 25, 0, 1, 2), "random format"), - ("12:08 PM", datetime(2003, 9, 25, 12, 8), "random format"), - ("01h02m03", datetime(2003, 9, 25, 1, 2, 3), "random format"), - ("01h02", datetime(2003, 9, 25, 1, 2), "random format"), - ("01h02s", datetime(2003, 9, 25, 1, 0, 2), "random format"), - ("01m02", datetime(2003, 9, 25, 0, 1, 2), "random format"), - ("01m02h", datetime(2003, 9, 25, 2, 1), "random format"), - ("2004 10 Apr 11h30m", datetime(2004, 4, 10, 11, 30), "random format") -] -# Check that we don't have any duplicates -assert len(set([x[0] for x in PARSER_DEFAULT_TEST_CASES])) == len(PARSER_DEFAULT_TEST_CASES) - - -@pytest.mark.parametrize("parsable_text,expected_datetime,assertion_message", PARSER_DEFAULT_TEST_CASES) -def test_parser_default(parsable_text, expected_datetime, assertion_message): - assert parse(parsable_text, default=datetime(2003, 9, 25)) == expected_datetime, assertion_message - - -@pytest.mark.parametrize('sep', ['-', '.', '/', ' ']) -def test_parse_dayfirst(sep): - expected = datetime(2003, 9, 10) - fmt = sep.join(['%d', '%m', '%Y']) - dstr = expected.strftime(fmt) - result = parse(dstr, dayfirst=True) - assert result == expected - - -@pytest.mark.parametrize('sep', ['-', '.', '/', ' ']) -def test_parse_yearfirst(sep): - expected = datetime(2010, 9, 3) - fmt = sep.join(['%Y', '%m', '%d']) - dstr = expected.strftime(fmt) - result = parse(dstr, yearfirst=True) - assert result == expected - - -@pytest.mark.parametrize('dstr,expected', [ - ("Thu Sep 25 10:36:28 BRST 2003", datetime(2003, 9, 25, 10, 36, 28)), - ("1996.07.10 AD at 15:08:56 PDT", datetime(1996, 7, 10, 15, 8, 56)), - ("Tuesday, April 12, 1952 AD 3:30:42pm PST", - datetime(1952, 4, 12, 15, 30, 42)), - ("November 5, 1994, 8:15:30 am EST", datetime(1994, 11, 5, 8, 15, 30)), - ("1994-11-05T08:15:30-05:00", datetime(1994, 11, 5, 8, 15, 30)), - ("1994-11-05T08:15:30Z", datetime(1994, 11, 5, 8, 15, 30)), - ("1976-07-04T00:01:02Z", datetime(1976, 7, 4, 0, 1, 2)), - ("1986-07-05T08:15:30z", datetime(1986, 7, 5, 8, 15, 30)), - ("Tue Apr 4 00:22:12 PDT 1995", datetime(1995, 4, 4, 0, 22, 12)), -]) -def test_parse_ignoretz(dstr, expected): - result = parse(dstr, ignoretz=True) - assert result == expected - - -_brsttz = tzoffset("BRST", -10800) - - -@pytest.mark.parametrize('dstr,expected', [ - ("20030925T104941-0300", - datetime(2003, 9, 25, 10, 49, 41, tzinfo=_brsttz)), - ("Thu, 25 Sep 2003 10:49:41 -0300", - datetime(2003, 9, 25, 10, 49, 41, tzinfo=_brsttz)), - ("2003-09-25T10:49:41.5-03:00", - datetime(2003, 9, 25, 10, 49, 41, 500000, tzinfo=_brsttz)), - ("2003-09-25T10:49:41-03:00", - datetime(2003, 9, 25, 10, 49, 41, tzinfo=_brsttz)), - ("20030925T104941.5-0300", - datetime(2003, 9, 25, 10, 49, 41, 500000, tzinfo=_brsttz)), -]) -def test_parse_with_tzoffset(dstr, expected): - # In these cases, we are _not_ passing a tzinfos arg - result = parse(dstr) - assert result == expected - - -class TestFormat(object): - + pass + + +@pytest.fixture(params=[True, False]) +def fuzzy(request): + """Fixture to pass fuzzy=True or fuzzy=False to parse""" + return request.param + + +# Parser test cases using no keyword arguments. Format: (parsable_text, expected_datetime, assertion_message) +PARSER_TEST_CASES = [ + ("Thu Sep 25 10:36:28 2003", datetime(2003, 9, 25, 10, 36, 28), "date command format strip"), + ("Thu Sep 25 2003", datetime(2003, 9, 25), "date command format strip"), + ("2003-09-25T10:49:41", datetime(2003, 9, 25, 10, 49, 41), "iso format strip"), + ("2003-09-25T10:49", datetime(2003, 9, 25, 10, 49), "iso format strip"), + ("2003-09-25T10", datetime(2003, 9, 25, 10), "iso format strip"), + ("2003-09-25", datetime(2003, 9, 25), "iso format strip"), + ("20030925T104941", datetime(2003, 9, 25, 10, 49, 41), "iso stripped format strip"), + ("20030925T1049", datetime(2003, 9, 25, 10, 49, 0), "iso stripped format strip"), + ("20030925T10", datetime(2003, 9, 25, 10), "iso stripped format strip"), + ("20030925", datetime(2003, 9, 25), "iso stripped format strip"), + ("2003-09-25 10:49:41,502", datetime(2003, 9, 25, 10, 49, 41, 502000), "python logger format"), + ("199709020908", datetime(1997, 9, 2, 9, 8), "no separator"), + ("19970902090807", datetime(1997, 9, 2, 9, 8, 7), "no separator"), + ("09-25-2003", datetime(2003, 9, 25), "date with dash"), + ("25-09-2003", datetime(2003, 9, 25), "date with dash"), + ("10-09-2003", datetime(2003, 10, 9), "date with dash"), + ("10-09-03", datetime(2003, 10, 9), "date with dash"), + ("2003.09.25", datetime(2003, 9, 25), "date with dot"), + ("09.25.2003", datetime(2003, 9, 25), "date with dot"), + ("25.09.2003", datetime(2003, 9, 25), "date with dot"), + ("10.09.2003", datetime(2003, 10, 9), "date with dot"), + ("10.09.03", datetime(2003, 10, 9), "date with dot"), + ("2003/09/25", datetime(2003, 9, 25), "date with slash"), + ("09/25/2003", datetime(2003, 9, 25), "date with slash"), + ("25/09/2003", datetime(2003, 9, 25), "date with slash"), + ("10/09/2003", datetime(2003, 10, 9), "date with slash"), + ("10/09/03", datetime(2003, 10, 9), "date with slash"), + ("2003 09 25", datetime(2003, 9, 25), "date with space"), + ("09 25 2003", datetime(2003, 9, 25), "date with space"), + ("25 09 2003", datetime(2003, 9, 25), "date with space"), + ("10 09 2003", datetime(2003, 10, 9), "date with space"), + ("10 09 03", datetime(2003, 10, 9), "date with space"), + ("25 09 03", datetime(2003, 9, 25), "date with space"), + ("03 25 Sep", datetime(2003, 9, 25), "strangely ordered date"), + ("25 03 Sep", datetime(2025, 9, 3), "strangely ordered date"), + (" July 4 , 1976 12:01:02 am ", datetime(1976, 7, 4, 0, 1, 2), "extra space"), + ("Wed, July 10, '96", datetime(1996, 7, 10, 0, 0), "random format"), + ("1996.July.10 AD 12:08 PM", datetime(1996, 7, 10, 12, 8), "random format"), + ("July 4, 1976", datetime(1976, 7, 4), "random format"), + ("7 4 1976", datetime(1976, 7, 4), "random format"), + ("4 jul 1976", datetime(1976, 7, 4), "random format"), + ("4 Jul 1976", datetime(1976, 7, 4), "'%-d %b %Y' format"), + ("7-4-76", datetime(1976, 7, 4), "random format"), + ("19760704", datetime(1976, 7, 4), "random format"), + ("0:01:02 on July 4, 1976", datetime(1976, 7, 4, 0, 1, 2), "random format"), + ("July 4, 1976 12:01:02 am", datetime(1976, 7, 4, 0, 1, 2), "random format"), + ("Mon Jan 2 04:24:27 1995", datetime(1995, 1, 2, 4, 24, 27), "random format"), + ("04.04.95 00:22", datetime(1995, 4, 4, 0, 22), "random format"), + ("Jan 1 1999 11:23:34.578", datetime(1999, 1, 1, 11, 23, 34, 578000), "random format"), + ("950404 122212", datetime(1995, 4, 4, 12, 22, 12), "random format"), + ("3rd of May 2001", datetime(2001, 5, 3), "random format"), + ("5th of March 2001", datetime(2001, 3, 5), "random format"), + ("1st of May 2003", datetime(2003, 5, 1), "random format"), + ('0099-01-01T00:00:00', datetime(99, 1, 1, 0, 0), "99 ad"), + ('0031-01-01T00:00:00', datetime(31, 1, 1, 0, 0), "31 ad"), + ("20080227T21:26:01.123456789", datetime(2008, 2, 27, 21, 26, 1, 123456), "high precision seconds"), + ('13NOV2017', datetime(2017, 11, 13), "dBY (See GH360)"), + ('0003-03-04', datetime(3, 3, 4), "pre 12 year same month (See GH PR #293)"), + ('December.0031.30', datetime(31, 12, 30), "BYd corner case (GH#687)"), + + # Cases with legacy h/m/s format, candidates for deprecation (GH#886) + ("2016-12-21 04.2h", datetime(2016, 12, 21, 4, 12), "Fractional Hours"), +] +# Check that we don't have any duplicates +assert len(set([x[0] for x in PARSER_TEST_CASES])) == len(PARSER_TEST_CASES) + + +@pytest.mark.parametrize("parsable_text,expected_datetime,assertion_message", PARSER_TEST_CASES) +def test_parser(parsable_text, expected_datetime, assertion_message): + assert parse(parsable_text) == expected_datetime, assertion_message + + +# Parser test cases using datetime(2003, 9, 25) as a default. +# Format: (parsable_text, expected_datetime, assertion_message) +PARSER_DEFAULT_TEST_CASES = [ + ("Thu Sep 25 10:36:28", datetime(2003, 9, 25, 10, 36, 28), "date command format strip"), + ("Thu Sep 10:36:28", datetime(2003, 9, 25, 10, 36, 28), "date command format strip"), + ("Thu 10:36:28", datetime(2003, 9, 25, 10, 36, 28), "date command format strip"), + ("Sep 10:36:28", datetime(2003, 9, 25, 10, 36, 28), "date command format strip"), + ("10:36:28", datetime(2003, 9, 25, 10, 36, 28), "date command format strip"), + ("10:36", datetime(2003, 9, 25, 10, 36), "date command format strip"), + ("Sep 2003", datetime(2003, 9, 25), "date command format strip"), + ("Sep", datetime(2003, 9, 25), "date command format strip"), + ("2003", datetime(2003, 9, 25), "date command format strip"), + ("10h36m28.5s", datetime(2003, 9, 25, 10, 36, 28, 500000), "hour with letters"), + ("10h36m28s", datetime(2003, 9, 25, 10, 36, 28), "hour with letters strip"), + ("10h36m", datetime(2003, 9, 25, 10, 36), "hour with letters strip"), + ("10h", datetime(2003, 9, 25, 10), "hour with letters strip"), + ("10 h 36", datetime(2003, 9, 25, 10, 36), "hour with letters strip"), + ("10 h 36.5", datetime(2003, 9, 25, 10, 36, 30), "hour with letter strip"), + ("36 m 5", datetime(2003, 9, 25, 0, 36, 5), "hour with letters spaces"), + ("36 m 5 s", datetime(2003, 9, 25, 0, 36, 5), "minute with letters spaces"), + ("36 m 05", datetime(2003, 9, 25, 0, 36, 5), "minute with letters spaces"), + ("36 m 05 s", datetime(2003, 9, 25, 0, 36, 5), "minutes with letters spaces"), + ("10h am", datetime(2003, 9, 25, 10), "hour am pm"), + ("10h pm", datetime(2003, 9, 25, 22), "hour am pm"), + ("10am", datetime(2003, 9, 25, 10), "hour am pm"), + ("10pm", datetime(2003, 9, 25, 22), "hour am pm"), + ("10:00 am", datetime(2003, 9, 25, 10), "hour am pm"), + ("10:00 pm", datetime(2003, 9, 25, 22), "hour am pm"), + ("10:00am", datetime(2003, 9, 25, 10), "hour am pm"), + ("10:00pm", datetime(2003, 9, 25, 22), "hour am pm"), + ("10:00a.m", datetime(2003, 9, 25, 10), "hour am pm"), + ("10:00p.m", datetime(2003, 9, 25, 22), "hour am pm"), + ("10:00a.m.", datetime(2003, 9, 25, 10), "hour am pm"), + ("10:00p.m.", datetime(2003, 9, 25, 22), "hour am pm"), + ("Wed", datetime(2003, 10, 1), "weekday alone"), + ("Wednesday", datetime(2003, 10, 1), "long weekday"), + ("October", datetime(2003, 10, 25), "long month"), + ("31-Dec-00", datetime(2000, 12, 31), "zero year"), + ("0:01:02", datetime(2003, 9, 25, 0, 1, 2), "random format"), + ("12h 01m02s am", datetime(2003, 9, 25, 0, 1, 2), "random format"), + ("12:08 PM", datetime(2003, 9, 25, 12, 8), "random format"), + ("01h02m03", datetime(2003, 9, 25, 1, 2, 3), "random format"), + ("01h02", datetime(2003, 9, 25, 1, 2), "random format"), + ("01h02s", datetime(2003, 9, 25, 1, 0, 2), "random format"), + ("01m02", datetime(2003, 9, 25, 0, 1, 2), "random format"), + ("01m02h", datetime(2003, 9, 25, 2, 1), "random format"), + ("2004 10 Apr 11h30m", datetime(2004, 4, 10, 11, 30), "random format") +] +# Check that we don't have any duplicates +assert len(set([x[0] for x in PARSER_DEFAULT_TEST_CASES])) == len(PARSER_DEFAULT_TEST_CASES) + + +@pytest.mark.parametrize("parsable_text,expected_datetime,assertion_message", PARSER_DEFAULT_TEST_CASES) +def test_parser_default(parsable_text, expected_datetime, assertion_message): + assert parse(parsable_text, default=datetime(2003, 9, 25)) == expected_datetime, assertion_message + + +@pytest.mark.parametrize('sep', ['-', '.', '/', ' ']) +def test_parse_dayfirst(sep): + expected = datetime(2003, 9, 10) + fmt = sep.join(['%d', '%m', '%Y']) + dstr = expected.strftime(fmt) + result = parse(dstr, dayfirst=True) + assert result == expected + + +@pytest.mark.parametrize('sep', ['-', '.', '/', ' ']) +def test_parse_yearfirst(sep): + expected = datetime(2010, 9, 3) + fmt = sep.join(['%Y', '%m', '%d']) + dstr = expected.strftime(fmt) + result = parse(dstr, yearfirst=True) + assert result == expected + + +@pytest.mark.parametrize('dstr,expected', [ + ("Thu Sep 25 10:36:28 BRST 2003", datetime(2003, 9, 25, 10, 36, 28)), + ("1996.07.10 AD at 15:08:56 PDT", datetime(1996, 7, 10, 15, 8, 56)), + ("Tuesday, April 12, 1952 AD 3:30:42pm PST", + datetime(1952, 4, 12, 15, 30, 42)), + ("November 5, 1994, 8:15:30 am EST", datetime(1994, 11, 5, 8, 15, 30)), + ("1994-11-05T08:15:30-05:00", datetime(1994, 11, 5, 8, 15, 30)), + ("1994-11-05T08:15:30Z", datetime(1994, 11, 5, 8, 15, 30)), + ("1976-07-04T00:01:02Z", datetime(1976, 7, 4, 0, 1, 2)), + ("1986-07-05T08:15:30z", datetime(1986, 7, 5, 8, 15, 30)), + ("Tue Apr 4 00:22:12 PDT 1995", datetime(1995, 4, 4, 0, 22, 12)), +]) +def test_parse_ignoretz(dstr, expected): + result = parse(dstr, ignoretz=True) + assert result == expected + + +_brsttz = tzoffset("BRST", -10800) + + +@pytest.mark.parametrize('dstr,expected', [ + ("20030925T104941-0300", + datetime(2003, 9, 25, 10, 49, 41, tzinfo=_brsttz)), + ("Thu, 25 Sep 2003 10:49:41 -0300", + datetime(2003, 9, 25, 10, 49, 41, tzinfo=_brsttz)), + ("2003-09-25T10:49:41.5-03:00", + datetime(2003, 9, 25, 10, 49, 41, 500000, tzinfo=_brsttz)), + ("2003-09-25T10:49:41-03:00", + datetime(2003, 9, 25, 10, 49, 41, tzinfo=_brsttz)), + ("20030925T104941.5-0300", + datetime(2003, 9, 25, 10, 49, 41, 500000, tzinfo=_brsttz)), +]) +def test_parse_with_tzoffset(dstr, expected): + # In these cases, we are _not_ passing a tzinfos arg + result = parse(dstr) + assert result == expected + + +class TestFormat(object): + def test_ybd(self): # If we have a 4-digit year, a non-numeric month (abbreviated or not), # and a day (1 or 2 digits), then there is no ambiguity as to which @@ -248,63 +248,63 @@ class TestFormat(object): for fmt in unambig_fmts: dstr = actual.strftime(fmt) res = parse(dstr) - assert res == actual - - # TODO: some redundancy with PARSER_TEST_CASES cases - @pytest.mark.parametrize("fmt,dstr", [ - ("%a %b %d %Y", "Thu Sep 25 2003"), - ("%b %d %Y", "Sep 25 2003"), - ("%Y-%m-%d", "2003-09-25"), - ("%Y%m%d", "20030925"), - ("%Y-%b-%d", "2003-Sep-25"), - ("%d-%b-%Y", "25-Sep-2003"), - ("%b-%d-%Y", "Sep-25-2003"), - ("%m-%d-%Y", "09-25-2003"), - ("%d-%m-%Y", "25-09-2003"), - ("%Y.%m.%d", "2003.09.25"), - ("%Y.%b.%d", "2003.Sep.25"), - ("%d.%b.%Y", "25.Sep.2003"), - ("%b.%d.%Y", "Sep.25.2003"), - ("%m.%d.%Y", "09.25.2003"), - ("%d.%m.%Y", "25.09.2003"), - ("%Y/%m/%d", "2003/09/25"), - ("%Y/%b/%d", "2003/Sep/25"), - ("%d/%b/%Y", "25/Sep/2003"), - ("%b/%d/%Y", "Sep/25/2003"), - ("%m/%d/%Y", "09/25/2003"), - ("%d/%m/%Y", "25/09/2003"), - ("%Y %m %d", "2003 09 25"), - ("%Y %b %d", "2003 Sep 25"), - ("%d %b %Y", "25 Sep 2003"), - ("%m %d %Y", "09 25 2003"), - ("%d %m %Y", "25 09 2003"), - ("%y %d %b", "03 25 Sep",), - ]) - def test_strftime_formats_2003Sep25(self, fmt, dstr): - expected = datetime(2003, 9, 25) - - # First check that the format strings behave as expected - # (not strictly necessary, but nice to have) - assert expected.strftime(fmt) == dstr - - res = parse(dstr) - assert res == expected - - -class TestInputTypes(object): - def test_empty_string_invalid(self): - with pytest.raises(ParserError): + assert res == actual + + # TODO: some redundancy with PARSER_TEST_CASES cases + @pytest.mark.parametrize("fmt,dstr", [ + ("%a %b %d %Y", "Thu Sep 25 2003"), + ("%b %d %Y", "Sep 25 2003"), + ("%Y-%m-%d", "2003-09-25"), + ("%Y%m%d", "20030925"), + ("%Y-%b-%d", "2003-Sep-25"), + ("%d-%b-%Y", "25-Sep-2003"), + ("%b-%d-%Y", "Sep-25-2003"), + ("%m-%d-%Y", "09-25-2003"), + ("%d-%m-%Y", "25-09-2003"), + ("%Y.%m.%d", "2003.09.25"), + ("%Y.%b.%d", "2003.Sep.25"), + ("%d.%b.%Y", "25.Sep.2003"), + ("%b.%d.%Y", "Sep.25.2003"), + ("%m.%d.%Y", "09.25.2003"), + ("%d.%m.%Y", "25.09.2003"), + ("%Y/%m/%d", "2003/09/25"), + ("%Y/%b/%d", "2003/Sep/25"), + ("%d/%b/%Y", "25/Sep/2003"), + ("%b/%d/%Y", "Sep/25/2003"), + ("%m/%d/%Y", "09/25/2003"), + ("%d/%m/%Y", "25/09/2003"), + ("%Y %m %d", "2003 09 25"), + ("%Y %b %d", "2003 Sep 25"), + ("%d %b %Y", "25 Sep 2003"), + ("%m %d %Y", "09 25 2003"), + ("%d %m %Y", "25 09 2003"), + ("%y %d %b", "03 25 Sep",), + ]) + def test_strftime_formats_2003Sep25(self, fmt, dstr): + expected = datetime(2003, 9, 25) + + # First check that the format strings behave as expected + # (not strictly necessary, but nice to have) + assert expected.strftime(fmt) == dstr + + res = parse(dstr) + assert res == expected + + +class TestInputTypes(object): + def test_empty_string_invalid(self): + with pytest.raises(ParserError): parse('') - def test_none_invalid(self): - with pytest.raises(TypeError): + def test_none_invalid(self): + with pytest.raises(TypeError): parse(None) - def test_int_invalid(self): - with pytest.raises(TypeError): + def test_int_invalid(self): + with pytest.raises(TypeError): parse(13) - def test_duck_typing(self): + def test_duck_typing(self): # We want to support arbitrary classes that implement the stream # interface. @@ -317,110 +317,110 @@ class TestInputTypes(object): dstr = StringPassThrough(StringIO('2014 January 19')) - res = parse(dstr) - expected = datetime(2014, 1, 19) - assert res == expected + res = parse(dstr) + expected = datetime(2014, 1, 19) + assert res == expected - def test_parse_stream(self): + def test_parse_stream(self): dstr = StringIO('2014 January 19') - res = parse(dstr) - expected = datetime(2014, 1, 19) - assert res == expected - - def test_parse_str(self): - # Parser should be able to handle bytestring and unicode - uni_str = '2014-05-01 08:00:00' - bytes_str = uni_str.encode() - - res = parse(bytes_str) - expected = parse(uni_str) - assert res == expected - - def test_parse_bytes(self): - res = parse(b'2014 January 19') - expected = datetime(2014, 1, 19) - assert res == expected - - def test_parse_bytearray(self): - # GH#417 - res = parse(bytearray(b'2014 January 19')) - expected = datetime(2014, 1, 19) - assert res == expected - - -class TestTzinfoInputTypes(object): - def assert_equal_same_tz(self, dt1, dt2): - assert dt1 == dt2 - assert dt1.tzinfo is dt2.tzinfo - - def test_tzinfo_dict_could_return_none(self): - dstr = "2017-02-03 12:40 BRST" - result = parse(dstr, tzinfos={"BRST": None}) - expected = datetime(2017, 2, 3, 12, 40) - self.assert_equal_same_tz(result, expected) - - def test_tzinfos_callable_could_return_none(self): - dstr = "2017-02-03 12:40 BRST" - result = parse(dstr, tzinfos=lambda *args: None) - expected = datetime(2017, 2, 3, 12, 40) - self.assert_equal_same_tz(result, expected) - - def test_invalid_tzinfo_input(self): - dstr = "2014 January 19 09:00 UTC" - # Pass an absurd tzinfos object - tzinfos = {"UTC": ValueError} - with pytest.raises(TypeError): - parse(dstr, tzinfos=tzinfos) - - def test_valid_tzinfo_tzinfo_input(self): - dstr = "2014 January 19 09:00 UTC" - tzinfos = {"UTC": tz.UTC} - expected = datetime(2014, 1, 19, 9, tzinfo=tz.UTC) - res = parse(dstr, tzinfos=tzinfos) - self.assert_equal_same_tz(res, expected) - - def test_valid_tzinfo_unicode_input(self): - dstr = "2014 January 19 09:00 UTC" - tzinfos = {u"UTC": u"UTC+0"} - expected = datetime(2014, 1, 19, 9, tzinfo=tz.tzstr("UTC+0")) - res = parse(dstr, tzinfos=tzinfos) - self.assert_equal_same_tz(res, expected) - - def test_valid_tzinfo_callable_input(self): - dstr = "2014 January 19 09:00 UTC" - - def tzinfos(*args, **kwargs): - return u"UTC+0" - - expected = datetime(2014, 1, 19, 9, tzinfo=tz.tzstr("UTC+0")) - res = parse(dstr, tzinfos=tzinfos) - self.assert_equal_same_tz(res, expected) - - def test_valid_tzinfo_int_input(self): - dstr = "2014 January 19 09:00 UTC" - tzinfos = {u"UTC": -28800} - expected = datetime(2014, 1, 19, 9, tzinfo=tz.tzoffset(u"UTC", -28800)) - res = parse(dstr, tzinfos=tzinfos) - self.assert_equal_same_tz(res, expected) - - -class ParserTest(unittest.TestCase): - - @classmethod - def setup_class(cls): - cls.tzinfos = {"BRST": -10800} - cls.brsttz = tzoffset("BRST", -10800) - cls.default = datetime(2003, 9, 25) - - # Parser should be able to handle bytestring and unicode - cls.uni_str = '2014-05-01 08:00:00' - cls.str_str = cls.uni_str.encode() - + res = parse(dstr) + expected = datetime(2014, 1, 19) + assert res == expected + + def test_parse_str(self): + # Parser should be able to handle bytestring and unicode + uni_str = '2014-05-01 08:00:00' + bytes_str = uni_str.encode() + + res = parse(bytes_str) + expected = parse(uni_str) + assert res == expected + + def test_parse_bytes(self): + res = parse(b'2014 January 19') + expected = datetime(2014, 1, 19) + assert res == expected + + def test_parse_bytearray(self): + # GH#417 + res = parse(bytearray(b'2014 January 19')) + expected = datetime(2014, 1, 19) + assert res == expected + + +class TestTzinfoInputTypes(object): + def assert_equal_same_tz(self, dt1, dt2): + assert dt1 == dt2 + assert dt1.tzinfo is dt2.tzinfo + + def test_tzinfo_dict_could_return_none(self): + dstr = "2017-02-03 12:40 BRST" + result = parse(dstr, tzinfos={"BRST": None}) + expected = datetime(2017, 2, 3, 12, 40) + self.assert_equal_same_tz(result, expected) + + def test_tzinfos_callable_could_return_none(self): + dstr = "2017-02-03 12:40 BRST" + result = parse(dstr, tzinfos=lambda *args: None) + expected = datetime(2017, 2, 3, 12, 40) + self.assert_equal_same_tz(result, expected) + + def test_invalid_tzinfo_input(self): + dstr = "2014 January 19 09:00 UTC" + # Pass an absurd tzinfos object + tzinfos = {"UTC": ValueError} + with pytest.raises(TypeError): + parse(dstr, tzinfos=tzinfos) + + def test_valid_tzinfo_tzinfo_input(self): + dstr = "2014 January 19 09:00 UTC" + tzinfos = {"UTC": tz.UTC} + expected = datetime(2014, 1, 19, 9, tzinfo=tz.UTC) + res = parse(dstr, tzinfos=tzinfos) + self.assert_equal_same_tz(res, expected) + + def test_valid_tzinfo_unicode_input(self): + dstr = "2014 January 19 09:00 UTC" + tzinfos = {u"UTC": u"UTC+0"} + expected = datetime(2014, 1, 19, 9, tzinfo=tz.tzstr("UTC+0")) + res = parse(dstr, tzinfos=tzinfos) + self.assert_equal_same_tz(res, expected) + + def test_valid_tzinfo_callable_input(self): + dstr = "2014 January 19 09:00 UTC" + + def tzinfos(*args, **kwargs): + return u"UTC+0" + + expected = datetime(2014, 1, 19, 9, tzinfo=tz.tzstr("UTC+0")) + res = parse(dstr, tzinfos=tzinfos) + self.assert_equal_same_tz(res, expected) + + def test_valid_tzinfo_int_input(self): + dstr = "2014 January 19 09:00 UTC" + tzinfos = {u"UTC": -28800} + expected = datetime(2014, 1, 19, 9, tzinfo=tz.tzoffset(u"UTC", -28800)) + res = parse(dstr, tzinfos=tzinfos) + self.assert_equal_same_tz(res, expected) + + +class ParserTest(unittest.TestCase): + + @classmethod + def setup_class(cls): + cls.tzinfos = {"BRST": -10800} + cls.brsttz = tzoffset("BRST", -10800) + cls.default = datetime(2003, 9, 25) + + # Parser should be able to handle bytestring and unicode + cls.uni_str = '2014-05-01 08:00:00' + cls.str_str = cls.uni_str.encode() + def testParserParseStr(self): from dateutil.parser import parser - assert parser().parse(self.str_str) == parser().parse(self.uni_str) + assert parser().parse(self.str_str) == parser().parse(self.uni_str) def testParseUnicodeWords(self): @@ -438,9 +438,9 @@ class ParserTest(unittest.TestCase): ("ноя", "Ноябрь"), ("дек", "Декабрь")] - expected = datetime(2015, 9, 10, 10, 20) - res = parse('10 Сентябрь 2015 10:20', parserinfo=rus_parserinfo()) - assert res == expected + expected = datetime(2015, 9, 10, 10, 20) + res = parse('10 Сентябрь 2015 10:20', parserinfo=rus_parserinfo()) + assert res == expected def testParseWithNulls(self): # This relies on the from __future__ import unicode_literals, because @@ -448,7 +448,7 @@ class ParserTest(unittest.TestCase): # May want to switch to u'...' if we ever drop Python 3.2 support. pstring = '\x00\x00August 29, 1924' - assert parse(pstring) == datetime(1924, 8, 29) + assert parse(pstring) == datetime(1924, 8, 29) def testDateCommandFormat(self): self.assertEqual(parse("Thu Sep 25 10:36:28 BRST 2003", @@ -463,34 +463,34 @@ class ParserTest(unittest.TestCase): tzinfo=self.brsttz)) def testDateCommandFormatWithLong(self): - if PY2: + if PY2: self.assertEqual(parse("Thu Sep 25 10:36:28 BRST 2003", tzinfos={"BRST": long(-10800)}), datetime(2003, 9, 25, 10, 36, 28, tzinfo=self.brsttz)) - + def testISOFormatStrip2(self): - self.assertEqual(parse("2003-09-25T10:49:41+03:00"), - datetime(2003, 9, 25, 10, 49, 41, - tzinfo=tzoffset(None, 10800))) + self.assertEqual(parse("2003-09-25T10:49:41+03:00"), + datetime(2003, 9, 25, 10, 49, 41, + tzinfo=tzoffset(None, 10800))) def testISOStrippedFormatStrip2(self): - self.assertEqual(parse("20030925T104941+0300"), - datetime(2003, 9, 25, 10, 49, 41, - tzinfo=tzoffset(None, 10800))) + self.assertEqual(parse("20030925T104941+0300"), + datetime(2003, 9, 25, 10, 49, 41, + tzinfo=tzoffset(None, 10800))) def testAMPMNoHour(self): - with pytest.raises(ParserError): + with pytest.raises(ParserError): parse("AM") - with pytest.raises(ParserError): + with pytest.raises(ParserError): parse("Jan 20, 2015 PM") def testAMPMRange(self): - with pytest.raises(ParserError): + with pytest.raises(ParserError): parse("13:44 AM") - with pytest.raises(ParserError): + with pytest.raises(ParserError): parse("January 25, 1921 23:13 PM") def testPertain(self): @@ -566,15 +566,15 @@ class ParserTest(unittest.TestCase): datetime(2008, 2, 29)) def testErrorType01(self): - with pytest.raises(ParserError): - parse('shouldfail') + with pytest.raises(ParserError): + parse('shouldfail') def testCorrectErrorOnFuzzyWithTokens(self): - assertRaisesRegex(self, ParserError, 'Unknown string format', + assertRaisesRegex(self, ParserError, 'Unknown string format', parse, '04/04/32/423', fuzzy_with_tokens=True) - assertRaisesRegex(self, ParserError, 'Unknown string format', + assertRaisesRegex(self, ParserError, 'Unknown string format', parse, '04/04/04 +32423', fuzzy_with_tokens=True) - assertRaisesRegex(self, ParserError, 'Unknown string format', + assertRaisesRegex(self, ParserError, 'Unknown string format', parse, '04/04/0d4', fuzzy_with_tokens=True) def testIncreasingCTime(self): @@ -585,22 +585,22 @@ class ParserTest(unittest.TestCase): delta = timedelta(days=365+31+1, seconds=1+60+60*60) dt = datetime(1900, 1, 1, 0, 0, 0, 0) for i in range(200): - assert parse(dt.ctime()) == dt + assert parse(dt.ctime()) == dt dt += delta def testIncreasingISOFormat(self): delta = timedelta(days=365+31+1, seconds=1+60+60*60) dt = datetime(1900, 1, 1, 0, 0, 0, 0) for i in range(200): - assert parse(dt.isoformat()) == dt + assert parse(dt.isoformat()) == dt dt += delta def testMicrosecondsPrecisionError(self): # Skip found out that sad precision problem. :-( dt1 = parse("00:11:25.01") dt2 = parse("00:12:10.01") - assert dt1.microsecond == 10000 - assert dt2.microsecond == 10000 + assert dt1.microsecond == 10000 + assert dt2.microsecond == 10000 def testMicrosecondPrecisionErrorReturns(self): # One more precision issue, discovered by Eric Brown. This should @@ -610,7 +610,7 @@ class ParserTest(unittest.TestCase): 1001, 1000, 999, 998, 101, 100, 99, 98]: dt = datetime(2008, 2, 27, 21, 26, 1, ms) - assert parse(dt.isoformat()) == dt + assert parse(dt.isoformat()) == dt def testCustomParserInfo(self): # Custom parser info wasn't working, as Michael Elsdörfer discovered. @@ -621,7 +621,7 @@ class ParserTest(unittest.TestCase): MONTHS[0] = ("Foo", "Foo") myparser = parser(myparserinfo()) dt = myparser.parse("01/Foo/2007") - assert dt == datetime(2007, 1, 1) + assert dt == datetime(2007, 1, 1) def testCustomParserShortDaynames(self): # Horacio Hoyos discovered that day names shorter than 3 characters, @@ -704,18 +704,18 @@ class ParserTest(unittest.TestCase): # Pre-PR, the trailing colon will cause an IndexError at 824-825 # when checking `i < len_l` and then accessing `l[i+1]` res = parse(dtstr, fuzzy=True) - assert res == datetime(2017, 7, 17, 6, 15) + assert res == datetime(2017, 7, 17, 6, 15) def test_hmBY(self): # See GH#483 dtstr = '02:17NOV2017' res = parse(dtstr, default=self.default) - assert res == datetime(2017, 11, self.default.day, 2, 17) + assert res == datetime(2017, 11, self.default.day, 2, 17) def test_validate_hour(self): # See GH353 invalid = "201A-01-01T23:58:39.239769+03:00" - with pytest.raises(ParserError): + with pytest.raises(ParserError): parse(invalid) def test_era_trailing_year(self): @@ -723,52 +723,52 @@ class ParserTest(unittest.TestCase): res = parse(dstr) assert res.year == 2001, res - def test_includes_timestr(self): - timestr = "2020-13-97T44:61:83" - - try: - parse(timestr) - except ParserError as e: - assert e.args[1] == timestr - else: - pytest.fail("Failed to raise ParserError") - - -class TestOutOfBounds(object): - - def test_no_year_zero(self): - with pytest.raises(ParserError): - parse("0000 Jun 20") - - def test_out_of_bound_day(self): - with pytest.raises(ParserError): - parse("Feb 30, 2007") - - def test_illegal_month_error(self): - with pytest.raises(ParserError): - parse("0-100") - - def test_day_sanity(self, fuzzy): - dstr = "2014-15-25" - with pytest.raises(ParserError): - parse(dstr, fuzzy=fuzzy) - - def test_minute_sanity(self, fuzzy): - dstr = "2014-02-28 22:64" - with pytest.raises(ParserError): - parse(dstr, fuzzy=fuzzy) - - def test_hour_sanity(self, fuzzy): - dstr = "2014-02-28 25:16 PM" - with pytest.raises(ParserError): - parse(dstr, fuzzy=fuzzy) - - def test_second_sanity(self, fuzzy): - dstr = "2014-02-28 22:14:64" - with pytest.raises(ParserError): - parse(dstr, fuzzy=fuzzy) - - + def test_includes_timestr(self): + timestr = "2020-13-97T44:61:83" + + try: + parse(timestr) + except ParserError as e: + assert e.args[1] == timestr + else: + pytest.fail("Failed to raise ParserError") + + +class TestOutOfBounds(object): + + def test_no_year_zero(self): + with pytest.raises(ParserError): + parse("0000 Jun 20") + + def test_out_of_bound_day(self): + with pytest.raises(ParserError): + parse("Feb 30, 2007") + + def test_illegal_month_error(self): + with pytest.raises(ParserError): + parse("0-100") + + def test_day_sanity(self, fuzzy): + dstr = "2014-15-25" + with pytest.raises(ParserError): + parse(dstr, fuzzy=fuzzy) + + def test_minute_sanity(self, fuzzy): + dstr = "2014-02-28 22:64" + with pytest.raises(ParserError): + parse(dstr, fuzzy=fuzzy) + + def test_hour_sanity(self, fuzzy): + dstr = "2014-02-28 25:16 PM" + with pytest.raises(ParserError): + parse(dstr, fuzzy=fuzzy) + + def test_second_sanity(self, fuzzy): + dstr = "2014-02-28 22:14:64" + with pytest.raises(ParserError): + parse(dstr, fuzzy=fuzzy) + + class TestParseUnimplementedCases(object): @pytest.mark.xfail def test_somewhat_ambiguous_string(self): @@ -818,7 +818,7 @@ class TestParseUnimplementedCases(object): @pytest.mark.xfail def test_non_date_number(self): dstr = '1,700' - with pytest.raises(ParserError): + with pytest.raises(ParserError): parse(dstr) @pytest.mark.xfail @@ -842,7 +842,7 @@ class TestParseUnimplementedCases(object): def test_extraneous_year_tokens(self): # This was found in the wild at insidertrading.org # Unlike in the case above, identifying the first "2012" as the year - # would not be a problem, but inferring that the latter 2012 is hhmm + # would not be a problem, but inferring that the latter 2012 is hhmm # is a problem. dstr = "2012 MARTIN CHILDREN'S IRREVOCABLE TRUST u/a/d NOVEMBER 7, 2012" expected = datetime(2012, 11, 7) @@ -876,52 +876,52 @@ class TestParseUnimplementedCases(object): expected = datetime(2017, 12, 1) assert res == expected - @pytest.mark.xfail - def test_extraneous_numerical_content(self): - # ref: https://github.com/dateutil/dateutil/issues/1029 - # parser interprets price and percentage as parts of the date - dstr = "£14.99 (25% off, until April 20)" - res = parse(dstr, fuzzy=True, default=datetime(2000, 1, 1)) - expected = datetime(2000, 4, 20) - assert res == expected - - -@pytest.mark.skipif(IS_WIN, reason="Windows does not use TZ var") -class TestTZVar(object): - def test_parse_unambiguous_nonexistent_local(self): - # When dates are specified "EST" even when they should be "EDT" in the - # local time zone, we should still assign the local time zone - with TZEnvContext('EST+5EDT,M3.2.0/2,M11.1.0/2'): - dt_exp = datetime(2011, 8, 1, 12, 30, tzinfo=tz.tzlocal()) - dt = parse('2011-08-01T12:30 EST') - - assert dt.tzname() == 'EDT' - assert dt == dt_exp - - def test_tzlocal_in_gmt(self): - # GH #318 - with TZEnvContext('GMT0BST,M3.5.0,M10.5.0'): - # This is an imaginary datetime in tz.tzlocal() but should still - # parse using the GMT-as-alias-for-UTC rule - dt = parse('2004-05-01T12:00 GMT') - dt_exp = datetime(2004, 5, 1, 12, tzinfo=tz.UTC) - - assert dt == dt_exp - - def test_tzlocal_parse_fold(self): - # One manifestion of GH #318 - with TZEnvContext('EST+5EDT,M3.2.0/2,M11.1.0/2'): - dt_exp = datetime(2011, 11, 6, 1, 30, tzinfo=tz.tzlocal()) - dt_exp = tz.enfold(dt_exp, fold=1) - dt = parse('2011-11-06T01:30 EST') - - # Because this is ambiguous, until `tz.tzlocal() is tz.tzlocal()` - # we'll just check the attributes we care about rather than - # dt == dt_exp - assert dt.tzname() == dt_exp.tzname() - assert dt.replace(tzinfo=None) == dt_exp.replace(tzinfo=None) - assert getattr(dt, 'fold') == getattr(dt_exp, 'fold') - assert dt.astimezone(tz.UTC) == dt_exp.astimezone(tz.UTC) + @pytest.mark.xfail + def test_extraneous_numerical_content(self): + # ref: https://github.com/dateutil/dateutil/issues/1029 + # parser interprets price and percentage as parts of the date + dstr = "£14.99 (25% off, until April 20)" + res = parse(dstr, fuzzy=True, default=datetime(2000, 1, 1)) + expected = datetime(2000, 4, 20) + assert res == expected + + +@pytest.mark.skipif(IS_WIN, reason="Windows does not use TZ var") +class TestTZVar(object): + def test_parse_unambiguous_nonexistent_local(self): + # When dates are specified "EST" even when they should be "EDT" in the + # local time zone, we should still assign the local time zone + with TZEnvContext('EST+5EDT,M3.2.0/2,M11.1.0/2'): + dt_exp = datetime(2011, 8, 1, 12, 30, tzinfo=tz.tzlocal()) + dt = parse('2011-08-01T12:30 EST') + + assert dt.tzname() == 'EDT' + assert dt == dt_exp + + def test_tzlocal_in_gmt(self): + # GH #318 + with TZEnvContext('GMT0BST,M3.5.0,M10.5.0'): + # This is an imaginary datetime in tz.tzlocal() but should still + # parse using the GMT-as-alias-for-UTC rule + dt = parse('2004-05-01T12:00 GMT') + dt_exp = datetime(2004, 5, 1, 12, tzinfo=tz.UTC) + + assert dt == dt_exp + + def test_tzlocal_parse_fold(self): + # One manifestion of GH #318 + with TZEnvContext('EST+5EDT,M3.2.0/2,M11.1.0/2'): + dt_exp = datetime(2011, 11, 6, 1, 30, tzinfo=tz.tzlocal()) + dt_exp = tz.enfold(dt_exp, fold=1) + dt = parse('2011-11-06T01:30 EST') + + # Because this is ambiguous, until `tz.tzlocal() is tz.tzlocal()` + # we'll just check the attributes we care about rather than + # dt == dt_exp + assert dt.tzname() == dt_exp.tzname() + assert dt.replace(tzinfo=None) == dt_exp.replace(tzinfo=None) + assert getattr(dt, 'fold') == getattr(dt_exp, 'fold') + assert dt.astimezone(tz.UTC) == dt_exp.astimezone(tz.UTC) def test_parse_tzinfos_fold(): @@ -934,7 +934,7 @@ def test_parse_tzinfos_fold(): assert dt == dt_exp assert dt.tzinfo is dt_exp.tzinfo assert getattr(dt, 'fold') == getattr(dt_exp, 'fold') - assert dt.astimezone(tz.UTC) == dt_exp.astimezone(tz.UTC) + assert dt.astimezone(tz.UTC) == dt_exp.astimezone(tz.UTC) @pytest.mark.parametrize('dtstr,dt', [ @@ -949,16 +949,16 @@ def test_rounding_floatlike_strings(dtstr, dt): @pytest.mark.parametrize('value', ['1: test', 'Nan']) def test_decimal_error(value): - # GH 632, GH 662 - decimal.Decimal raises some non-ParserError exception - # when constructed with an invalid value - with pytest.raises(ParserError): + # GH 632, GH 662 - decimal.Decimal raises some non-ParserError exception + # when constructed with an invalid value + with pytest.raises(ParserError): parse(value) - -def test_parsererror_repr(): - # GH 991 — the __repr__ was not properly indented and so was never defined. - # This tests the current behavior of the ParserError __repr__, but the - # precise format is not guaranteed to be stable and may change even in - # minor versions. This test exists to avoid regressions. - s = repr(ParserError("Problem with string: %s", "2019-01-01")) - - assert s == "ParserError('Problem with string: %s', '2019-01-01')" + +def test_parsererror_repr(): + # GH 991 — the __repr__ was not properly indented and so was never defined. + # This tests the current behavior of the ParserError __repr__, but the + # precise format is not guaranteed to be stable and may change even in + # minor versions. This test exists to avoid regressions. + s = repr(ParserError("Problem with string: %s", "2019-01-01")) + + assert s == "ParserError('Problem with string: %s', '2019-01-01')" diff --git a/contrib/python/dateutil/dateutil/test/test_relativedelta.py b/contrib/python/dateutil/dateutil/test/test_relativedelta.py index 1e5d170449..9a72b2e3af 100644 --- a/contrib/python/dateutil/dateutil/test/test_relativedelta.py +++ b/contrib/python/dateutil/dateutil/test/test_relativedelta.py @@ -1,17 +1,17 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from ._common import NotAValue +from ._common import NotAValue import calendar from datetime import datetime, date, timedelta import unittest -import pytest - +import pytest + from dateutil.relativedelta import relativedelta, MO, TU, WE, FR, SU -class RelativeDeltaTest(unittest.TestCase): +class RelativeDeltaTest(unittest.TestCase): now = datetime(2003, 9, 17, 20, 54, 47, 282310) today = date(2003, 9, 17) @@ -119,30 +119,30 @@ class RelativeDeltaTest(unittest.TestCase): self.assertEqual(self.today+relativedelta(day=31, weekday=FR(-1)), date(2003, 9, 26)) - def testLastDayOfFebruary(self): - self.assertEqual(date(2021, 2, 1) + relativedelta(day=31), - date(2021, 2, 28)) - - def testLastDayOfFebruaryLeapYear(self): - self.assertEqual(date(2020, 2, 1) + relativedelta(day=31), - date(2020, 2, 29)) - + def testLastDayOfFebruary(self): + self.assertEqual(date(2021, 2, 1) + relativedelta(day=31), + date(2021, 2, 28)) + + def testLastDayOfFebruaryLeapYear(self): + self.assertEqual(date(2020, 2, 1) + relativedelta(day=31), + date(2020, 2, 29)) + def testNextWednesdayIsToday(self): self.assertEqual(self.today+relativedelta(weekday=WE), date(2003, 9, 17)) - def testNextWednesdayNotToday(self): + def testNextWednesdayNotToday(self): self.assertEqual(self.today+relativedelta(days=+1, weekday=WE), date(2003, 9, 24)) - def testAddMoreThan12Months(self): - self.assertEqual(date(2003, 12, 1) + relativedelta(months=+13), - date(2005, 1, 1)) - - def testAddNegativeMonths(self): - self.assertEqual(date(2003, 1, 1) + relativedelta(months=-2), - date(2002, 11, 1)) - + def testAddMoreThan12Months(self): + self.assertEqual(date(2003, 12, 1) + relativedelta(months=+13), + date(2005, 1, 1)) + + def testAddNegativeMonths(self): + self.assertEqual(date(2003, 1, 1) + relativedelta(months=-2), + date(2002, 11, 1)) + def test15thISOYearWeek(self): self.assertEqual(date(2003, 1, 1) + relativedelta(day=4, weeks=+14, weekday=MO(-1)), @@ -368,38 +368,38 @@ class RelativeDeltaTest(unittest.TestCase): with self.assertRaises(ValueError): relativedelta(months=1.5) - def testRelativeDeltaInvalidDatetimeObject(self): - with self.assertRaises(TypeError): - relativedelta(dt1='2018-01-01', dt2='2018-01-02') - - with self.assertRaises(TypeError): - relativedelta(dt1=datetime(2018, 1, 1), dt2='2018-01-02') - - with self.assertRaises(TypeError): - relativedelta(dt1='2018-01-01', dt2=datetime(2018, 1, 2)) - + def testRelativeDeltaInvalidDatetimeObject(self): + with self.assertRaises(TypeError): + relativedelta(dt1='2018-01-01', dt2='2018-01-02') + + with self.assertRaises(TypeError): + relativedelta(dt1=datetime(2018, 1, 1), dt2='2018-01-02') + + with self.assertRaises(TypeError): + relativedelta(dt1='2018-01-01', dt2=datetime(2018, 1, 2)) + def testRelativeDeltaFractionalAbsolutes(self): # Fractional absolute values will soon be unsupported, # check for the deprecation warning. - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning): relativedelta(year=2.86) - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning): relativedelta(month=1.29) - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning): relativedelta(day=0.44) - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning): relativedelta(hour=23.98) - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning): relativedelta(minute=45.21) - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning): relativedelta(second=13.2) - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning): relativedelta(microsecond=157221.93) def testRelativeDeltaFractionalRepr(self): @@ -484,7 +484,7 @@ class RelativeDeltaTest(unittest.TestCase): self.assertEqual(rd1.normalized(), relativedelta(days=2, hours=18)) - # Equivalent to (days=1, hours=11, minutes=31, seconds=12) + # Equivalent to (days=1, hours=11, minutes=31, seconds=12) rd2 = relativedelta(days=1.48) self.assertEqual(rd2.normalized(), diff --git a/contrib/python/dateutil/dateutil/test/test_rrule.py b/contrib/python/dateutil/dateutil/test/test_rrule.py index 52673ecc26..9a3dbca042 100644 --- a/contrib/python/dateutil/dateutil/test/test_rrule.py +++ b/contrib/python/dateutil/dateutil/test/test_rrule.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals from datetime import datetime, date import unittest -from six import PY2 +from six import PY2 from dateutil import tz from dateutil.rrule import ( @@ -19,7 +19,7 @@ import pytest @pytest.mark.rrule -class RRuleTest(unittest.TestCase): +class RRuleTest(unittest.TestCase): def _rrulestr_reverse_test(self, rule): """ Call with an `rrule` and it will test that `str(rrule)` generates a @@ -2283,7 +2283,7 @@ class RRuleTest(unittest.TestCase): datetime(2010, 3, 22, 14, 1)]) def testLongIntegers(self): - if PY2: # There are no longs in python3 + if PY2: # There are no longs in python3 self.assertEqual(list(rrule(MINUTELY, count=long(2), interval=long(2), @@ -2371,7 +2371,7 @@ class RRuleTest(unittest.TestCase): See rfc-5545 3.3.10 - This checks for the deprecation warning, and will eventually check for an error. """ - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning): rrule(DAILY, dtstart=datetime(1997, 9, 2, 9, 0), count=3, until=datetime(1997, 9, 4, 9, 0)) @@ -2852,74 +2852,74 @@ class RRuleTest(unittest.TestCase): datetime(1997, 9, 9, 9, 0), datetime(1997, 9, 16, 9, 0)]) - def testStrSetExDateMultiple(self): - rrstr = ("DTSTART:19970902T090000\n" - "RRULE:FREQ=YEARLY;COUNT=6;BYDAY=TU,TH\n" - "EXDATE:19970904T090000,19970911T090000,19970918T090000\n") - - rr = rrulestr(rrstr) - assert list(rr) == [datetime(1997, 9, 2, 9, 0), - datetime(1997, 9, 9, 9, 0), - datetime(1997, 9, 16, 9, 0)] - - def testStrSetExDateWithTZID(self): - BXL = tz.gettz('Europe/Brussels') - rr = rrulestr("DTSTART;TZID=Europe/Brussels:19970902T090000\n" - "RRULE:FREQ=YEARLY;COUNT=6;BYDAY=TU,TH\n" - "EXDATE;TZID=Europe/Brussels:19970904T090000\n" - "EXDATE;TZID=Europe/Brussels:19970911T090000\n" - "EXDATE;TZID=Europe/Brussels:19970918T090000\n") - - assert list(rr) == [datetime(1997, 9, 2, 9, 0, tzinfo=BXL), - datetime(1997, 9, 9, 9, 0, tzinfo=BXL), - datetime(1997, 9, 16, 9, 0, tzinfo=BXL)] - - def testStrSetExDateValueDateTimeNoTZID(self): - rrstr = '\n'.join([ - "DTSTART:19970902T090000", - "RRULE:FREQ=YEARLY;COUNT=4;BYDAY=TU,TH", - "EXDATE;VALUE=DATE-TIME:19970902T090000", - "EXDATE;VALUE=DATE-TIME:19970909T090000", - ]) - - rr = rrulestr(rrstr) - assert list(rr) == [datetime(1997, 9, 4, 9), datetime(1997, 9, 11, 9)] - - def testStrSetExDateValueMixDateTimeNoTZID(self): - rrstr = '\n'.join([ - "DTSTART:19970902T090000", - "RRULE:FREQ=YEARLY;COUNT=4;BYDAY=TU,TH", - "EXDATE;VALUE=DATE-TIME:19970902T090000", - "EXDATE:19970909T090000", - ]) - - rr = rrulestr(rrstr) - assert list(rr) == [datetime(1997, 9, 4, 9), datetime(1997, 9, 11, 9)] - - def testStrSetExDateValueDateTimeWithTZID(self): - BXL = tz.gettz('Europe/Brussels') - rrstr = '\n'.join([ - "DTSTART;VALUE=DATE-TIME;TZID=Europe/Brussels:19970902T090000", - "RRULE:FREQ=YEARLY;COUNT=4;BYDAY=TU,TH", - "EXDATE;VALUE=DATE-TIME;TZID=Europe/Brussels:19970902T090000", - "EXDATE;VALUE=DATE-TIME;TZID=Europe/Brussels:19970909T090000", - ]) - - rr = rrulestr(rrstr) - assert list(rr) == [datetime(1997, 9, 4, 9, tzinfo=BXL), - datetime(1997, 9, 11, 9, tzinfo=BXL)] - - def testStrSetExDateValueDate(self): - rrstr = '\n'.join([ - "DTSTART;VALUE=DATE:19970902", - "RRULE:FREQ=YEARLY;COUNT=4;BYDAY=TU,TH", - "EXDATE;VALUE=DATE:19970902", - "EXDATE;VALUE=DATE:19970909", - ]) - - rr = rrulestr(rrstr) - assert list(rr) == [datetime(1997, 9, 4), datetime(1997, 9, 11)] - + def testStrSetExDateMultiple(self): + rrstr = ("DTSTART:19970902T090000\n" + "RRULE:FREQ=YEARLY;COUNT=6;BYDAY=TU,TH\n" + "EXDATE:19970904T090000,19970911T090000,19970918T090000\n") + + rr = rrulestr(rrstr) + assert list(rr) == [datetime(1997, 9, 2, 9, 0), + datetime(1997, 9, 9, 9, 0), + datetime(1997, 9, 16, 9, 0)] + + def testStrSetExDateWithTZID(self): + BXL = tz.gettz('Europe/Brussels') + rr = rrulestr("DTSTART;TZID=Europe/Brussels:19970902T090000\n" + "RRULE:FREQ=YEARLY;COUNT=6;BYDAY=TU,TH\n" + "EXDATE;TZID=Europe/Brussels:19970904T090000\n" + "EXDATE;TZID=Europe/Brussels:19970911T090000\n" + "EXDATE;TZID=Europe/Brussels:19970918T090000\n") + + assert list(rr) == [datetime(1997, 9, 2, 9, 0, tzinfo=BXL), + datetime(1997, 9, 9, 9, 0, tzinfo=BXL), + datetime(1997, 9, 16, 9, 0, tzinfo=BXL)] + + def testStrSetExDateValueDateTimeNoTZID(self): + rrstr = '\n'.join([ + "DTSTART:19970902T090000", + "RRULE:FREQ=YEARLY;COUNT=4;BYDAY=TU,TH", + "EXDATE;VALUE=DATE-TIME:19970902T090000", + "EXDATE;VALUE=DATE-TIME:19970909T090000", + ]) + + rr = rrulestr(rrstr) + assert list(rr) == [datetime(1997, 9, 4, 9), datetime(1997, 9, 11, 9)] + + def testStrSetExDateValueMixDateTimeNoTZID(self): + rrstr = '\n'.join([ + "DTSTART:19970902T090000", + "RRULE:FREQ=YEARLY;COUNT=4;BYDAY=TU,TH", + "EXDATE;VALUE=DATE-TIME:19970902T090000", + "EXDATE:19970909T090000", + ]) + + rr = rrulestr(rrstr) + assert list(rr) == [datetime(1997, 9, 4, 9), datetime(1997, 9, 11, 9)] + + def testStrSetExDateValueDateTimeWithTZID(self): + BXL = tz.gettz('Europe/Brussels') + rrstr = '\n'.join([ + "DTSTART;VALUE=DATE-TIME;TZID=Europe/Brussels:19970902T090000", + "RRULE:FREQ=YEARLY;COUNT=4;BYDAY=TU,TH", + "EXDATE;VALUE=DATE-TIME;TZID=Europe/Brussels:19970902T090000", + "EXDATE;VALUE=DATE-TIME;TZID=Europe/Brussels:19970909T090000", + ]) + + rr = rrulestr(rrstr) + assert list(rr) == [datetime(1997, 9, 4, 9, tzinfo=BXL), + datetime(1997, 9, 11, 9, tzinfo=BXL)] + + def testStrSetExDateValueDate(self): + rrstr = '\n'.join([ + "DTSTART;VALUE=DATE:19970902", + "RRULE:FREQ=YEARLY;COUNT=4;BYDAY=TU,TH", + "EXDATE;VALUE=DATE:19970902", + "EXDATE;VALUE=DATE:19970909", + ]) + + rr = rrulestr(rrstr) + assert list(rr) == [datetime(1997, 9, 4), datetime(1997, 9, 11)] + def testStrSetDateAndExDate(self): self.assertEqual(list(rrulestr( "DTSTART:19970902T090000\n" @@ -2996,11 +2996,11 @@ class RRuleTest(unittest.TestCase): self.assertEqual(list(rr), [datetime(1997, 9, 2, 0, 0, 0), datetime(1998, 9, 2, 0, 0, 0)]) - def testStrMultipleDTStartComma(self): - with pytest.raises(ValueError): - rr = rrulestr("DTSTART:19970101T000000,19970202T000000\n" - "RRULE:FREQ=YEARLY;COUNT=1") - + def testStrMultipleDTStartComma(self): + with pytest.raises(ValueError): + rr = rrulestr("DTSTART:19970101T000000,19970202T000000\n" + "RRULE:FREQ=YEARLY;COUNT=1") + def testStrInvalidUntil(self): with self.assertRaises(ValueError): list(rrulestr("DTSTART:19970902T090000\n" @@ -4578,7 +4578,7 @@ class RRuleTest(unittest.TestCase): dtstart=datetime(1997, 9, 2, 9, 0))) def testToStrLongIntegers(self): - if PY2: # There are no longs in python3 + if PY2: # There are no longs in python3 self._rrulestr_reverse_test(rrule(MINUTELY, count=long(2), interval=long(2), diff --git a/contrib/python/dateutil/dateutil/test/test_tz.py b/contrib/python/dateutil/dateutil/test/test_tz.py index e5e4772d9a..0fba337a3e 100644 --- a/contrib/python/dateutil/dateutil/test/test_tz.py +++ b/contrib/python/dateutil/dateutil/test/test_tz.py @@ -7,15 +7,15 @@ from ._common import ComparesEqual from datetime import datetime, timedelta from datetime import time as dt_time from datetime import tzinfo -from six import PY2 -from io import BytesIO, StringIO +from six import PY2 +from io import BytesIO, StringIO import unittest import sys import base64 import copy -import gc -import weakref +import gc +import weakref from functools import partial @@ -156,9 +156,9 @@ END:VTIMEZONE EST_TUPLE = ('EST', timedelta(hours=-5), timedelta(hours=0)) EDT_TUPLE = ('EDT', timedelta(hours=-4), timedelta(hours=1)) -SUPPORTS_SUB_MINUTE_OFFSETS = sys.version_info >= (3, 6) - +SUPPORTS_SUB_MINUTE_OFFSETS = sys.version_info >= (3, 6) + ### # Helper functions def get_timezone_tuple(dt): @@ -197,8 +197,8 @@ class TzFoldMixin(object): with self._gettz_context(tzname): SYD = self.gettz(tzname) - t0_u = datetime(2012, 3, 31, 15, 30, tzinfo=tz.UTC) # AEST - t1_u = datetime(2012, 3, 31, 16, 30, tzinfo=tz.UTC) # AEDT + t0_u = datetime(2012, 3, 31, 15, 30, tzinfo=tz.UTC) # AEST + t1_u = datetime(2012, 3, 31, 16, 30, tzinfo=tz.UTC) # AEDT t0_syd0 = t0_u.astimezone(SYD) t1_syd1 = t1_u.astimezone(SYD) @@ -219,8 +219,8 @@ class TzFoldMixin(object): with self._gettz_context(tzname): SYD = self.gettz(tzname) - t0_u = datetime(2012, 10, 6, 15, 30, tzinfo=tz.UTC) # AEST - t1_u = datetime(2012, 10, 6, 16, 30, tzinfo=tz.UTC) # AEDT + t0_u = datetime(2012, 10, 6, 15, 30, tzinfo=tz.UTC) # AEST + t1_u = datetime(2012, 10, 6, 16, 30, tzinfo=tz.UTC) # AEDT t0 = t0_u.astimezone(SYD) t1 = t1_u.astimezone(SYD) @@ -241,8 +241,8 @@ class TzFoldMixin(object): with self._gettz_context(tzname): TOR = self.gettz(tzname) - t0_u = datetime(2011, 11, 6, 5, 30, tzinfo=tz.UTC) - t1_u = datetime(2011, 11, 6, 6, 30, tzinfo=tz.UTC) + t0_u = datetime(2011, 11, 6, 5, 30, tzinfo=tz.UTC) + t1_u = datetime(2011, 11, 6, 6, 30, tzinfo=tz.UTC) t0_tor = t0_u.astimezone(TOR) t1_tor = t1_u.astimezone(TOR) @@ -264,8 +264,8 @@ class TzFoldMixin(object): with self._gettz_context(tzname): TOR = self.gettz(tzname) - t0_u = datetime(2011, 3, 13, 6, 30, tzinfo=tz.UTC) - t1_u = datetime(2011, 3, 13, 7, 30, tzinfo=tz.UTC) + t0_u = datetime(2011, 3, 13, 6, 30, tzinfo=tz.UTC) + t1_u = datetime(2011, 3, 13, 7, 30, tzinfo=tz.UTC) t0 = t0_u.astimezone(TOR) t1 = t1_u.astimezone(TOR) @@ -285,7 +285,7 @@ class TzFoldMixin(object): with self._gettz_context(tzname): LON = self.gettz(tzname) - UTC = tz.UTC + UTC = tz.UTC t0_u = datetime(2013, 10, 27, 0, 30, tzinfo=UTC) # BST t1_u = datetime(2013, 10, 27, 1, 30, tzinfo=UTC) # GMT @@ -307,7 +307,7 @@ class TzFoldMixin(object): with self._gettz_context(tzname): NYC = self.gettz(tzname) - UTC = tz.UTC + UTC = tz.UTC hour = timedelta(hours=1) # Firmly 2015-11-01 0:30 EDT-4 @@ -338,7 +338,7 @@ class TzFoldMixin(object): with self._gettz_context(tzname): NYC = self.gettz(tzname) - UTC = tz.UTC + UTC = tz.UTC dt0 = datetime(2011, 11, 6, 1, 30, tzinfo=NYC) dt1 = tz.enfold(dt0, fold=1) @@ -424,7 +424,7 @@ class TzFoldMixin(object): SYD0 = self.gettz(tzname) SYD1 = self.gettz(tzname) - t0_u = datetime(2012, 3, 31, 14, 30, tzinfo=tz.UTC) # AEST + t0_u = datetime(2012, 3, 31, 14, 30, tzinfo=tz.UTC) # AEST t0_syd0 = t0_u.astimezone(SYD0) t0_syd1 = t0_u.astimezone(SYD1) @@ -453,13 +453,13 @@ class TzWinFoldMixin(object): if gap: t_n = dston - timedelta(minutes=30) - t0_u = t_n.replace(tzinfo=tzi).astimezone(tz.UTC) + t0_u = t_n.replace(tzinfo=tzi).astimezone(tz.UTC) t1_u = t0_u + timedelta(hours=1) else: # Get 1 hour before the first ambiguous date t_n = dstoff - timedelta(minutes=30) - t0_u = t_n.replace(tzinfo=tzi).astimezone(tz.UTC) + t0_u = t_n.replace(tzinfo=tzi).astimezone(tz.UTC) t_n += timedelta(hours=1) # Naive ambiguous date t0_u = t0_u + timedelta(hours=1) # First ambiguous date t1_u = t0_u + timedelta(hours=1) # Second ambiguous date @@ -560,7 +560,7 @@ class TzWinFoldMixin(object): with self.context(tzname): NYC = self.tzclass(*args) - UTC = tz.UTC + UTC = tz.UTC hour = timedelta(hours=1) # Firmly 2015-11-01 0:30 EDT-4 @@ -595,7 +595,7 @@ class TzWinFoldMixin(object): with self.context(tzname): NYC = self.tzclass(*args) - UTC = tz.UTC + UTC = tz.UTC t_n, t0_u, t1_u = self.get_utc_transitions(NYC, 2011, False) @@ -699,7 +699,7 @@ class TzOffsetTest(unittest.TestCase): self.assertEqual(utc, gmt) def testUTCEquality(self): - utc = tz.UTC + utc = tz.UTC o_utc = tz.tzoffset('UTC', 0) self.assertEqual(utc, o_utc) @@ -735,29 +735,29 @@ class TzOffsetTest(unittest.TestCase): assert tz1 is tz2 - -@pytest.mark.smoke -@pytest.mark.tzoffset -def test_tzoffset_weakref(): - UTC1 = tz.tzoffset('UTC', 0) - UTC_ref = weakref.ref(tz.tzoffset('UTC', 0)) - UTC1 is UTC_ref() - del UTC1 - gc.collect() - - assert UTC_ref() is not None # Should be in the strong cache - assert UTC_ref() is tz.tzoffset('UTC', 0) - - # Fill the strong cache with other items - for offset in range(5,15): - tz.tzoffset('RandomZone', offset) - - gc.collect() - assert UTC_ref() is None - assert UTC_ref() is not tz.tzoffset('UTC', 0) - - + +@pytest.mark.smoke @pytest.mark.tzoffset +def test_tzoffset_weakref(): + UTC1 = tz.tzoffset('UTC', 0) + UTC_ref = weakref.ref(tz.tzoffset('UTC', 0)) + UTC1 is UTC_ref() + del UTC1 + gc.collect() + + assert UTC_ref() is not None # Should be in the strong cache + assert UTC_ref() is tz.tzoffset('UTC', 0) + + # Fill the strong cache with other items + for offset in range(5,15): + tz.tzoffset('RandomZone', offset) + + gc.collect() + assert UTC_ref() is None + assert UTC_ref() is not tz.tzoffset('UTC', 0) + + +@pytest.mark.tzoffset @pytest.mark.parametrize('args', [ ('UTC', 0), ('EST', -18000), @@ -770,25 +770,25 @@ def test_tzoffset_singleton(args): assert tz1 is tz2 - -@pytest.mark.tzoffset -@pytest.mark.skipif(not SUPPORTS_SUB_MINUTE_OFFSETS, - reason='Sub-minute offsets not supported') -def test_tzoffset_sub_minute(): - delta = timedelta(hours=12, seconds=30) - test_datetime = datetime(2000, 1, 1, tzinfo=tz.tzoffset(None, delta)) - assert test_datetime.utcoffset() == delta - - -@pytest.mark.tzoffset -@pytest.mark.skipif(SUPPORTS_SUB_MINUTE_OFFSETS, - reason='Sub-minute offsets supported') -def test_tzoffset_sub_minute_rounding(): - delta = timedelta(hours=12, seconds=30) - test_date = datetime(2000, 1, 1, tzinfo=tz.tzoffset(None, delta)) - assert test_date.utcoffset() == timedelta(hours=12, minutes=1) - - + +@pytest.mark.tzoffset +@pytest.mark.skipif(not SUPPORTS_SUB_MINUTE_OFFSETS, + reason='Sub-minute offsets not supported') +def test_tzoffset_sub_minute(): + delta = timedelta(hours=12, seconds=30) + test_datetime = datetime(2000, 1, 1, tzinfo=tz.tzoffset(None, delta)) + assert test_datetime.utcoffset() == delta + + +@pytest.mark.tzoffset +@pytest.mark.skipif(SUPPORTS_SUB_MINUTE_OFFSETS, + reason='Sub-minute offsets supported') +def test_tzoffset_sub_minute_rounding(): + delta = timedelta(hours=12, seconds=30) + test_date = datetime(2000, 1, 1, tzinfo=tz.tzoffset(None, delta)) + assert test_date.utcoffset() == timedelta(hours=12, minutes=1) + + @pytest.mark.tzlocal class TzLocalTest(unittest.TestCase): def testEquality(self): @@ -952,7 +952,7 @@ class TzLocalNixTest(unittest.TestCase, TzFoldMixin): def testUTCEquality(self): with TZEnvContext(self.UTC): - assert tz.tzlocal() == tz.UTC + assert tz.tzlocal() == tz.UTC # TODO: Maybe a better hack than this? @@ -993,7 +993,7 @@ def test_tzlocal_local_time_trim_colon(): @mark_tzlocal_nix @pytest.mark.parametrize('tzvar, tzoff', [ ('EST5', tz.tzoffset('EST', -18000)), - ('GMT0', tz.tzoffset('GMT', 0)), + ('GMT0', tz.tzoffset('GMT', 0)), ('YAKT-9', tz.tzoffset('YAKT', timedelta(hours=9))), ('JST-9', tz.tzoffset('JST', timedelta(hours=9))), ]) @@ -1078,65 +1078,65 @@ class GettzTest(unittest.TestCase, TzFoldMixin): assert local1 is not local2 - -@pytest.mark.gettz -def test_gettz_same_result_for_none_and_empty_string(): - local_from_none = tz.gettz() - local_from_empty_string = tz.gettz("") - assert local_from_none is not None - assert local_from_empty_string is not None - assert local_from_none == local_from_empty_string - - -@pytest.mark.gettz -@pytest.mark.parametrize('badzone', [ - 'Fake.Region/Abcdefghijklmnop', # Violates several tz project name rules -]) -def test_gettz_badzone(badzone): - # Make sure passing a bad TZ string to gettz returns None (GH #800) - tzi = tz.gettz(badzone) - assert tzi is None - - -@pytest.mark.gettz -def test_gettz_badzone_unicode(): - # Make sure a unicode string can be passed to TZ (GH #802) - # When fixed, combine this with test_gettz_badzone - tzi = tz.gettz('🐼') - assert tzi is None - - -@pytest.mark.gettz -@pytest.mark.parametrize( - "badzone,exc_reason", - [ - pytest.param( - b"America/New_York", - ".*should be str, not bytes.*", - id="bytes on Python 3", - marks=[ - pytest.mark.skipif( - PY2, reason="bytes arguments accepted in Python 2" - ) - ], - ), - pytest.param( - object(), - None, - id="no startswith()", - marks=[ - pytest.mark.xfail(reason="AttributeError instead of TypeError", - raises=AttributeError), - ], - ), - ], -) -def test_gettz_zone_wrong_type(badzone, exc_reason): - with pytest.raises(TypeError, match=exc_reason): - tz.gettz(badzone) - - + @pytest.mark.gettz +def test_gettz_same_result_for_none_and_empty_string(): + local_from_none = tz.gettz() + local_from_empty_string = tz.gettz("") + assert local_from_none is not None + assert local_from_empty_string is not None + assert local_from_none == local_from_empty_string + + +@pytest.mark.gettz +@pytest.mark.parametrize('badzone', [ + 'Fake.Region/Abcdefghijklmnop', # Violates several tz project name rules +]) +def test_gettz_badzone(badzone): + # Make sure passing a bad TZ string to gettz returns None (GH #800) + tzi = tz.gettz(badzone) + assert tzi is None + + +@pytest.mark.gettz +def test_gettz_badzone_unicode(): + # Make sure a unicode string can be passed to TZ (GH #802) + # When fixed, combine this with test_gettz_badzone + tzi = tz.gettz('🐼') + assert tzi is None + + +@pytest.mark.gettz +@pytest.mark.parametrize( + "badzone,exc_reason", + [ + pytest.param( + b"America/New_York", + ".*should be str, not bytes.*", + id="bytes on Python 3", + marks=[ + pytest.mark.skipif( + PY2, reason="bytes arguments accepted in Python 2" + ) + ], + ), + pytest.param( + object(), + None, + id="no startswith()", + marks=[ + pytest.mark.xfail(reason="AttributeError instead of TypeError", + raises=AttributeError), + ], + ), + ], +) +def test_gettz_zone_wrong_type(badzone, exc_reason): + with pytest.raises(TypeError, match=exc_reason): + tz.gettz(badzone) + + +@pytest.mark.gettz @pytest.mark.xfail(IS_WIN, reason='zoneinfo separately cached') def test_gettz_cache_clear(): NYC1 = tz.gettz('America/New_York') @@ -1146,54 +1146,54 @@ def test_gettz_cache_clear(): assert NYC1 is not NYC2 -@pytest.mark.gettz -@pytest.mark.xfail(IS_WIN, reason='zoneinfo separately cached') -def test_gettz_set_cache_size(): - tz.gettz.cache_clear() - tz.gettz.set_cache_size(3) - - MONACO_ref = weakref.ref(tz.gettz('Europe/Monaco')) - EASTER_ref = weakref.ref(tz.gettz('Pacific/Easter')) - CURRIE_ref = weakref.ref(tz.gettz('Australia/Currie')) - - gc.collect() - - assert MONACO_ref() is not None - assert EASTER_ref() is not None - assert CURRIE_ref() is not None - - tz.gettz.set_cache_size(2) - gc.collect() - - assert MONACO_ref() is None - -@pytest.mark.xfail(IS_WIN, reason="Windows does not use system zoneinfo") -@pytest.mark.smoke -@pytest.mark.gettz -def test_gettz_weakref(): - tz.gettz.cache_clear() - tz.gettz.set_cache_size(2) - NYC1 = tz.gettz('America/New_York') - NYC_ref = weakref.ref(tz.gettz('America/New_York')) - - assert NYC1 is NYC_ref() - - del NYC1 - gc.collect() - - assert NYC_ref() is not None # Should still be in the strong cache - assert tz.gettz('America/New_York') is NYC_ref() - - # Populate strong cache with other timezones - tz.gettz('Europe/Monaco') - tz.gettz('Pacific/Easter') - tz.gettz('Australia/Currie') - - gc.collect() - assert NYC_ref() is None # Should have been pushed out - assert tz.gettz('America/New_York') is not NYC_ref() - -class ZoneInfoGettzTest(GettzTest): +@pytest.mark.gettz +@pytest.mark.xfail(IS_WIN, reason='zoneinfo separately cached') +def test_gettz_set_cache_size(): + tz.gettz.cache_clear() + tz.gettz.set_cache_size(3) + + MONACO_ref = weakref.ref(tz.gettz('Europe/Monaco')) + EASTER_ref = weakref.ref(tz.gettz('Pacific/Easter')) + CURRIE_ref = weakref.ref(tz.gettz('Australia/Currie')) + + gc.collect() + + assert MONACO_ref() is not None + assert EASTER_ref() is not None + assert CURRIE_ref() is not None + + tz.gettz.set_cache_size(2) + gc.collect() + + assert MONACO_ref() is None + +@pytest.mark.xfail(IS_WIN, reason="Windows does not use system zoneinfo") +@pytest.mark.smoke +@pytest.mark.gettz +def test_gettz_weakref(): + tz.gettz.cache_clear() + tz.gettz.set_cache_size(2) + NYC1 = tz.gettz('America/New_York') + NYC_ref = weakref.ref(tz.gettz('America/New_York')) + + assert NYC1 is NYC_ref() + + del NYC1 + gc.collect() + + assert NYC_ref() is not None # Should still be in the strong cache + assert tz.gettz('America/New_York') is NYC_ref() + + # Populate strong cache with other timezones + tz.gettz('Europe/Monaco') + tz.gettz('Pacific/Easter') + tz.gettz('Australia/Currie') + + gc.collect() + assert NYC_ref() is None # Should have been pushed out + assert tz.gettz('America/New_York') is not NYC_ref() + +class ZoneInfoGettzTest(GettzTest): def gettz(self, name): zoneinfo_file = zoneinfo.get_zonefile_instance() return zoneinfo_file.get(name) @@ -1253,11 +1253,11 @@ class ZoneInfoGettzTest(GettzTest): self.assertIs(zif_1, zif_2) def testZoneInfoDeprecated(self): - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning): zoneinfo.gettz('US/Eastern') def testZoneInfoMetadataDeprecated(self): - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning): zoneinfo.gettz_db_metadata() @@ -1350,7 +1350,7 @@ class TZRangeTest(unittest.TestCase, TzFoldMixin): def testBrokenIsDstHandling(self): # tzrange._isdst() was using a date() rather than a datetime(). # Issue reported by Lennart Regebro. - dt = datetime(2007, 8, 6, 4, 10, tzinfo=tz.UTC) + dt = datetime(2007, 8, 6, 4, 10, tzinfo=tz.UTC) self.assertEqual(dt.astimezone(tz=tz.gettz("GMT+2")), datetime(2007, 8, 6, 6, 10, tzinfo=tz.tzstr("GMT+2"))) @@ -1520,29 +1520,29 @@ class TZStrTest(unittest.TestCase, TzFoldMixin): # Ensure that these still are all the same zone assert tz1 == tz2 == tz3 - -@pytest.mark.smoke -@pytest.mark.tzstr -def test_tzstr_weakref(): - tz_t1 = tz.tzstr('EST5EDT') - tz_t2_ref = weakref.ref(tz.tzstr('EST5EDT')) - assert tz_t1 is tz_t2_ref() - - del tz_t1 - gc.collect() - - assert tz_t2_ref() is not None - assert tz.tzstr('EST5EDT') is tz_t2_ref() - - for offset in range(5,15): - tz.tzstr('GMT+{}'.format(offset)) - gc.collect() - - assert tz_t2_ref() is None - assert tz.tzstr('EST5EDT') is not tz_t2_ref() - - + +@pytest.mark.smoke @pytest.mark.tzstr +def test_tzstr_weakref(): + tz_t1 = tz.tzstr('EST5EDT') + tz_t2_ref = weakref.ref(tz.tzstr('EST5EDT')) + assert tz_t1 is tz_t2_ref() + + del tz_t1 + gc.collect() + + assert tz_t2_ref() is not None + assert tz.tzstr('EST5EDT') is tz_t2_ref() + + for offset in range(5,15): + tz.tzstr('GMT+{}'.format(offset)) + gc.collect() + + assert tz_t2_ref() is None + assert tz.tzstr('EST5EDT') is not tz_t2_ref() + + +@pytest.mark.tzstr @pytest.mark.parametrize('tz_str,expected', [ # From https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html ('', tz.tzrange(None)), # TODO: Should change this so tz.tzrange('') works @@ -2068,13 +2068,13 @@ class TZTest(unittest.TestCase): def testGMTOffset(self): # GMT and UTC offsets have inverted signal when compared to the # usual TZ variable handling. - dt = datetime(2007, 8, 6, 4, 10, tzinfo=tz.UTC) + dt = datetime(2007, 8, 6, 4, 10, tzinfo=tz.UTC) self.assertEqual(dt.astimezone(tz=tz.tzstr("GMT+2")), datetime(2007, 8, 6, 6, 10, tzinfo=tz.tzstr("GMT+2"))) self.assertEqual(dt.astimezone(tz=tz.gettz("UTC-2")), datetime(2007, 8, 6, 2, 10, tzinfo=tz.tzstr("UTC-2"))) - @unittest.skipIf(IS_WIN, "requires Unix") + @unittest.skipIf(IS_WIN, "requires Unix") def testTZSetDoesntCorrupt(self): # if we start in non-UTC then tzset UTC make sure parse doesn't get # confused @@ -2084,41 +2084,41 @@ class TZTest(unittest.TestCase): self.assertEqual(str(dt), '2014-07-20 12:34:56+00:00') -@pytest.mark.tzfile -@pytest.mark.skipif(not SUPPORTS_SUB_MINUTE_OFFSETS, - reason='Sub-minute offsets not supported') -def test_tzfile_sub_minute_offset(): - # If user running python 3.6 or newer, exact offset is used - tzc = tz.tzfile(BytesIO(base64.b64decode(EUROPE_HELSINKI))) - offset = timedelta(hours=1, minutes=39, seconds=52) - assert datetime(1900, 1, 1, 0, 0, tzinfo=tzc).utcoffset() == offset - - -@pytest.mark.tzfile -@pytest.mark.skipif(SUPPORTS_SUB_MINUTE_OFFSETS, - reason='Sub-minute offsets supported.') -def test_sub_minute_rounding_tzfile(): - # This timezone has an offset of 5992 seconds in 1900-01-01. - # For python version pre-3.6, this will be rounded - tzc = tz.tzfile(BytesIO(base64.b64decode(EUROPE_HELSINKI))) - offset = timedelta(hours=1, minutes=40) - assert datetime(1900, 1, 1, 0, 0, tzinfo=tzc).utcoffset() == offset - - -@pytest.mark.tzfile -def test_samoa_transition(): - # utcoffset() was erroneously returning +14:00 an hour early (GH #812) - APIA = tz.gettz('Pacific/Apia') - dt = datetime(2011, 12, 29, 23, 59, tzinfo=APIA) - assert dt.utcoffset() == timedelta(hours=-10) - - # Make sure the transition actually works, too - dt_after = (dt.astimezone(tz.UTC) + timedelta(minutes=1)).astimezone(APIA) - assert dt_after == datetime(2011, 12, 31, tzinfo=APIA) - assert dt_after.utcoffset() == timedelta(hours=14) - - -@unittest.skipUnless(IS_WIN, "Requires Windows") +@pytest.mark.tzfile +@pytest.mark.skipif(not SUPPORTS_SUB_MINUTE_OFFSETS, + reason='Sub-minute offsets not supported') +def test_tzfile_sub_minute_offset(): + # If user running python 3.6 or newer, exact offset is used + tzc = tz.tzfile(BytesIO(base64.b64decode(EUROPE_HELSINKI))) + offset = timedelta(hours=1, minutes=39, seconds=52) + assert datetime(1900, 1, 1, 0, 0, tzinfo=tzc).utcoffset() == offset + + +@pytest.mark.tzfile +@pytest.mark.skipif(SUPPORTS_SUB_MINUTE_OFFSETS, + reason='Sub-minute offsets supported.') +def test_sub_minute_rounding_tzfile(): + # This timezone has an offset of 5992 seconds in 1900-01-01. + # For python version pre-3.6, this will be rounded + tzc = tz.tzfile(BytesIO(base64.b64decode(EUROPE_HELSINKI))) + offset = timedelta(hours=1, minutes=40) + assert datetime(1900, 1, 1, 0, 0, tzinfo=tzc).utcoffset() == offset + + +@pytest.mark.tzfile +def test_samoa_transition(): + # utcoffset() was erroneously returning +14:00 an hour early (GH #812) + APIA = tz.gettz('Pacific/Apia') + dt = datetime(2011, 12, 29, 23, 59, tzinfo=APIA) + assert dt.utcoffset() == timedelta(hours=-10) + + # Make sure the transition actually works, too + dt_after = (dt.astimezone(tz.UTC) + timedelta(minutes=1)).astimezone(APIA) + assert dt_after == datetime(2011, 12, 31, tzinfo=APIA) + assert dt_after.utcoffset() == timedelta(hours=14) + + +@unittest.skipUnless(IS_WIN, "Requires Windows") class TzWinTest(unittest.TestCase, TzWinFoldMixin): def setUp(self): self.tzclass = tzwin.tzwin @@ -2207,7 +2207,7 @@ class TzWinTest(unittest.TestCase, TzWinFoldMixin): def testTzWinEqualityInvalid(self): # Compare to objects that do not implement comparison with this # (should default to False) - UTC = tz.UTC + UTC = tz.UTC EST = tz.tzwin('Eastern Standard Time') self.assertFalse(EST == UTC) @@ -2256,7 +2256,7 @@ class TzWinTest(unittest.TestCase, TzWinFoldMixin): 'South Africa Standard Time') -@unittest.skipUnless(IS_WIN, "Requires Windows") +@unittest.skipUnless(IS_WIN, "Requires Windows") class TzWinLocalTest(unittest.TestCase, TzWinFoldMixin): def setUp(self): @@ -2269,7 +2269,7 @@ class TzWinLocalTest(unittest.TestCase, TzWinFoldMixin): def testLocal(self): # Not sure how to pin a local time zone, so for now we're just going # to run this and make sure it doesn't raise an error - # See GitHub Issue #135: https://github.com/dateutil/dateutil/issues/135 + # See GitHub Issue #135: https://github.com/dateutil/dateutil/issues/135 datetime.now(tzwin.tzwinlocal()) def testTzwinLocalUTCOffset(self): @@ -2663,46 +2663,46 @@ class DatetimeExistsTest(unittest.TestCase): self.assertFalse(tz.datetime_exists(dt, tz=AEST)) -class TestEnfold: - def test_enter_fold_default(self): +class TestEnfold: + def test_enter_fold_default(self): dt = tz.enfold(datetime(2020, 1, 19, 3, 32)) - assert dt.fold == 1 + assert dt.fold == 1 - def test_enter_fold(self): + def test_enter_fold(self): dt = tz.enfold(datetime(2020, 1, 19, 3, 32), fold=1) - assert dt.fold == 1 + assert dt.fold == 1 - def test_exit_fold(self): + def test_exit_fold(self): dt = tz.enfold(datetime(2020, 1, 19, 3, 32), fold=0) # Before Python 3.6, dt.fold won't exist if fold is 0. - assert getattr(dt, 'fold', 0) == 0 - - def test_defold(self): - dt = tz.enfold(datetime(2020, 1, 19, 3, 32), fold=1) - - dt2 = tz.enfold(dt, fold=0) - - assert getattr(dt2, 'fold', 0) == 0 - - def test_fold_replace_args(self): - # This test can be dropped when Python < 3.6 is dropped, since it - # is mainly to cover the `replace` method on _DatetimeWithFold - dt = tz.enfold(datetime(1950, 1, 2, 12, 30, 15, 8), fold=1) - - dt2 = dt.replace(1952, 2, 3, 13, 31, 16, 9) - assert dt2 == tz.enfold(datetime(1952, 2, 3, 13, 31, 16, 9), fold=1) - assert dt2.fold == 1 - - def test_fold_replace_exception_duplicate_args(self): - dt = tz.enfold(datetime(1999, 1, 3), fold=1) - - with pytest.raises(TypeError): - dt.replace(1950, year=2000) - - + assert getattr(dt, 'fold', 0) == 0 + + def test_defold(self): + dt = tz.enfold(datetime(2020, 1, 19, 3, 32), fold=1) + + dt2 = tz.enfold(dt, fold=0) + + assert getattr(dt2, 'fold', 0) == 0 + + def test_fold_replace_args(self): + # This test can be dropped when Python < 3.6 is dropped, since it + # is mainly to cover the `replace` method on _DatetimeWithFold + dt = tz.enfold(datetime(1950, 1, 2, 12, 30, 15, 8), fold=1) + + dt2 = dt.replace(1952, 2, 3, 13, 31, 16, 9) + assert dt2 == tz.enfold(datetime(1952, 2, 3, 13, 31, 16, 9), fold=1) + assert dt2.fold == 1 + + def test_fold_replace_exception_duplicate_args(self): + dt = tz.enfold(datetime(1999, 1, 3), fold=1) + + with pytest.raises(TypeError): + dt.replace(1950, year=2000) + + @pytest.mark.tz_resolve_imaginary class ImaginaryDateTest(unittest.TestCase): def testCanberraForward(self): @@ -2749,7 +2749,7 @@ def test_resolve_imaginary_ambiguous(dt): datetime(2017, 12, 2, 12, 30, tzinfo=tz.gettz('America/New_York')), datetime(2018, 12, 2, 9, 30, tzinfo=tz.gettz('Europe/London')), datetime(2017, 6, 2, 16, 30, tzinfo=tz.gettz('Australia/Sydney')), - datetime(2025, 9, 25, 1, 17, tzinfo=tz.UTC), + datetime(2025, 9, 25, 1, 17, tzinfo=tz.UTC), datetime(2025, 9, 25, 1, 17, tzinfo=tz.tzoffset('EST', -18000)), datetime(2019, 3, 4, tzinfo=None) ]) @@ -2782,7 +2782,7 @@ def __get_kiritimati_resolve_imaginary_test(): return (tzi, ) + dates -resolve_imaginary_tests = [ +resolve_imaginary_tests = [ (tz.gettz('Europe/London'), datetime(2018, 3, 25, 1, 30), datetime(2018, 3, 25, 2, 30)), (tz.gettz('America/New_York'), @@ -2790,20 +2790,20 @@ resolve_imaginary_tests = [ (tz.gettz('Australia/Sydney'), datetime(2014, 10, 5, 2, 0), datetime(2014, 10, 5, 3, 0)), __get_kiritimati_resolve_imaginary_test(), -] - +] -if SUPPORTS_SUB_MINUTE_OFFSETS: - resolve_imaginary_tests.append( - (tz.gettz('Africa/Monrovia'), - datetime(1972, 1, 7, 0, 30), datetime(1972, 1, 7, 1, 14, 30))) +if SUPPORTS_SUB_MINUTE_OFFSETS: + resolve_imaginary_tests.append( + (tz.gettz('Africa/Monrovia'), + datetime(1972, 1, 7, 0, 30), datetime(1972, 1, 7, 1, 14, 30))) + @pytest.mark.tz_resolve_imaginary -@pytest.mark.parametrize('tzi, dt, dt_exp', resolve_imaginary_tests) -def test_resolve_imaginary(tzi, dt, dt_exp): - dt = dt.replace(tzinfo=tzi) - dt_exp = dt_exp.replace(tzinfo=tzi) +@pytest.mark.parametrize('tzi, dt, dt_exp', resolve_imaginary_tests) +def test_resolve_imaginary(tzi, dt, dt_exp): + dt = dt.replace(tzinfo=tzi) + dt_exp = dt_exp.replace(tzinfo=tzi) dt_r = tz.resolve_imaginary(dt) assert dt_r == dt_exp diff --git a/contrib/python/dateutil/dateutil/test/test_utils.py b/contrib/python/dateutil/dateutil/test/test_utils.py index fe1bfdcb84..e955cfd05d 100644 --- a/contrib/python/dateutil/dateutil/test/test_utils.py +++ b/contrib/python/dateutil/dateutil/test/test_utils.py @@ -4,7 +4,7 @@ from datetime import timedelta, datetime from dateutil import tz from dateutil import utils -from dateutil.tz import UTC +from dateutil.tz import UTC from dateutil.utils import within_delta from freezegun import freeze_time @@ -12,41 +12,41 @@ from freezegun import freeze_time NYC = tz.gettz("America/New_York") -@freeze_time(datetime(2014, 12, 15, 1, 21, 33, 4003)) -def test_utils_today(): - assert utils.today() == datetime(2014, 12, 15, 0, 0, 0) +@freeze_time(datetime(2014, 12, 15, 1, 21, 33, 4003)) +def test_utils_today(): + assert utils.today() == datetime(2014, 12, 15, 0, 0, 0) -@freeze_time(datetime(2014, 12, 15, 12), tz_offset=5) -def test_utils_today_tz_info(): - assert utils.today(NYC) == datetime(2014, 12, 15, 0, 0, 0, tzinfo=NYC) +@freeze_time(datetime(2014, 12, 15, 12), tz_offset=5) +def test_utils_today_tz_info(): + assert utils.today(NYC) == datetime(2014, 12, 15, 0, 0, 0, tzinfo=NYC) -@freeze_time(datetime(2014, 12, 15, 23), tz_offset=5) -def test_utils_today_tz_info_different_day(): - assert utils.today(UTC) == datetime(2014, 12, 16, 0, 0, 0, tzinfo=UTC) +@freeze_time(datetime(2014, 12, 15, 23), tz_offset=5) +def test_utils_today_tz_info_different_day(): + assert utils.today(UTC) == datetime(2014, 12, 16, 0, 0, 0, tzinfo=UTC) -def test_utils_default_tz_info_naive(): - dt = datetime(2014, 9, 14, 9, 30) - assert utils.default_tzinfo(dt, NYC).tzinfo is NYC +def test_utils_default_tz_info_naive(): + dt = datetime(2014, 9, 14, 9, 30) + assert utils.default_tzinfo(dt, NYC).tzinfo is NYC -def test_utils_default_tz_info_aware(): - dt = datetime(2014, 9, 14, 9, 30, tzinfo=UTC) - assert utils.default_tzinfo(dt, NYC).tzinfo is UTC - - -def test_utils_within_delta(): - d1 = datetime(2016, 1, 1, 12, 14, 1, 9) - d2 = d1.replace(microsecond=15) - - assert within_delta(d1, d2, timedelta(seconds=1)) - assert not within_delta(d1, d2, timedelta(microseconds=1)) - - -def test_utils_within_delta_with_negative_delta(): - d1 = datetime(2016, 1, 1) - d2 = datetime(2015, 12, 31) - - assert within_delta(d2, d1, timedelta(days=-1)) +def test_utils_default_tz_info_aware(): + dt = datetime(2014, 9, 14, 9, 30, tzinfo=UTC) + assert utils.default_tzinfo(dt, NYC).tzinfo is UTC + + +def test_utils_within_delta(): + d1 = datetime(2016, 1, 1, 12, 14, 1, 9) + d2 = d1.replace(microsecond=15) + + assert within_delta(d1, d2, timedelta(seconds=1)) + assert not within_delta(d1, d2, timedelta(microseconds=1)) + + +def test_utils_within_delta_with_negative_delta(): + d1 = datetime(2016, 1, 1) + d2 = datetime(2015, 12, 31) + + assert within_delta(d2, d1, timedelta(days=-1)) diff --git a/contrib/python/dateutil/dateutil/tz/_common.py b/contrib/python/dateutil/dateutil/tz/_common.py index e6ac118315..c309591ec7 100644 --- a/contrib/python/dateutil/dateutil/tz/_common.py +++ b/contrib/python/dateutil/dateutil/tz/_common.py @@ -1,4 +1,4 @@ -from six import PY2 +from six import PY2 from functools import wraps @@ -16,18 +16,18 @@ def tzname_in_python2(namefunc): tzname() API changed in Python 3. It used to return bytes, but was changed to unicode strings """ - if PY2: - @wraps(namefunc) - def adjust_encoding(*args, **kwargs): - name = namefunc(*args, **kwargs) - if name is not None: - name = name.encode() + if PY2: + @wraps(namefunc) + def adjust_encoding(*args, **kwargs): + name = namefunc(*args, **kwargs) + if name is not None: + name = name.encode() - return name + return name - return adjust_encoding - else: - return namefunc + return adjust_encoding + else: + return namefunc # The following is adapted from Alexander Belopolsky's tz library @@ -212,7 +212,7 @@ class _tzinfo(tzinfo): Since this is the one time that we *know* we have an unambiguous datetime object, we take this opportunity to determine whether the datetime is ambiguous and in a "fold" state (e.g. if it's the first - occurrence, chronologically, of the ambiguous datetime). + occurrence, chronologically, of the ambiguous datetime). :param dt: A timezone-aware :class:`datetime.datetime` object. @@ -250,7 +250,7 @@ class _tzinfo(tzinfo): Since this is the one time that we *know* we have an unambiguous datetime object, we take this opportunity to determine whether the datetime is ambiguous and in a "fold" state (e.g. if it's the first - occurrence, chronologically, of the ambiguous datetime). + occurrence, chronologically, of the ambiguous datetime). :param dt: A timezone-aware :class:`datetime.datetime` object. diff --git a/contrib/python/dateutil/dateutil/tz/_factories.py b/contrib/python/dateutil/dateutil/tz/_factories.py index f8a65891a0..737aa95e0f 100644 --- a/contrib/python/dateutil/dateutil/tz/_factories.py +++ b/contrib/python/dateutil/dateutil/tz/_factories.py @@ -1,10 +1,10 @@ from datetime import timedelta -import weakref -from collections import OrderedDict - -from six.moves import _thread +import weakref +from collections import OrderedDict +from six.moves import _thread + class _TzSingleton(type): def __init__(cls, *args, **kwargs): cls.__instance = None @@ -15,7 +15,7 @@ class _TzSingleton(type): cls.__instance = super(_TzSingleton, cls).__call__() return cls.__instance - + class _TzFactory(type): def instance(cls, *args, **kwargs): """Alternate constructor that returns a fresh instance""" @@ -24,57 +24,57 @@ class _TzFactory(type): class _TzOffsetFactory(_TzFactory): def __init__(cls, *args, **kwargs): - cls.__instances = weakref.WeakValueDictionary() - cls.__strong_cache = OrderedDict() - cls.__strong_cache_size = 8 - - cls._cache_lock = _thread.allocate_lock() + cls.__instances = weakref.WeakValueDictionary() + cls.__strong_cache = OrderedDict() + cls.__strong_cache_size = 8 + + cls._cache_lock = _thread.allocate_lock() def __call__(cls, name, offset): - if isinstance(offset, timedelta): - key = (name, offset.total_seconds()) - else: - key = (name, offset) - - instance = cls.__instances.get(key, None) - if instance is None: - instance = cls.__instances.setdefault(key, - cls.instance(name, offset)) - - # This lock may not be necessary in Python 3. See GH issue #901 - with cls._cache_lock: - cls.__strong_cache[key] = cls.__strong_cache.pop(key, instance) - - # Remove an item if the strong cache is overpopulated - if len(cls.__strong_cache) > cls.__strong_cache_size: - cls.__strong_cache.popitem(last=False) - + if isinstance(offset, timedelta): + key = (name, offset.total_seconds()) + else: + key = (name, offset) + + instance = cls.__instances.get(key, None) + if instance is None: + instance = cls.__instances.setdefault(key, + cls.instance(name, offset)) + + # This lock may not be necessary in Python 3. See GH issue #901 + with cls._cache_lock: + cls.__strong_cache[key] = cls.__strong_cache.pop(key, instance) + + # Remove an item if the strong cache is overpopulated + if len(cls.__strong_cache) > cls.__strong_cache_size: + cls.__strong_cache.popitem(last=False) + return instance class _TzStrFactory(_TzFactory): def __init__(cls, *args, **kwargs): - cls.__instances = weakref.WeakValueDictionary() - cls.__strong_cache = OrderedDict() - cls.__strong_cache_size = 8 - - cls.__cache_lock = _thread.allocate_lock() + cls.__instances = weakref.WeakValueDictionary() + cls.__strong_cache = OrderedDict() + cls.__strong_cache_size = 8 + cls.__cache_lock = _thread.allocate_lock() + def __call__(cls, s, posix_offset=False): - key = (s, posix_offset) - instance = cls.__instances.get(key, None) - - if instance is None: - instance = cls.__instances.setdefault(key, - cls.instance(s, posix_offset)) - - # This lock may not be necessary in Python 3. See GH issue #901 - with cls.__cache_lock: - cls.__strong_cache[key] = cls.__strong_cache.pop(key, instance) - - # Remove an item if the strong cache is overpopulated - if len(cls.__strong_cache) > cls.__strong_cache_size: - cls.__strong_cache.popitem(last=False) - + key = (s, posix_offset) + instance = cls.__instances.get(key, None) + + if instance is None: + instance = cls.__instances.setdefault(key, + cls.instance(s, posix_offset)) + + # This lock may not be necessary in Python 3. See GH issue #901 + with cls.__cache_lock: + cls.__strong_cache[key] = cls.__strong_cache.pop(key, instance) + + # Remove an item if the strong cache is overpopulated + if len(cls.__strong_cache) > cls.__strong_cache_size: + cls.__strong_cache.popitem(last=False) + return instance - + diff --git a/contrib/python/dateutil/dateutil/tz/tz.py b/contrib/python/dateutil/dateutil/tz/tz.py index c67f56d465..00b0984f87 100644 --- a/contrib/python/dateutil/dateutil/tz/tz.py +++ b/contrib/python/dateutil/dateutil/tz/tz.py @@ -13,8 +13,8 @@ import time import sys import os import bisect -import weakref -from collections import OrderedDict +import weakref +from collections import OrderedDict import six from six import string_types @@ -30,9 +30,9 @@ try: except ImportError: tzwin = tzwinlocal = None -# For warning about rounding tzinfo -from warnings import warn - +# For warning about rounding tzinfo +from warnings import warn + ZERO = datetime.timedelta(0) EPOCH = datetime.datetime.utcfromtimestamp(0) EPOCHORDINAL = EPOCH.toordinal() @@ -123,12 +123,12 @@ class tzutc(datetime.tzinfo): __reduce__ = object.__reduce__ -#: Convenience constant providing a :class:`tzutc()` instance -#: -#: .. versionadded:: 2.7.0 -UTC = tzutc() - - +#: Convenience constant providing a :class:`tzutc()` instance +#: +#: .. versionadded:: 2.7.0 +UTC = tzutc() + + @six.add_metaclass(_TzOffsetFactory) class tzoffset(datetime.tzinfo): """ @@ -149,8 +149,8 @@ class tzoffset(datetime.tzinfo): except (TypeError, AttributeError): pass - self._offset = datetime.timedelta(seconds=_get_supported_offset(offset)) - + self._offset = datetime.timedelta(seconds=_get_supported_offset(offset)) + def utcoffset(self, dt): return self._offset @@ -385,7 +385,7 @@ class _tzfile(object): class tzfile(_tzinfo): """ - This is a ``tzinfo`` subclass that allows one to use the ``tzfile(5)`` + This is a ``tzinfo`` subclass that allows one to use the ``tzfile(5)`` format timezone files to extract current and historical zone information. :param fileobj: @@ -472,7 +472,7 @@ class tzfile(_tzinfo): if fileobj is not None: if not file_opened_here: - fileobj = _nullcontext(fileobj) + fileobj = _nullcontext(fileobj) with fileobj as file_stream: tzobj = self._read_tzfile(file_stream) @@ -612,7 +612,7 @@ class tzfile(_tzinfo): out.ttinfo_list = [] for i in range(typecnt): gmtoff, isdst, abbrind = ttinfo[i] - gmtoff = _get_supported_offset(gmtoff) + gmtoff = _get_supported_offset(gmtoff) tti = _ttinfo() tti.offset = gmtoff tti.dstoffset = datetime.timedelta(0) @@ -664,45 +664,45 @@ class tzfile(_tzinfo): # isgmt are off, so it should be in wall time. OTOH, it's # always in gmt time. Let me know if you have comments # about this. - lastdst = None - lastoffset = None - lastdstoffset = None - lastbaseoffset = None + lastdst = None + lastoffset = None + lastdstoffset = None + lastbaseoffset = None out.trans_list = [] - + for i, tti in enumerate(out.trans_idx): - offset = tti.offset - dstoffset = 0 - - if lastdst is not None: - if tti.isdst: - if not lastdst: - dstoffset = offset - lastoffset - - if not dstoffset and lastdstoffset: - dstoffset = lastdstoffset - - tti.dstoffset = datetime.timedelta(seconds=dstoffset) - lastdstoffset = dstoffset - - # If a time zone changes its base offset during a DST transition, - # then you need to adjust by the previous base offset to get the - # transition time in local time. Otherwise you use the current - # base offset. Ideally, I would have some mathematical proof of - # why this is true, but I haven't really thought about it enough. - baseoffset = offset - dstoffset - adjustment = baseoffset - if (lastbaseoffset is not None and baseoffset != lastbaseoffset - and tti.isdst != lastdst): - # The base DST has changed - adjustment = lastbaseoffset - - lastdst = tti.isdst - lastoffset = offset - lastbaseoffset = baseoffset - - out.trans_list.append(out.trans_list_utc[i] + adjustment) - + offset = tti.offset + dstoffset = 0 + + if lastdst is not None: + if tti.isdst: + if not lastdst: + dstoffset = offset - lastoffset + + if not dstoffset and lastdstoffset: + dstoffset = lastdstoffset + + tti.dstoffset = datetime.timedelta(seconds=dstoffset) + lastdstoffset = dstoffset + + # If a time zone changes its base offset during a DST transition, + # then you need to adjust by the previous base offset to get the + # transition time in local time. Otherwise you use the current + # base offset. Ideally, I would have some mathematical proof of + # why this is true, but I haven't really thought about it enough. + baseoffset = offset - dstoffset + adjustment = baseoffset + if (lastbaseoffset is not None and baseoffset != lastbaseoffset + and tti.isdst != lastdst): + # The base DST has changed + adjustment = lastbaseoffset + + lastdst = tti.isdst + lastoffset = offset + lastbaseoffset = baseoffset + + out.trans_list.append(out.trans_list_utc[i] + adjustment) + out.trans_idx = tuple(out.trans_idx) out.trans_list = tuple(out.trans_list) out.trans_list_utc = tuple(out.trans_list_utc) @@ -1271,7 +1271,7 @@ class tzical(object): fileobj = open(fileobj, 'r') else: self._s = getattr(fileobj, 'name', repr(fileobj)) - fileobj = _nullcontext(fileobj) + fileobj = _nullcontext(fileobj) self._vtz = {} @@ -1544,9 +1544,9 @@ def __get_gettz(): """ def __init__(self): - self.__instances = weakref.WeakValueDictionary() - self.__strong_cache_size = 8 - self.__strong_cache = OrderedDict() + self.__instances = weakref.WeakValueDictionary() + self.__strong_cache_size = 8 + self.__strong_cache = OrderedDict() self._cache_lock = _thread.allocate_lock() def __call__(self, name=None): @@ -1555,37 +1555,37 @@ def __get_gettz(): if rv is None: rv = self.nocache(name=name) - if not (name is None - or isinstance(rv, tzlocal_classes) - or rv is None): + if not (name is None + or isinstance(rv, tzlocal_classes) + or rv is None): # tzlocal is slightly more complicated than the other # time zone providers because it depends on environment # at construction time, so don't cache that. - # - # We also cannot store weak references to None, so we - # will also not store that. + # + # We also cannot store weak references to None, so we + # will also not store that. self.__instances[name] = rv - else: - # No need for strong caching, return immediately - return rv - - self.__strong_cache[name] = self.__strong_cache.pop(name, rv) - - if len(self.__strong_cache) > self.__strong_cache_size: - self.__strong_cache.popitem(last=False) - + else: + # No need for strong caching, return immediately + return rv + + self.__strong_cache[name] = self.__strong_cache.pop(name, rv) + + if len(self.__strong_cache) > self.__strong_cache_size: + self.__strong_cache.popitem(last=False) + return rv - def set_cache_size(self, size): - with self._cache_lock: - self.__strong_cache_size = size - while len(self.__strong_cache) > size: - self.__strong_cache.popitem(last=False) - + def set_cache_size(self, size): + with self._cache_lock: + self.__strong_cache_size = size + while len(self.__strong_cache) > size: + self.__strong_cache.popitem(last=False) + def cache_clear(self): with self._cache_lock: - self.__instances = weakref.WeakValueDictionary() - self.__strong_cache.clear() + self.__instances = weakref.WeakValueDictionary() + self.__strong_cache.clear() @staticmethod def nocache(name=None): @@ -1596,7 +1596,7 @@ def __get_gettz(): name = os.environ["TZ"] except KeyError: pass - if name is None or name in ("", ":"): + if name is None or name in ("", ":"): for filepath in TZFILES: if not os.path.isabs(filepath): filename = filepath @@ -1615,15 +1615,15 @@ def __get_gettz(): else: tz = tzlocal() else: - try: - if name.startswith(":"): - name = name[1:] - except TypeError as e: - if isinstance(name, bytes): - new_msg = "gettz argument should be str, not bytes" - six.raise_from(TypeError(new_msg), e) - else: - raise + try: + if name.startswith(":"): + name = name[1:] + except TypeError as e: + if isinstance(name, bytes): + new_msg = "gettz argument should be str, not bytes" + six.raise_from(TypeError(new_msg), e) + else: + raise if os.path.isabs(name): if os.path.isfile(name): tz = tzfile(name) @@ -1646,8 +1646,8 @@ def __get_gettz(): if tzwin is not None: try: tz = tzwin(name) - except (WindowsError, UnicodeEncodeError): - # UnicodeEncodeError is for Python 2.7 compat + except (WindowsError, UnicodeEncodeError): + # UnicodeEncodeError is for Python 2.7 compat tz = None if not tz: @@ -1668,7 +1668,7 @@ def __get_gettz(): break else: if name in ("GMT", "UTC"): - tz = UTC + tz = UTC elif name in time.tzname: tz = tzlocal() return tz @@ -1708,7 +1708,7 @@ def datetime_exists(dt, tz=None): # This is essentially a test of whether or not the datetime can survive # a round trip to UTC. - dt_rt = dt.replace(tzinfo=tz).astimezone(UTC).astimezone(tz) + dt_rt = dt.replace(tzinfo=tz).astimezone(UTC).astimezone(tz) dt_rt = dt_rt.replace(tzinfo=None) return dt == dt_rt @@ -1814,36 +1814,36 @@ def _datetime_to_timestamp(dt): return (dt.replace(tzinfo=None) - EPOCH).total_seconds() -if sys.version_info >= (3, 6): - def _get_supported_offset(second_offset): - return second_offset -else: - def _get_supported_offset(second_offset): - # For python pre-3.6, round to full-minutes if that's not the case. - # Python's datetime doesn't accept sub-minute timezones. Check - # http://python.org/sf/1447945 or https://bugs.python.org/issue5288 - # for some information. - old_offset = second_offset - calculated_offset = 60 * ((second_offset + 30) // 60) - return calculated_offset - - -try: - # Python 3.7 feature - from contextlib import nullcontext as _nullcontext -except ImportError: - class _nullcontext(object): - """ - Class for wrapping contexts so that they are passed through in a - with statement. - """ - def __init__(self, context): - self.context = context - - def __enter__(self): - return self.context - - def __exit__(*args, **kwargs): - pass - +if sys.version_info >= (3, 6): + def _get_supported_offset(second_offset): + return second_offset +else: + def _get_supported_offset(second_offset): + # For python pre-3.6, round to full-minutes if that's not the case. + # Python's datetime doesn't accept sub-minute timezones. Check + # http://python.org/sf/1447945 or https://bugs.python.org/issue5288 + # for some information. + old_offset = second_offset + calculated_offset = 60 * ((second_offset + 30) // 60) + return calculated_offset + + +try: + # Python 3.7 feature + from contextlib import nullcontext as _nullcontext +except ImportError: + class _nullcontext(object): + """ + Class for wrapping contexts so that they are passed through in a + with statement. + """ + def __init__(self, context): + self.context = context + + def __enter__(self): + return self.context + + def __exit__(*args, **kwargs): + pass + # vim:ts=4:sw=4:et diff --git a/contrib/python/dateutil/dateutil/tz/win.py b/contrib/python/dateutil/dateutil/tz/win.py index cde07ba792..80931b7c12 100644 --- a/contrib/python/dateutil/dateutil/tz/win.py +++ b/contrib/python/dateutil/dateutil/tz/win.py @@ -1,11 +1,11 @@ -# -*- coding: utf-8 -*- -""" -This module provides an interface to the native time zone data on Windows, -including :py:class:`datetime.tzinfo` implementations. - -Attempting to import this module on a non-Windows platform will raise an -:py:obj:`ImportError`. -""" +# -*- coding: utf-8 -*- +""" +This module provides an interface to the native time zone data on Windows, +including :py:class:`datetime.tzinfo` implementations. + +Attempting to import this module on a non-Windows platform will raise an +:py:obj:`ImportError`. +""" # This code was originally contributed by Jeffrey Harris. import datetime import struct @@ -47,7 +47,7 @@ TZKEYNAME = _settzkeyname() class tzres(object): """ - Class for accessing ``tzres.dll``, which contains timezone name related + Class for accessing ``tzres.dll``, which contains timezone name related resources. .. versionadded:: 2.5.0 @@ -80,10 +80,10 @@ class tzres(object): :param offset: A positive integer value referring to a string from the tzres dll. - .. note:: - + .. note:: + Offsets found in the registry are generally of the form - ``@tzres.dll,-114``. The offset in this case is 114, not -114. + ``@tzres.dll,-114``. The offset in this case is 114, not -114. """ resource = self.p_wchar() @@ -155,9 +155,9 @@ class tzwinbase(tzrangebase): return result def display(self): - """ - Return the display name of the time zone. - """ + """ + Return the display name of the time zone. + """ return self._display def transitions(self, year): @@ -200,18 +200,18 @@ class tzwinbase(tzrangebase): class tzwin(tzwinbase): - """ - Time zone object created from the zone info in the Windows registry - - These are similar to :py:class:`dateutil.tz.tzrange` objects in that - the time zone data is provided in the format of a single offset rule - for either 0 or 2 time zone transitions per year. - - :param: name - The name of a Windows time zone key, e.g. "Eastern Standard Time". - The full list of keys can be retrieved with :func:`tzwin.list`. - """ - + """ + Time zone object created from the zone info in the Windows registry + + These are similar to :py:class:`dateutil.tz.tzrange` objects in that + the time zone data is provided in the format of a single offset rule + for either 0 or 2 time zone transitions per year. + + :param: name + The name of a Windows time zone key, e.g. "Eastern Standard Time". + The full list of keys can be retrieved with :func:`tzwin.list`. + """ + def __init__(self, name): self._name = name @@ -257,22 +257,22 @@ class tzwin(tzwinbase): class tzwinlocal(tzwinbase): - """ - Class representing the local time zone information in the Windows registry - - While :class:`dateutil.tz.tzlocal` makes system calls (via the :mod:`time` - module) to retrieve time zone information, ``tzwinlocal`` retrieves the - rules directly from the Windows registry and creates an object like - :class:`dateutil.tz.tzwin`. - - Because Windows does not have an equivalent of :func:`time.tzset`, on - Windows, :class:`dateutil.tz.tzlocal` instances will always reflect the - time zone settings *at the time that the process was started*, meaning - changes to the machine's time zone settings during the run of a program - on Windows will **not** be reflected by :class:`dateutil.tz.tzlocal`. - Because ``tzwinlocal`` reads the registry directly, it is unaffected by - this issue. - """ + """ + Class representing the local time zone information in the Windows registry + + While :class:`dateutil.tz.tzlocal` makes system calls (via the :mod:`time` + module) to retrieve time zone information, ``tzwinlocal`` retrieves the + rules directly from the Windows registry and creates an object like + :class:`dateutil.tz.tzwin`. + + Because Windows does not have an equivalent of :func:`time.tzset`, on + Windows, :class:`dateutil.tz.tzlocal` instances will always reflect the + time zone settings *at the time that the process was started*, meaning + changes to the machine's time zone settings during the run of a program + on Windows will **not** be reflected by :class:`dateutil.tz.tzlocal`. + Because ``tzwinlocal`` reads the registry directly, it is unaffected by + this issue. + """ def __init__(self): with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: with winreg.OpenKey(handle, TZLOCALKEYNAME) as tzlocalkey: diff --git a/contrib/python/dateutil/dateutil/utils.py b/contrib/python/dateutil/dateutil/utils.py index dd2d245a0b..af10d21688 100644 --- a/contrib/python/dateutil/dateutil/utils.py +++ b/contrib/python/dateutil/dateutil/utils.py @@ -28,7 +28,7 @@ def today(tzinfo=None): def default_tzinfo(dt, tzinfo): """ - Sets the ``tzinfo`` parameter on naive datetimes only + Sets the ``tzinfo`` parameter on naive datetimes only This is useful for example when you are provided a datetime that may have either an implicit or explicit time zone, such as when parsing a time zone @@ -63,7 +63,7 @@ def default_tzinfo(dt, tzinfo): def within_delta(dt1, dt2, delta): """ - Useful for comparing two datetimes that may have a negligible difference + Useful for comparing two datetimes that may have a negligible difference to be considered equal. """ delta = abs(delta) diff --git a/contrib/python/dateutil/dateutil/zoneinfo/__init__.py b/contrib/python/dateutil/dateutil/zoneinfo/__init__.py index 34f11ad66c..7759f2ce6b 100644 --- a/contrib/python/dateutil/dateutil/zoneinfo/__init__.py +++ b/contrib/python/dateutil/dateutil/zoneinfo/__init__.py @@ -3,7 +3,7 @@ import warnings import json from tarfile import TarFile -from pkgutil import get_data +from pkgutil import get_data from io import BytesIO from dateutil.tz import tzfile as _tzfile @@ -21,7 +21,7 @@ class tzfile(_tzfile): def getzoneinfofile_stream(): try: - return BytesIO(get_data(__name__, ZONEFILENAME)) + return BytesIO(get_data(__name__, ZONEFILENAME)) except IOError as e: # TODO switch to FileNotFoundError? warnings.warn("I/O error({0}): {1}".format(e.errno, e.strerror)) return None diff --git a/contrib/python/dateutil/dateutil/zoneinfo/rebuild.py b/contrib/python/dateutil/dateutil/zoneinfo/rebuild.py index 684c6586f0..86e86e37d6 100644 --- a/contrib/python/dateutil/dateutil/zoneinfo/rebuild.py +++ b/contrib/python/dateutil/dateutil/zoneinfo/rebuild.py @@ -3,7 +3,7 @@ import os import tempfile import shutil import json -from subprocess import check_call, check_output +from subprocess import check_call, check_output from tarfile import TarFile from dateutil.zoneinfo import METADATA_FN, ZONEFILENAME @@ -23,9 +23,9 @@ def rebuild(filename, tag=None, format="gz", zonegroups=[], metadata=None): for name in zonegroups: tf.extract(name, tmpdir) filepaths = [os.path.join(tmpdir, n) for n in zonegroups] - - _run_zic(zonedir, filepaths) - + + _run_zic(zonedir, filepaths) + # write metadata file with open(os.path.join(zonedir, METADATA_FN), 'w') as f: json.dump(metadata, f, indent=4, sort_keys=True) @@ -38,30 +38,30 @@ def rebuild(filename, tag=None, format="gz", zonegroups=[], metadata=None): shutil.rmtree(tmpdir) -def _run_zic(zonedir, filepaths): - """Calls the ``zic`` compiler in a compatible way to get a "fat" binary. - - Recent versions of ``zic`` default to ``-b slim``, while older versions - don't even have the ``-b`` option (but default to "fat" binaries). The - current version of dateutil does not support Version 2+ TZif files, which - causes problems when used in conjunction with "slim" binaries, so this - function is used to ensure that we always get a "fat" binary. - """ - - try: - help_text = check_output(["zic", "--help"]) - except OSError as e: - _print_on_nosuchfile(e) - raise - - if b"-b " in help_text: - bloat_args = ["-b", "fat"] - else: - bloat_args = [] - - check_call(["zic"] + bloat_args + ["-d", zonedir] + filepaths) - - +def _run_zic(zonedir, filepaths): + """Calls the ``zic`` compiler in a compatible way to get a "fat" binary. + + Recent versions of ``zic`` default to ``-b slim``, while older versions + don't even have the ``-b`` option (but default to "fat" binaries). The + current version of dateutil does not support Version 2+ TZif files, which + causes problems when used in conjunction with "slim" binaries, so this + function is used to ensure that we always get a "fat" binary. + """ + + try: + help_text = check_output(["zic", "--help"]) + except OSError as e: + _print_on_nosuchfile(e) + raise + + if b"-b " in help_text: + bloat_args = ["-b", "fat"] + else: + bloat_args = [] + + check_call(["zic"] + bloat_args + ["-d", zonedir] + filepaths) + + def _print_on_nosuchfile(e): """Print helpful troubleshooting message diff --git a/contrib/python/dateutil/tests/ya.make b/contrib/python/dateutil/tests/ya.make index 93c811e26e..bcf5b66692 100644 --- a/contrib/python/dateutil/tests/ya.make +++ b/contrib/python/dateutil/tests/ya.make @@ -1,39 +1,39 @@ -PY23_TEST() - +PY23_TEST() + OWNER(g:python-contrib) -PEERDIR( - contrib/python/dateutil - contrib/python/freezegun - contrib/python/hypothesis -) - -ENV(LC_ALL=ru_RU.UTF-8) -ENV(LANG=ru_RU.UTF-8) -# because we cannot change TZ in arcadia CI -ENV(DATEUTIL_MAY_NOT_CHANGE_TZ_VAR=1) - -SRCDIR(contrib/python/dateutil/dateutil/test) - -TEST_SRCS( - property/test_isoparse_prop.py - property/test_parser_prop.py - # property/test_tz_prop.py - __init__.py - _common.py - conftest.py - test_easter.py - test_import_star.py - test_imports.py - test_internals.py - test_isoparser.py - test_parser.py - test_relativedelta.py - test_rrule.py - test_tz.py - test_utils.py -) - -NO_LINT() - -END() +PEERDIR( + contrib/python/dateutil + contrib/python/freezegun + contrib/python/hypothesis +) + +ENV(LC_ALL=ru_RU.UTF-8) +ENV(LANG=ru_RU.UTF-8) +# because we cannot change TZ in arcadia CI +ENV(DATEUTIL_MAY_NOT_CHANGE_TZ_VAR=1) + +SRCDIR(contrib/python/dateutil/dateutil/test) + +TEST_SRCS( + property/test_isoparse_prop.py + property/test_parser_prop.py + # property/test_tz_prop.py + __init__.py + _common.py + conftest.py + test_easter.py + test_import_star.py + test_imports.py + test_internals.py + test_isoparser.py + test_parser.py + test_relativedelta.py + test_rrule.py + test_tz.py + test_utils.py +) + +NO_LINT() + +END() diff --git a/contrib/python/dateutil/ya.make b/contrib/python/dateutil/ya.make index 0c4102c505..b131358690 100644 --- a/contrib/python/dateutil/ya.make +++ b/contrib/python/dateutil/ya.make @@ -1,19 +1,19 @@ -# Generated by devtools/yamaker (pypi). - -PY23_LIBRARY() +# Generated by devtools/yamaker (pypi). + +PY23_LIBRARY() OWNER(g:python-contrib) -VERSION(2.8.2) - -LICENSE(BSD-3-Clause) +VERSION(2.8.2) +LICENSE(BSD-3-Clause) + PEERDIR( contrib/python/six ) -NO_LINT() - +NO_LINT() + NO_CHECK_IMPORTS( dateutil.tz.win dateutil.tzwin @@ -41,15 +41,15 @@ PY_SRCS( dateutil/zoneinfo/rebuild.py ) -RESOURCE_FILES( - PREFIX contrib/python/dateutil/ - .dist-info/METADATA - .dist-info/top_level.txt - dateutil/zoneinfo/dateutil-zoneinfo.tar.gz +RESOURCE_FILES( + PREFIX contrib/python/dateutil/ + .dist-info/METADATA + .dist-info/top_level.txt + dateutil/zoneinfo/dateutil-zoneinfo.tar.gz ) END() - -RECURSE_FOR_TESTS( - tests -) + +RECURSE_FOR_TESTS( + tests +) |