1
\$\begingroup\$

I have a method in a class that accepts either a datetime or string parameter. It is shown in the last code block (I didn't include the class). A little background is that I am defining a wrapper around an API, and I want the end user to be able to pass either a string or a date but convert that into the appropriate string for the API query.

I wrote a decorator that validates the dates, and converts the datetime to the appropriate string format for the subsequent call to the API. The decorator I wrote is defined outside of the class as a function.

  1. Should I include validate_date_helper in the scope of the wrapper?
  2. Is defining these functions outside of the class pythonic and is this a valid approach for what I am trying to accomplish?
  3. Are there other ways to accomplish validations like this?
from datetime import datetime as dt
from typing import Union

def validate_date_helper(date):
     """
     validates a start date or updated after date.
     end
     """
     utc_format = "%Y-%m-%dT%H:%M:%S"
     if isinstance(date, dt):
         date = date.strftime(utc_format)
     elif isinstance(date, str):
         utc_format_date = date + "T00:00:00"
         dt.strptime(utc_format_date, utc_format)
     else:
         raise ValueError(f"{date} must be datetime object or string")
     return date


def validate_dates(func):
     def func_wrapper(self, *args, **kwargs):
         """
         validates dates for the between function
         """
         new_args = []
         new_kwargs = {}
         for arg in args:
             arg = validate_date_helper(arg)
             new_args.append(arg)
         for key, val in kwargs.items():
             if val is not None:
                 val = validate_date_helper(val)
             new_kwargs[key] = val
         res = func(self, *new_args, **new_kwargs)
         return res
       return func_wrapper



@validate_dates
def between(self, start: Union[dt, str], end=None):         
    """
    sets startime and endtime for API query
    """
    self.query["starttime"] = start # self.query is an empty dictionary at class instantiation
    if end is not None:
        self.query["endtime"] = end  
    return self

\$\endgroup\$
6
  • \$\begingroup\$ It's not a validator if it returns new value. \$\endgroup\$
    – slepic
    Nov 25, 2022 at 4:21
  • \$\begingroup\$ I think that it's totally fine to declare this method outside the class. Its task is to preprocess an input, so the input adheres to some specification. The class is the user of this decorator. They aren't tightly coupled, nor necessarily belong together. But the helper function should be at least private or put inside the wrapper. And/or I would rename it to convert_date_to_string. \$\endgroup\$ Nov 25, 2022 at 6:11
  • 1
    \$\begingroup\$ Please choose a title that describes what the app does, not the question you have. Thanks. \$\endgroup\$
    – ggorlen
    Nov 25, 2022 at 6:53
  • \$\begingroup\$ Welcome to Code Review! I changed the title so that it describes what the code does per site goals: "State what your code does in your title, not your main concerns about it.". Please check that I haven't misrepresented your code, and correct it if I have. \$\endgroup\$ Nov 25, 2022 at 8:02
  • \$\begingroup\$ @Green绿色 I went ahead and implemented the changed that you described. Should I make these edits in the post? \$\endgroup\$ Nov 27, 2022 at 0:31

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.