From 628ad8fdf23d7ad84930eee97e91302d660c2a22 Mon Sep 17 00:00:00 2001 From: Matt Fisher Date: Fri, 27 Sep 2024 11:07:28 -0600 Subject: [PATCH] Type annotate the temporal module (#604) Co-authored-by: Jessica Scheick Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Jessica Scheick --- .../documentation/classes_dev_uml.svg | 138 +++++++++--------- icepyx/core/query.py | 10 +- icepyx/core/temporal.py | 77 ++++++---- 3 files changed, 122 insertions(+), 103 deletions(-) diff --git a/doc/source/user_guide/documentation/classes_dev_uml.svg b/doc/source/user_guide/documentation/classes_dev_uml.svg index 5be4ca7af..223dbde8d 100644 --- a/doc/source/user_guide/documentation/classes_dev_uml.svg +++ b/doc/source/user_guide/documentation/classes_dev_uml.svg @@ -4,11 +4,11 @@ - + classes_dev_uml - + icepyx.quest.dataset_scripts.argo.Argo @@ -241,20 +241,20 @@ icepyx.core.query.GenQuery - -GenQuery - -_spatial -_temporal -dates -end_time -spatial -spatial_extent -start_time -temporal - -__init__(spatial_extent, date_range, start_time, end_time) -__str__() + +GenQuery + +_spatial +_temporal +dates +end_time +spatial +spatial_extent +start_time +temporal + +__init__(spatial_extent, date_range, start_time, end_time) +__str__() @@ -415,30 +415,30 @@ icepyx.core.query.Query->icepyx.core.query.GenQuery - - + + icepyx.quest.quest.Quest - -Quest - -datasets : dict - -__init__(spatial_extent, date_range, start_time, end_time, proj) -__str__() -add_argo(params, presRange): None -add_icesat2(product, start_time, end_time, version, cycles, tracks, files): None -download_all(path) -save_all(path) -search_all() + +Quest + +datasets : dict + +__init__(spatial_extent, date_range, start_time, end_time, proj) +__str__() +add_argo(params, presRange): None +add_icesat2(product, start_time, end_time, version, cycles, tracks, files): None +download_all(path) +save_all(path) +search_all() icepyx.quest.quest.Quest->icepyx.core.query.GenQuery - - + + @@ -472,58 +472,58 @@ icepyx.core.spatial.Spatial - -Spatial - -_ext_type : str -_gdf_spat : GeoDataFrame -_geom_file : NoneType -_spatial_ext -_xdateln -extent -extent_as_gdf -extent_file -extent_type - -__init__(spatial_extent) -__str__() -fmt_for_CMR() -fmt_for_EGI() + +Spatial + +_ext_type : str +_gdf_spat : GeoDataFrame +_geom_file : NoneType +_spatial_ext +_xdateln +extent +extent_as_gdf +extent_file +extent_type + +__init__(spatial_extent) +__str__() +fmt_for_CMR() +fmt_for_EGI() icepyx.core.spatial.Spatial->icepyx.core.query.GenQuery - - -_spatial + + +_spatial icepyx.core.spatial.Spatial->icepyx.core.query.GenQuery - - -_spatial + + +_spatial icepyx.core.temporal.Temporal - -Temporal - -_end : datetime -_start : datetime -end -start - -__init__(date_range, start_time, end_time) -__str__() + +Temporal + +_end : datetime +_start : datetime +end +start + +__init__(date_range: Union[list, dict], start_time: Union[str, dt.time, None], end_time: Union[str, dt.time, None]) +__str__(): str icepyx.core.temporal.Temporal->icepyx.core.query.GenQuery - - -_temporal + + +_temporal diff --git a/icepyx/core/query.py b/icepyx/core/query.py index 71df8723e..763ec6c52 100644 --- a/icepyx/core/query.py +++ b/icepyx/core/query.py @@ -126,6 +126,8 @@ class GenQuery: Quest """ + _temporal: tp.Temporal + def __init__( self, spatial_extent=None, @@ -157,7 +159,7 @@ def __str__(self): # Properties @property - def temporal(self): + def temporal(self) -> Union[tp.Temporal, list[str]]: """ Return the Temporal object containing date/time range information for the query object. @@ -254,7 +256,7 @@ def spatial_extent(self): return (self._spatial._ext_type, self._spatial._spatial_ext) @property - def dates(self): + def dates(self) -> list[str]: """ Return an array showing the date range of the query object. Dates are returned as an array containing the start and end datetime @@ -279,7 +281,7 @@ def dates(self): ] # could also use self._start.date() @property - def start_time(self): + def start_time(self) -> Union[list[str], str]: """ Return the start time specified for the start date. @@ -303,7 +305,7 @@ def start_time(self): return self._temporal._start.strftime("%H:%M:%S") @property - def end_time(self): + def end_time(self) -> Union[list[str], str]: """ Return the end time specified for the end date. diff --git a/icepyx/core/temporal.py b/icepyx/core/temporal.py index c02326fbf..86b7a56d1 100644 --- a/icepyx/core/temporal.py +++ b/icepyx/core/temporal.py @@ -1,12 +1,11 @@ import datetime as dt +from typing import Union import warnings -""" -Helper functions for validation of dates -""" +#### Helper functions for validation of dates #### -def convert_string_to_date(date): +def convert_string_to_date(date: str) -> dt.date: """ Converts a string to a datetime object. Throws an error if an invalid format is passed in. @@ -49,7 +48,7 @@ def convert_string_to_date(date): ) -def check_valid_date_range(start, end): +def check_valid_date_range(start: dt.date, end: dt.date) -> None: """ Helper function for checking if a date range is valid. @@ -86,7 +85,10 @@ def check_valid_date_range(start, end): ), "Your date range is invalid; end date MUST be on or after the start date." -def validate_times(start_time, end_time): +def validate_times( + start_time: Union[str, dt.time, None], + end_time: Union[str, dt.time, None], +) -> tuple[dt.time, dt.time]: """ Validates the start and end times passed into __init__ and returns them as datetime.time objects. @@ -141,7 +143,11 @@ def validate_times(start_time, end_time): return start_time, end_time -def validate_date_range_datestr(date_range, start_time=None, end_time=None): +def validate_date_range_datestr( + date_range: list[str], + start_time: Union[str, dt.time, None] = None, + end_time: Union[str, dt.time, None] = None, +) -> tuple[dt.datetime, dt.datetime]: """ Validates a date range provided in the form of a list of strings. @@ -150,12 +156,10 @@ def validate_date_range_datestr(date_range, start_time=None, end_time=None): Parameters ---------- - date_range: list(str) + date_range: A date range provided in the form of a list of strings Strings must be of formats accepted by validate_inputs_temporal.convert_string_to_date(). List must be of length 2. - start_time: string, datetime.time, None - end_time: string, datetime.time, None Returns ------- @@ -185,17 +189,19 @@ def validate_date_range_datestr(date_range, start_time=None, end_time=None): return _start, _end -def validate_date_range_datetime(date_range, start_time=None, end_time=None): +def validate_date_range_datetime( + date_range: list[dt.datetime], + start_time: Union[str, dt.time, None] = None, + end_time: Union[str, dt.time, None] = None, +) -> tuple[dt.datetime, dt.datetime]: """ Validates a date range provided in the form of a list of datetimes. Parameters ---------- - date_range: list(datetime.datetime) + date_range: A date range provided in the form of a list of datetimes. List must be of length 2. - start_time: None, string, datetime.time - end_time: None, string, datetime.time NOTE: If start and/or end times are given, they will be **ignored** in favor of the time from the start/end datetime.datetime objects. @@ -224,7 +230,11 @@ def validate_date_range_datetime(date_range, start_time=None, end_time=None): return date_range[0], date_range[1] -def validate_date_range_date(date_range, start_time=None, end_time=None): +def validate_date_range_date( + date_range: list[dt.date], + start_time: Union[str, dt.time, None] = None, + end_time: Union[str, dt.time, None] = None, +): """ Validates a date range provided in the form of a list of datetime.date objects. @@ -233,11 +243,9 @@ def validate_date_range_date(date_range, start_time=None, end_time=None): Parameters ---------- - date_range: list(str) + date_range: A date range provided in the form of a list of datetime.dates. List must be of length 2. - start_time: string or datetime.time - end_time: string or datetime.time Returns ------- @@ -261,14 +269,18 @@ def validate_date_range_date(date_range, start_time=None, end_time=None): return _start, _end -def validate_date_range_dict(date_range, start_time=None, end_time=None): +def validate_date_range_dict( + date_range: dict[str, Union[str, dt.date]], + start_time: Union[str, dt.time, None] = None, + end_time: Union[str, dt.time, None] = None, +) -> tuple[dt.datetime, dt.datetime]: """ Validates a date range provided in the form of a dict with the following keys: Parameters ---------- - date_range: dict(str, datetime.datetime, datetime.date) + date_range: A date range provided in the form of a dict. date_range must contain only the following keys: * `start_date`: start date, type can be of dt.datetime, dt.date, or string @@ -278,8 +290,6 @@ def validate_date_range_dict(date_range, start_time=None, end_time=None): If the values are of type dt.datetime and were created without times, the datetime package defaults of all 0s are used and the start_time/end_time parameters will be ignored! - start_time: string or datetime.time - end_time: string or datetime.time Returns @@ -293,7 +303,6 @@ def validate_date_range_dict(date_range, start_time=None, end_time=None): >>> valid_drange = validate_date_range_dict(drange, "00:00:00", "23:59:59") >>> valid_drange (datetime.datetime(2016, 1, 1, 0, 0), datetime.datetime(2020, 1, 1, 23, 59, 59)) - """ # Try to get keys from date_range dict @@ -366,7 +375,15 @@ def validate_date_range_dict(date_range, start_time=None, end_time=None): class Temporal: - def __init__(self, date_range, start_time=None, end_time=None): + _start: dt.datetime + _end: dt.datetime + + def __init__( + self, + date_range: Union[list, dict], + start_time: Union[str, dt.time, None] = None, + end_time: Union[str, dt.time, None] = None, + ): """ Validates input from "date_range" argument (and start/end time arguments, if provided), then creates a Temporal object with validated inputs as properties of the object. @@ -376,7 +393,7 @@ def __init__(self, date_range, start_time=None, end_time=None): Parameters ---------- - date_range : list or dict, as follows + date_range : Date range of interest, provided as start and end dates, inclusive. Accepted input date formats are: * YYYY-MM-DD string @@ -387,13 +404,13 @@ def __init__(self, date_range, start_time=None, end_time=None): Date inputs are accepted as a list or dictionary with `start_date` and `end_date` keys. Currently, a list of specific dates (rather than a range) is not accepted. TODO: allow searches with a list of dates, rather than a range. - start_time : str, datetime.time, default None + start_time : Start time in UTC/Zulu (24 hour clock). Input types are an HH:mm:ss string or datetime.time object where HH = hours, mm = minutes, ss = seconds. If None is given (and a datetime.datetime object is not supplied for `date_range`), a default of 00:00:00 is applied. - end_time : str, datetime.time, default None + end_time : End time in UTC/Zulu (24 hour clock). Input types are an HH:mm:ss string or datetime.time object where HH = hours, mm = minutes, ss = seconds. @@ -444,14 +461,14 @@ def __init__(self, date_range, start_time=None, end_time=None): "Your date range list is the wrong length. It should be of length 2, with start and end dates only." ) - def __str__(self): + def __str__(self) -> str: return "Start date and time: {0}\nEnd date and time: {1}".format( self._start.strftime("%Y-%m-%d %H:%M:%S"), self._end.strftime("%Y-%m-%d %H:%M:%S"), ) @property - def start(self): + def start(self) -> dt.datetime: """ Return the start date and time of the Temporal object as a datetime.datetime object. @@ -465,7 +482,7 @@ def start(self): return self._start @property - def end(self): + def end(self) -> dt.datetime: """ Return the end date and time of the Temporal object as a datetime.datetime object.