diff --git a/augur/dates.py b/augur/dates/__init__.py similarity index 96% rename from augur/dates.py rename to augur/dates/__init__.py index 382336537..c8969ba19 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 .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 @@ -114,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/util_support/date_disambiguator.py b/augur/dates/ambiguous_date.py similarity index 98% rename from augur/util_support/date_disambiguator.py rename to augur/dates/ambiguous_date.py index 81ccfe9dc..525dad257 100644 --- a/augur/util_support/date_disambiguator.py +++ b/augur/dates/ambiguous_date.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): @@ -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/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.ambiguous_date.rst similarity index 50% rename from docs/api/developer/augur.util_support.date_disambiguator.rst rename to docs/api/developer/augur.dates.ambiguous_date.rst index ebae8164e..2471f3e8f 100644 --- a/docs/api/developer/augur.util_support.date_disambiguator.rst +++ b/docs/api/developer/augur.dates.ambiguous_date.rst @@ -1,7 +1,7 @@ -augur.util\_support.date\_disambiguator +augur.dates.ambiguous\_date ======================================= -.. automodule:: augur.util_support.date_disambiguator +.. automodule:: augur.dates.ambiguous_date :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..5f314f3ce 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.ambiguous_date + 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_ambiguous_date.py similarity index 78% rename from tests/util_support/test_date_disambiguator.py rename to tests/dates/test_ambiguous_date.py index 5a4d7bb51..ce8f90370 100644 --- a/tests/util_support/test_date_disambiguator.py +++ b/tests/dates/test_ambiguous_date.py @@ -1,14 +1,14 @@ 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 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) 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