diff --git a/CHANGES.rst b/CHANGES.rst index a8d91e68..2951b09f 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,11 +1,65 @@ Changelog ========= +<<<<<<< HEAD +5.0.3 (unreleased) +------------------ + +<<<<<<< HEAD +<<<<<<< HEAD +Update prop.py +======= +Update parser.py +>>>>>>> 3463555 (Update CHANGES.rst) +======= +Update prop.py +>>>>>>> 4b91ae1 (Update CHANGES.rst pertaining to #482) + +- All ``format`` strings converted to python3.6+ compliant ``f-strings``. +- Optimised rudimentary returns with equivalent boolean statements. + +<<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> 89e39d1 (Update CHANGES.rst) +Breaking changes: + +- ... + +New features: + +- ... + +Bug fixes: + +- ... + +<<<<<<< HEAD +======= +>>>>>>> 3463555 (Update CHANGES.rst) +======= +>>>>>>> 89e39d1 (Update CHANGES.rst) +======= +>>>>>>> 3df7370 (Update CHANGES.rst) 5.0.2 (unreleased) ------------------ Minor changes: +<<<<<<< HEAD +<<<<<<< HEAD +<<<<<<< HEAD +- Refactored prop.py Ref: #482 [pronoym99] +======= +- Updated prop.py to convert all ``format`` strings to python3.6+ compliant ``f-strings`` and optimised rudimentary returns with equivalent boolean statements. Ref: #482 [pronoym99] +>>>>>>> cdca594 (Update CHANGES.rst pertaining to #482) +======= +- Updated prop.py to convert all ``format`` strings to python3.6+ compliant ``f-strings`` and optimised rudimentary returns with equivalent boolean statements. Ref: #482 [pronoym99] +>>>>>>> 3df7370 (Update CHANGES.rst) +======= +- Refactored prop.py Ref: #482 [pronoym99] +>>>>>>> 0421d31 (Update CHANGES.rst) + - Calendar.from_ical no longer throws long errors Ref: #473 Fixes: #472 diff --git a/src/icalendar/prop.py b/src/icalendar/prop.py index 56d516f4..45b8b87d 100644 --- a/src/icalendar/prop.py +++ b/src/icalendar/prop.py @@ -90,6 +90,7 @@ class FixedOffset(tzinfo): """Fixed offset in minutes east from UTC. """ + def __init__(self, offset, name): self.__offset = timedelta(minutes=offset) self.__name = name @@ -107,17 +108,12 @@ def dst(self, dt): class LocalTimezone(tzinfo): """Timezone of the machine where the code is running. """ + def utcoffset(self, dt): - if self._isdst(dt): - return DSTOFFSET - else: - return STDOFFSET + return self._isdst(dt) and DSTOFFSET or STDOFFSET def dst(self, dt): - if self._isdst(dt): - return DSTDIFF - else: - return ZERO + return self._isdst(dt) and DSTDIFF or ZERO def tzname(self, dt): return _time.tzname[self._isdst(dt)] @@ -140,7 +136,7 @@ def __init__(self, obj): self.params = Parameters(encoding='BASE64', value="BINARY") def __repr__(self): - return "vBinary('%s')" % self.to_ical() + return f"vBinary('{self.to_ical()}')" def to_ical(self): return binascii.b2a_base64(self.obj.encode('utf-8'))[:-1] @@ -164,16 +160,14 @@ def __new__(cls, *args, **kwargs): return self def to_ical(self): - if self: - return b'TRUE' - return b'FALSE' + return self and b'TRUE' or b'FALSE' @classmethod def from_ical(cls, ical): try: return cls.BOOL_MAP[ical] except Exception: - raise ValueError("Expected 'TRUE' or 'FALSE'. Got %s" % ical) + raise ValueError(f"Expected 'TRUE' or 'FALSE'. Got {ical}") class vCalAddress(str): @@ -186,7 +180,7 @@ def __new__(cls, value, encoding=DEFAULT_ENCODING): return self def __repr__(self): - return "vCalAddress('%s')" % self.to_ical() + return f"vCalAddress('{self.to_ical()}')" def to_ical(self): return self.encode(DEFAULT_ENCODING) @@ -212,7 +206,7 @@ def from_ical(cls, ical): try: return cls(ical) except Exception: - raise ValueError('Expected float value, got: %s' % ical) + raise ValueError(f'Expected float value, got: {ical}') class vInt(int): @@ -231,12 +225,13 @@ def from_ical(cls, ical): try: return cls(ical) except Exception: - raise ValueError('Expected int, got: %s' % ical) + raise ValueError(f'Expected int, got: {ical}') class vDDDLists: """A list of vDDDTypes values. """ + def __init__(self, dt_list): if not hasattr(dt_list, '__iter__'): dt_list = [dt_list] @@ -265,6 +260,7 @@ def from_ical(ical, timezone=None): out.append(vDDDTypes.from_ical(ical_dt, timezone=timezone)) return out + class vCategory: def __init__(self, c_list): @@ -287,6 +283,7 @@ class vDDDTypes: cannot be confused, and often values can be of either types. So this is practical. """ + def __init__(self, dt): if not isinstance(dt, (datetime, date, timedelta, time, tuple)): raise ValueError('You must use datetime, date, timedelta, ' @@ -346,13 +343,14 @@ def from_ical(cls, ical, timezone=None): return vTime.from_ical(ical) else: raise ValueError( - "Expected datetime, date, or time, got: '%s'" % ical + f"Expected datetime, date, or time, got: '{ical}'" ) class vDate: """Render and generates iCalendar date format. """ + def __init__(self, dt): if not isinstance(dt, date): raise ValueError('Value MUST be a date instance') @@ -360,7 +358,7 @@ def __init__(self, dt): self.params = Parameters({'value': 'DATE'}) def to_ical(self): - s = "%04d%02d%02d" % (self.dt.year, self.dt.month, self.dt.day) + s = f"{self.dt.year:04}{self.dt.month:02}{self.dt.day:02}" return s.encode('utf-8') @staticmethod @@ -373,7 +371,7 @@ def from_ical(ical): ) return date(*timetuple) except Exception: - raise ValueError('Wrong date format %s' % ical) + raise ValueError(f'Wrong date format {ical}') class vDatetime: @@ -387,6 +385,7 @@ class vDatetime: created. Be aware that there are certain limitations with timezone naive DATE-TIME components in the icalendar standard. """ + def __init__(self, dt): self.dt = dt self.params = Parameters() @@ -395,14 +394,7 @@ def to_ical(self): dt = self.dt tzid = tzid_from_dt(dt) - s = "%04d%02d%02dT%02d%02d%02d" % ( - dt.year, - dt.month, - dt.day, - dt.hour, - dt.minute, - dt.second - ) + s = f"{dt.year:04}{dt.month:02}{dt.day:02}T{dt.hour:02}{dt.minute:02}{dt.second:02}" if tzid == 'UTC': s += "Z" elif tzid: @@ -417,7 +409,8 @@ def from_ical(ical, timezone=None): tzinfo = pytz.timezone(timezone.strip('/')) except pytz.UnknownTimeZoneError: if timezone in WINDOWS_TO_OLSON: - tzinfo = pytz.timezone(WINDOWS_TO_OLSON.get(timezone.strip('/'))) + tzinfo = pytz.timezone( + WINDOWS_TO_OLSON.get(timezone.strip('/'))) else: tzinfo = _timezone_cache.get(timezone, None) @@ -439,7 +432,7 @@ def from_ical(ical, timezone=None): else: raise ValueError(ical) except Exception: - raise ValueError('Wrong datetime format: %s' % ical) + raise ValueError(f'Wrong datetime format: {ical}') class vDuration: @@ -466,18 +459,18 @@ def to_ical(self): minutes = td.seconds % 3600 // 60 seconds = td.seconds % 60 if hours: - timepart += "%dH" % hours + timepart += f"{hours}H" if minutes or (hours and seconds): - timepart += "%dM" % minutes + timepart += f"{minutes}M" if seconds: - timepart += "%dS" % seconds + timepart += f"{seconds}S" if td.days == 0 and timepart: - return (str(sign).encode('utf-8') + b'P' + - str(timepart).encode('utf-8')) + return (str(sign).encode('utf-8') + b'P' + + str(timepart).encode('utf-8')) else: - return (str(sign).encode('utf-8') + b'P' + - str(abs(td.days)).encode('utf-8') + - b'D' + str(timepart).encode('utf-8')) + return (str(sign).encode('utf-8') + b'P' + + str(abs(td.days)).encode('utf-8') + + b'D' + str(timepart).encode('utf-8')) @staticmethod def from_ical(ical): @@ -495,19 +488,20 @@ def from_ical(ical): value = -value return value except Exception: - raise ValueError('Invalid iCalendar duration: %s' % ical) + raise ValueError(f'Invalid iCalendar duration: {ical}') class vPeriod: """A precise period of time. """ + def __init__(self, per): start, end_or_duration = per if not (isinstance(start, datetime) or isinstance(start, date)): raise ValueError('Start value MUST be a datetime or date instance') - if not (isinstance(end_or_duration, datetime) or - isinstance(end_or_duration, date) or - isinstance(end_or_duration, timedelta)): + if not (isinstance(end_or_duration, datetime) + or isinstance(end_or_duration, date) + or isinstance(end_or_duration, timedelta)): raise ValueError('end_or_duration MUST be a datetime, ' 'date or timedelta instance') by_duration = 0 @@ -535,7 +529,8 @@ def __init__(self, per): def __cmp__(self, other): if not isinstance(other, vPeriod): - raise NotImplementedError('Cannot compare vPeriod with %r' % other) + raise NotImplementedError( + f'Cannot compare vPeriod with {other!r}') return cmp((self.start, self.end), (other.start, other.end)) def overlaps(self, other): @@ -547,10 +542,10 @@ def overlaps(self, other): def to_ical(self): if self.by_duration: - return (vDatetime(self.start).to_ical() + b'/' + - vDuration(self.duration).to_ical()) - return (vDatetime(self.start).to_ical() + b'/' + - vDatetime(self.end).to_ical()) + return (vDatetime(self.start).to_ical() + b'/' + + vDuration(self.duration).to_ical()) + return (vDatetime(self.start).to_ical() + b'/' + + vDatetime(self.end).to_ical()) @staticmethod def from_ical(ical): @@ -560,7 +555,7 @@ def from_ical(ical): end_or_duration = vDDDTypes.from_ical(end_or_duration) return (start, end_or_duration) except Exception: - raise ValueError('Expected period format, got: %s' % ical) + raise ValueError(f'Expected period format, got: {ical}') def __repr__(self): if self.by_duration: @@ -582,13 +577,13 @@ def __new__(cls, value, encoding=DEFAULT_ENCODING): self = super().__new__(cls, value) match = WEEKDAY_RULE.match(self) if match is None: - raise ValueError('Expected weekday abbrevation, got: %s' % self) + raise ValueError(f'Expected weekday abbrevation, got: {self}') match = match.groupdict() sign = match['signal'] weekday = match['weekday'] relative = match['relative'] if weekday not in vWeekday.week_days or sign not in '+-': - raise ValueError('Expected weekday abbrevation, got: %s' % self) + raise ValueError(f'Expected weekday abbrevation, got: {self}') self.relative = relative and int(relative) or None self.params = Parameters() return self @@ -601,7 +596,7 @@ def from_ical(cls, ical): try: return cls(ical.upper()) except Exception: - raise ValueError('Expected weekday abbrevation, got: %s' % ical) + raise ValueError(f'Expected weekday abbrevation, got: {ical}') class vFrequency(str): @@ -622,7 +617,7 @@ def __new__(cls, value, encoding=DEFAULT_ENCODING): value = to_unicode(value, encoding=encoding) self = super().__new__(cls, value) if self not in vFrequency.frequencies: - raise ValueError('Expected frequency, got: %s' % self) + raise ValueError(f'Expected frequency, got: {self}') self.params = Parameters() return self @@ -634,7 +629,7 @@ def from_ical(cls, ical): try: return cls(ical.upper()) except Exception: - raise ValueError('Expected frequency, got: %s' % ical) + raise ValueError(f'Expected frequency, got: {ical}') class vRecur(CaselessDict): @@ -708,7 +703,7 @@ def from_ical(cls, ical): recur[key] = cls.parse_type(key, vals) return dict(recur) except Exception: - raise ValueError('Error in recurrence rule: %s' % ical) + raise ValueError(f'Error in recurrence rule: {ical}') class vText(str): @@ -723,7 +718,7 @@ def __new__(cls, value, encoding=DEFAULT_ENCODING): return self def __repr__(self): - return "vText('%s')" % self.to_ical() + return f"vText('{self.to_ical()}')" def to_ical(self): return escape_char(self).encode(self.encoding) @@ -741,7 +736,7 @@ class vTime: def __init__(self, *args): if len(args) == 1: if not isinstance(args[0], (time, datetime)): - raise ValueError('Expected a datetime.time, got: %s' % args[0]) + raise ValueError(f'Expected a datetime.time, got: {args[0]}') self.dt = args[0] else: self.dt = time(*args) @@ -757,7 +752,7 @@ def from_ical(ical): timetuple = (int(ical[:2]), int(ical[2:4]), int(ical[4:6])) return time(*timetuple) except Exception: - raise ValueError('Expected time, got: %s' % ical) + raise ValueError(f'Expected time, got: {ical}') class vUri(str): @@ -778,7 +773,7 @@ def from_ical(cls, ical): try: return cls(ical) except Exception: - raise ValueError('Expected , got: %s' % ical) + raise ValueError(f'Expected , got: {ical}') class vGeo: @@ -806,7 +801,7 @@ def from_ical(ical): latitude, longitude = ical.split(';') return (float(latitude), float(longitude)) except Exception: - raise ValueError("Expected 'float;float' , got: %s" % ical) + raise ValueError(f"Expected 'float;float' , got: {ical}") class vUTCOffset: @@ -814,9 +809,9 @@ class vUTCOffset: """ ignore_exceptions = False # if True, and we cannot parse this - # component, we will silently ignore - # it, rather than let the exception - # propagate upwards + # component, we will silently ignore + # it, rather than let the exception + # propagate upwards def __init__(self, td): if not isinstance(td, timedelta): @@ -840,9 +835,9 @@ def to_ical(self): minutes = abs((seconds % 3600) // 60) seconds = abs(seconds % 60) if seconds: - duration = '%02i%02i%02i' % (hours, minutes, seconds) + duration = f'{hours:02}{minutes:02}{seconds:02}' else: - duration = '%02i%02i' % (hours, minutes) + duration = f'{hours:02}{minutes:02}' return sign % duration @classmethod @@ -856,10 +851,10 @@ def from_ical(cls, ical): int(ical[5:7] or 0)) offset = timedelta(hours=hours, minutes=minutes, seconds=seconds) except Exception: - raise ValueError('Expected utc offset, got: %s' % ical) + raise ValueError(f'Expected utc offset, got: {ical}') if not cls.ignore_exceptions and offset >= timedelta(hours=24): raise ValueError( - 'Offset must be less than 24 hours, was %s' % ical) + f'Offset must be less than 24 hours, was {ical}') if sign == '-': return -offset return offset