def date_property(attr, allow_none=True, default=MISSING, default_factory=MISSING, formats: List[str] = None): """Create a date dataclass property where the underlying datetime is saved to "_attr". Args: attr (str): Attribute name (example: "created_on" allow_none (bool)[True]: Allows the property to be set to None. This is needed if the default is None. default (object)[MISSING]: Default value for the dataclass default_factory (function)[MISSING]: Function that returns the default value. formats (list)[None]: List of string formats to accept. Returns: property (field_property): Dataclass field property for a date. """ attr = '_' + attr typeref = Union[Date, str] if allow_none: typeref = Union[Date, str, None] if default == MISSING and default_factory == MISSING and allow_none: default = None def fget(self): return getattr(self, attr) def fset(self, value: typeref): if value is None and not allow_none: raise TypeError('Invalid date value given!') elif value is not None: value = Date.make_date(value, formats=formats) setattr(self, attr, value) return field_property(fget, fset, doc='date property {}'.format(attr), default=default, default_factory=default_factory)
def weekdays_property(attr): """Return a property to access Weekdays.sunday as a property. Example: .. code-block:: python class MyClass: weekdays: Weekdays = Weekdays() sunday: bool = weekdays_property('sunday') monday: bool = weekdays_property('monday') tuesday: bool = weekdays_property('tuesday') wednesday: bool = weekdays_property('wednesday') thursday: bool = weekdays_property('thursday') friday: bool = weekdays_property('friday') saturday: bool = weekdays_property('saturday') """ def fget(self): return getattr(self.weekdays, attr, 0) def fset(self, value): if value is None: return # Ignore initial value of None setattr(self.weekdays, attr, value) def fdel(self): delattr(self.weekdays, attr) return field_property(fget, fset, fdel, doc='Alias for weekdays {}'.format(attr), default=None)
def seconds_property(attr='seconds'): """Property for a seconds attribute to turn floating points into milliseconds. Args: attr (str)['seconds']: Attribute name Returns: property (field_property): Property that when given a float will set seconds and milliseconds. """ attr = '_' + attr def fget(self) -> int: return getattr(self, attr, 0) def fset(self, value: Union[int, float]): if isinstance(value, float): mill = int((value % 1) * 1000) if mill: self.milliseconds = mill setattr(self, attr, int(value)) return field_property(fget, fset, doc='Seconds in time. If float also set milliseconds', default=0)
class Point: # X @field_property(default=1) def x(self) -> int: return self._x @x.setter def x(self, value: int): self._x = value # Y y: int = field_property(default=1) @y.getter def y(self) -> int: return self._y @y.setter def y(self, value: int): self._y = value # Z @field_property def z(self) -> int: return self._z z.default(5) @z.default_factory @classmethod def z(cls): return 5 @z.setter def z(self, value: int): self._z = value
def timedelta_helper_property(): """Return a timedelta property that uses a classes attributes for 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', and 'microseconds'. Example: .. code-block:: python @dataclass class MyClass: days: int = 0 hours: int = 0 minutes: int = 0 seconds: int = 0 milliseconds: int = 0 interval: datetime.timedelta = timedelta_helper_property() Returns: property (field_property): Timedelta property that uses a classes underlying attributes. """ def fget(self) -> datetime.timedelta: weeks = getattr(self, 'weeks', 0) days = getattr(self, 'days', 0) hours = getattr(self, 'hours', 0) minutes = getattr(self, 'minutes', 0) seconds = getattr(self, 'seconds', 0) milliseconds = getattr(self, 'milliseconds', 0) microseconds = getattr(self, 'microseconds', 0) return datetime.timedelta(weeks=weeks, days=days, hours=hours, minutes=minutes, seconds=seconds, milliseconds=milliseconds, microseconds=microseconds) def fset(self, value: datetime.timedelta): if value is None: # Protect the default of None return elif not isinstance(value, datetime.timedelta): raise TypeError('Invalid timedelta given!') days = value.days seconds = value.seconds microseconds = value.microseconds weeks = int(days / 7) days = int(days - weeks) if hasattr(self, 'weeks'): self.weeks = weeks if hasattr(self, 'days'): self.days = days hours = int(seconds / 3600) minutes = int((seconds - (hours * 3600)) / 60) seconds = int(seconds - (minutes * 60)) if hasattr(self, 'hours'): self.hours = hours if hasattr(self, 'minutes'): self.minutes = minutes if hasattr(self, 'seconds'): self.seconds = seconds milliseconds = int(microseconds / 1000) microseconds = int(microseconds - (milliseconds * 1000)) if hasattr(self, 'milliseconds'): self.milliseconds = milliseconds if hasattr(self, 'microseconds'): self.microseconds = microseconds return field_property(fget, fset, doc='Interval from the set time values', default=None)