From c0cc4a748b84d618670989b545638135bba7991c Mon Sep 17 00:00:00 2001 From: Victor Lin <13424970+victorlin@users.noreply.github.com> Date: Fri, 27 Jan 2023 16:39:06 -0800 Subject: [PATCH 1/2] Consolidate date code to one directory Instead of having most functions in dates.py, an exception class in errors.py, and a helper class in util_support/date_disambiguator.py, this puts everything under one directory. No functional changes, just moving things around. --- augur/{dates.py => dates/__init__.py} | 5 +++-- .../{util_support => dates}/date_disambiguator.py | 2 +- augur/dates/errors.py | 11 +++++++++++ augur/errors.py | 14 -------------- ...ator.rst => augur.dates.date_disambiguator.rst} | 4 ++-- docs/api/developer/augur.dates.errors.rst | 7 +++++++ docs/api/developer/augur.dates.rst | 5 +++++ docs/api/developer/augur.util_support.rst | 1 - .../test_date_disambiguator.py | 6 +++--- tests/{ => dates}/test_dates.py | 0 10 files changed, 32 insertions(+), 23 deletions(-) rename augur/{dates.py => dates/__init__.py} (97%) rename augur/{util_support => dates}/date_disambiguator.py (99%) create mode 100644 augur/dates/errors.py rename docs/api/developer/{augur.util_support.date_disambiguator.rst => augur.dates.date_disambiguator.rst} (50%) create mode 100644 docs/api/developer/augur.dates.errors.rst rename tests/{util_support => dates}/test_date_disambiguator.py (94%) rename tests/{ => dates}/test_dates.py (100%) diff --git a/augur/dates.py b/augur/dates/__init__.py similarity index 97% rename from augur/dates.py rename to augur/dates/__init__.py index 382336537..b83e760ce 100644 --- a/augur/dates.py +++ b/augur/dates/__init__.py @@ -5,9 +5,10 @@ import pandas as pd import re import treetime.utils -from .errors import AugurError, InvalidDate +from augur.errors import AugurError +from .errors import InvalidDate -from augur.util_support.date_disambiguator import DateDisambiguator +from .date_disambiguator import DateDisambiguator SUPPORTED_DATE_HELP_TEXT = dedent("""\ 1. an Augur-style numeric date with the year as the integer part (e.g. 2020.42) or diff --git a/augur/util_support/date_disambiguator.py b/augur/dates/date_disambiguator.py similarity index 99% rename from augur/util_support/date_disambiguator.py rename to augur/dates/date_disambiguator.py index 81ccfe9dc..0b5b8c5eb 100644 --- a/augur/util_support/date_disambiguator.py +++ b/augur/dates/date_disambiguator.py @@ -3,7 +3,7 @@ import functools import re -from augur.errors import InvalidDate +from .errors import InvalidDate def tuple_to_date(year, month, day): diff --git a/augur/dates/errors.py b/augur/dates/errors.py new file mode 100644 index 000000000..d7619f604 --- /dev/null +++ b/augur/dates/errors.py @@ -0,0 +1,11 @@ +class InvalidDate(Exception): + """Custom exception class to handle dates in unsupported formats.""" + + def __init__(self, date, message): + """Initialize the error with the culprit date string and a meaningful message.""" + self.date = date + self.message = message + + def __str__(self): + """Return a human-readable summary of the error.""" + return f"Invalid date '{self.date}': {self.message}" diff --git a/augur/errors.py b/augur/errors.py index d353f0014..3d0ae8a18 100644 --- a/augur/errors.py +++ b/augur/errors.py @@ -1,16 +1,2 @@ class AugurError(Exception): pass - - -# TODO: Move this to something like dates/errors.py -class InvalidDate(Exception): - """Custom exception class to handle dates in unsupported formats.""" - - def __init__(self, date, message): - """Initialize the error with the culprit date string and a meaningful message.""" - self.date = date - self.message = message - - def __str__(self): - """Return a human-readable summary of the error.""" - return f"Invalid date '{self.date}': {self.message}" diff --git a/docs/api/developer/augur.util_support.date_disambiguator.rst b/docs/api/developer/augur.dates.date_disambiguator.rst similarity index 50% rename from docs/api/developer/augur.util_support.date_disambiguator.rst rename to docs/api/developer/augur.dates.date_disambiguator.rst index ebae8164e..54422268e 100644 --- a/docs/api/developer/augur.util_support.date_disambiguator.rst +++ b/docs/api/developer/augur.dates.date_disambiguator.rst @@ -1,7 +1,7 @@ -augur.util\_support.date\_disambiguator +augur.dates.date\_disambiguator ======================================= -.. automodule:: augur.util_support.date_disambiguator +.. automodule:: augur.dates.date_disambiguator :members: :undoc-members: :show-inheritance: diff --git a/docs/api/developer/augur.dates.errors.rst b/docs/api/developer/augur.dates.errors.rst new file mode 100644 index 000000000..d4da219fc --- /dev/null +++ b/docs/api/developer/augur.dates.errors.rst @@ -0,0 +1,7 @@ +augur.dates.errors +================== + +.. automodule:: augur.dates.errors + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/api/developer/augur.dates.rst b/docs/api/developer/augur.dates.rst index 1e2684513..6a21a1d45 100644 --- a/docs/api/developer/augur.dates.rst +++ b/docs/api/developer/augur.dates.rst @@ -5,3 +5,8 @@ augur.dates :members: :undoc-members: :show-inheritance: + +.. toctree:: + + augur.dates.date_disambiguator + augur.dates.errors diff --git a/docs/api/developer/augur.util_support.rst b/docs/api/developer/augur.util_support.rst index e9fdae55b..0c20d9f1e 100644 --- a/docs/api/developer/augur.util_support.rst +++ b/docs/api/developer/augur.util_support.rst @@ -10,7 +10,6 @@ augur.util\_support augur.util_support.color_parser augur.util_support.color_parser_line - augur.util_support.date_disambiguator augur.util_support.node_data augur.util_support.node_data_file augur.util_support.node_data_reader diff --git a/tests/util_support/test_date_disambiguator.py b/tests/dates/test_date_disambiguator.py similarity index 94% rename from tests/util_support/test_date_disambiguator.py rename to tests/dates/test_date_disambiguator.py index 5a4d7bb51..fb2768acf 100644 --- a/tests/util_support/test_date_disambiguator.py +++ b/tests/dates/test_date_disambiguator.py @@ -1,8 +1,8 @@ import datetime -from augur.errors import InvalidDate -from augur.util_support import date_disambiguator -from augur.util_support.date_disambiguator import DateDisambiguator +from augur.dates import date_disambiguator +from augur.dates.date_disambiguator import DateDisambiguator +from augur.dates.errors import InvalidDate from freezegun import freeze_time import pytest diff --git a/tests/test_dates.py b/tests/dates/test_dates.py similarity index 100% rename from tests/test_dates.py rename to tests/dates/test_dates.py From 82a91fa583371afb2bc38cfd3e4e7b57d04e0000 Mon Sep 17 00:00:00 2001 From: Victor Lin <13424970+victorlin@users.noreply.github.com> Date: Mon, 30 Jan 2023 16:41:58 -0800 Subject: [PATCH 2/2] =?UTF-8?q?Rename=20DateDisambiguator=20=E2=86=92=20Am?= =?UTF-8?q?biguousDate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "DateDisambiguator" is a mouthful, and also uses a verb in a class name which is a bad pattern. Use a noun instead. --- augur/dates/__init__.py | 4 ++-- ...date_disambiguator.py => ambiguous_date.py} | 2 +- ...ator.rst => augur.dates.ambiguous_date.rst} | 4 ++-- docs/api/developer/augur.dates.rst | 2 +- ...disambiguator.py => test_ambiguous_date.py} | 18 +++++++++--------- 5 files changed, 15 insertions(+), 15 deletions(-) rename augur/dates/{date_disambiguator.py => ambiguous_date.py} (99%) rename docs/api/developer/{augur.dates.date_disambiguator.rst => augur.dates.ambiguous_date.rst} (54%) rename tests/dates/{test_date_disambiguator.py => test_ambiguous_date.py} (80%) diff --git a/augur/dates/__init__.py b/augur/dates/__init__.py index b83e760ce..c8969ba19 100644 --- a/augur/dates/__init__.py +++ b/augur/dates/__init__.py @@ -8,7 +8,7 @@ from augur.errors import AugurError from .errors import InvalidDate -from .date_disambiguator import DateDisambiguator +from .ambiguous_date import AmbiguousDate SUPPORTED_DATE_HELP_TEXT = dedent("""\ 1. an Augur-style numeric date with the year as the integer part (e.g. 2020.42) or @@ -115,7 +115,7 @@ def get_numerical_date_from_value(value, fmt=None, min_max_year=None): value = fmt.replace('%Y', value).replace('%m', 'XX').replace('%d', 'XX') if 'XX' in value: try: - ambig_date = DateDisambiguator(value, fmt=fmt, min_max_year=min_max_year).range() + ambig_date = AmbiguousDate(value, fmt=fmt, min_max_year=min_max_year).range() except InvalidDate as error: raise AugurError(str(error)) from error if ambig_date is None or None in ambig_date: diff --git a/augur/dates/date_disambiguator.py b/augur/dates/ambiguous_date.py similarity index 99% rename from augur/dates/date_disambiguator.py rename to augur/dates/ambiguous_date.py index 0b5b8c5eb..525dad257 100644 --- a/augur/dates/date_disambiguator.py +++ b/augur/dates/ambiguous_date.py @@ -38,7 +38,7 @@ def resolve_uncertain_int(uncertain_string, min_or_max): # This was originally from treetime.utils.ambiguous_date_to_date_range. -class DateDisambiguator: +class AmbiguousDate: """Transforms a date string with uncertainty into the range of possible dates.""" def __init__(self, uncertain_date, fmt="%Y-%m-%d", min_max_year=None): diff --git a/docs/api/developer/augur.dates.date_disambiguator.rst b/docs/api/developer/augur.dates.ambiguous_date.rst similarity index 54% rename from docs/api/developer/augur.dates.date_disambiguator.rst rename to docs/api/developer/augur.dates.ambiguous_date.rst index 54422268e..2471f3e8f 100644 --- a/docs/api/developer/augur.dates.date_disambiguator.rst +++ b/docs/api/developer/augur.dates.ambiguous_date.rst @@ -1,7 +1,7 @@ -augur.dates.date\_disambiguator +augur.dates.ambiguous\_date ======================================= -.. automodule:: augur.dates.date_disambiguator +.. automodule:: augur.dates.ambiguous_date :members: :undoc-members: :show-inheritance: diff --git a/docs/api/developer/augur.dates.rst b/docs/api/developer/augur.dates.rst index 6a21a1d45..5f314f3ce 100644 --- a/docs/api/developer/augur.dates.rst +++ b/docs/api/developer/augur.dates.rst @@ -8,5 +8,5 @@ augur.dates .. toctree:: - augur.dates.date_disambiguator + augur.dates.ambiguous_date augur.dates.errors diff --git a/tests/dates/test_date_disambiguator.py b/tests/dates/test_ambiguous_date.py similarity index 80% rename from tests/dates/test_date_disambiguator.py rename to tests/dates/test_ambiguous_date.py index fb2768acf..ce8f90370 100644 --- a/tests/dates/test_date_disambiguator.py +++ b/tests/dates/test_ambiguous_date.py @@ -1,14 +1,14 @@ import datetime -from augur.dates import date_disambiguator -from augur.dates.date_disambiguator import DateDisambiguator +from augur.dates import ambiguous_date +from augur.dates.ambiguous_date import AmbiguousDate from augur.dates.errors import InvalidDate from freezegun import freeze_time import pytest -class TestDateDisambiguator: +class TestAmbiguousDate: @freeze_time("2111-05-05") @pytest.mark.parametrize( "date_str, expected_range", @@ -19,7 +19,7 @@ class TestDateDisambiguator: ], ) def test_range(self, date_str, expected_range): - assert DateDisambiguator(date_str).range() == expected_range + assert AmbiguousDate(date_str).range() == expected_range @pytest.mark.parametrize( "date_str, fmt", @@ -31,7 +31,7 @@ def test_range(self, date_str, expected_range): ], ) def test_range_separators(self, date_str, fmt): - assert DateDisambiguator(date_str, fmt=fmt).range() == ( + assert AmbiguousDate(date_str, fmt=fmt).range() == ( datetime.date(2005, 2, 1), datetime.date(2005, 2, 28), ) @@ -46,12 +46,12 @@ def test_range_separators(self, date_str, fmt): ) def test_uncertain_date_components(self, date_str, expected_components): assert ( - DateDisambiguator(date_str).uncertain_date_components == expected_components + AmbiguousDate(date_str).uncertain_date_components == expected_components ) def test_uncertain_date_components_error(self): with pytest.raises(InvalidDate, match="Date does not match format"): - DateDisambiguator("5-5-5-5-5").uncertain_date_components + AmbiguousDate("5-5-5-5-5").uncertain_date_components @pytest.mark.parametrize( "date_str, min_or_max, expected", @@ -68,7 +68,7 @@ def test_uncertain_date_components_error(self): ) def test_resolve_uncertain_int(self, date_str, min_or_max, expected): assert ( - date_disambiguator.resolve_uncertain_int(date_str, min_or_max) == expected + ambiguous_date.resolve_uncertain_int(date_str, min_or_max) == expected ) @pytest.mark.parametrize( @@ -80,4 +80,4 @@ def test_resolve_uncertain_int(self, date_str, min_or_max, expected): ) def test_assert_only_less_significant_uncertainty(self, date_str, expected_error): with pytest.raises(InvalidDate, match=expected_error): - DateDisambiguator(date_str) + AmbiguousDate(date_str)