diff --git a/.pylintrc b/.pylintrc index 6aa5a3a..d7d5a16 100644 --- a/.pylintrc +++ b/.pylintrc @@ -23,7 +23,6 @@ disable= # W fixme, keyword-arg-before-vararg, - logging-format-interpolation, protected-access, raise-missing-from, unspecified-encoding, diff --git a/vobject/base.py b/vobject/base.py index 0287e80..00fdcc8 100644 --- a/vobject/base.py +++ b/vobject/base.py @@ -20,10 +20,10 @@ def str_(s): def to_unicode(value): - """Converts a string argument to a unicode string. + """Converts a string argument to a Unicode string. - If the argument is already a unicode string, it is returned unchanged. - Otherwise it must be a byte string and is decoded as utf8. + If the argument is already a Unicode string, it is returned unchanged. + Otherwise, it must be a byte string and is decoded as utf8. """ return value if isinstance(value, unicode_type) else value.decode("utf-8") @@ -32,7 +32,7 @@ def to_basestring(s): """Converts a string argument to a byte string. If the argument is already a byte string, it is returned unchanged. - Otherwise it must be a unicode string and is encoded as utf8. + Otherwise, it must be a Unicode string and is encoded as utf8. """ return s if isinstance(s, bytes) else s.encode("utf-8") @@ -419,7 +419,7 @@ class Component(VBase): are the lowercased names of child ContentLines or Components. Note that BEGIN and END ContentLines are not included in contents. @ivar name: - Uppercase string used to represent this Component, i.e VCARD if the + Uppercase string used to represent this Component, i.e. VCARD if the serialized object starts with BEGIN:VCARD. @ivar useBegin: A boolean flag determining whether BEGIN: and END: lines should @@ -897,7 +897,7 @@ def dquoteEscape(param): def foldOneLine(outbuf, input_, lineLength=75): """ - Folding line procedure that ensures multi-byte utf-8 sequences are not + Folding line procedure that ensures multibyte utf-8 sequences are not broken across lines TO-DO: This all seems odd. Is it still needed, especially in python3? @@ -1042,10 +1042,9 @@ def readComponents(streamOrString, validate=False, transform=True, ignoreUnreada vline = textLineToContentLine(line, n) except VObjectError as e: if e.lineNumber is not None: - msg = "Skipped line {lineNumber}, message: {msg}" + logger.error("Skipped line %d, message: %s", e.lineNumber, str(e)) else: - msg = "Skipped a line, message: {msg}" - logger.error(msg.format(**{"lineNumber": e.lineNumber, "msg": str(e)})) + logger.error("Skipped a line, message: %s", str(e)) continue else: vline = textLineToContentLine(line, n) diff --git a/vobject/behavior.py b/vobject/behavior.py index d0e7556..3c8db52 100644 --- a/vobject/behavior.py +++ b/vobject/behavior.py @@ -41,7 +41,7 @@ class Behavior: @cvar sortFirst: The lower-case list of children which should come first when sorting. @cvar allowGroup: - Whether or not vCard style group prefixes are allowed. + Whether vCard style group prefixes are allowed. """ name = "" @@ -69,10 +69,10 @@ def validate(cls, obj, raiseException=False, complainUnrecognized=False): L{Component} to be validated. @param raiseException: If True, raise a L{base.ValidateError} on validation failure. - Otherwise return a boolean. + Otherwise, return a boolean. @param complainUnrecognized: - If True, fail to validate if an uncrecognized parameter or child is - found. Otherwise log the lack of recognition. + If True, fail to validate if an unrecognized parameter or child is + found. Otherwise, log the lack of recognition. """ if not cls.allowGroup and obj.group is not None: @@ -139,7 +139,7 @@ def generateImplicitParameters(cls, obj): @classmethod def serialize(cls, obj, buf, lineLength, validate=True, *args, **kwargs): """ - Set implicit parameters, do encoding, return unicode string. + Set implicit parameters, do encoding, return Unicode string. If validate is True, raise VObjectError if the line doesn't validate after implicit parameters are generated. diff --git a/vobject/icalendar.py b/vobject/icalendar.py index 6ce5502..623e245 100644 --- a/vobject/icalendar.py +++ b/vobject/icalendar.py @@ -722,8 +722,8 @@ class RecurringBehavior(VCalendarComponentBehavior): hasNative = True - @staticmethod - def transformToNative(obj): + @classmethod + def transformToNative(cls, obj): """ Turn a recurring Component into a RecurringComponent. """ @@ -732,15 +732,15 @@ def transformToNative(obj): obj.isNative = True return obj - @staticmethod - def transformFromNative(obj): + @classmethod + def transformFromNative(cls, obj): if obj.isNative: object.__setattr__(obj, "__class__", Component) obj.isNative = False return obj - @staticmethod - def generateImplicitParameters(obj): + @classmethod + def generateImplicitParameters(cls, obj): """ Generate a UID and DTSTAMP if one does not exist. @@ -765,8 +765,8 @@ class DateTimeBehavior(behavior.Behavior): hasNative = True - @staticmethod - def transformToNative(obj): + @classmethod + def transformToNative(cls, obj): """ Turn obj.value into a datetime. @@ -825,8 +825,8 @@ class DateOrDateTimeBehavior(behavior.Behavior): hasNative = True - @staticmethod - def transformToNative(obj): + @classmethod + def transformToNative(cls, obj): """ Turn obj.value into a date or datetime. """ @@ -843,8 +843,8 @@ def transformToNative(obj): del obj.tzid_param return obj - @staticmethod - def transformFromNative(obj): + @classmethod + def transformFromNative(cls, obj): """ Replace the date or datetime in obj.value with an ISO 8601 string. """ @@ -865,8 +865,8 @@ class MultiDateBehavior(behavior.Behavior): hasNative = True - @staticmethod - def transformToNative(obj): + @classmethod + def transformToNative(cls, obj): """ Turn obj.value into a list of dates, datetimes, or (datetime, timedelta) tuples. @@ -888,8 +888,8 @@ def transformToNative(obj): obj.value = [stringToPeriod(x, tzinfo) for x in valTexts] return obj - @staticmethod - def transformFromNative(obj): + @classmethod + def transformFromNative(cls, obj): """ Replace the date, datetime or period tuples in obj.value with appropriate strings. @@ -1104,14 +1104,14 @@ class VTimezone(VCalendarComponentBehavior): } @classmethod - def validate(cls, obj, raiseException, *args): + def validate(cls, obj, raiseException=False, complainUnrecognized=False): if not hasattr(obj, "tzid") or obj.tzid.value is None: if raiseException: m = "VTIMEZONE components must contain a valid TZID" raise ValidateError(m) return False if "standard" in obj.contents or "daylight" in obj.contents: - return super(VTimezone, cls).validate(obj, raiseException, *args) + return super(VTimezone, cls).validate(obj, raiseException, complainUnrecognized) else: if raiseException: m = "VTIMEZONE components must contain a STANDARD or a DAYLIGHT\ @@ -1119,16 +1119,16 @@ def validate(cls, obj, raiseException, *args): raise ValidateError(m) return False - @staticmethod - def transformToNative(obj): + @classmethod + def transformToNative(cls, obj): if not obj.isNative: object.__setattr__(obj, "__class__", TimezoneComponent) obj.isNative = True obj.registerTzinfo(obj.tzinfo) return obj - @staticmethod - def transformFromNative(obj): + @classmethod + def transformFromNative(cls, obj): return obj @@ -1206,7 +1206,7 @@ class VEvent(RecurringBehavior): } @classmethod - def validate(cls, obj, raiseException, *args): + def validate(cls, obj, raiseException=False, complainUnrecognized=False): if "dtend" in obj.contents and "duration" in obj.contents: if raiseException: m = "VEVENT components cannot contain both DTEND and DURATION\ @@ -1214,7 +1214,7 @@ def validate(cls, obj, raiseException, *args): raise ValidateError(m) return False else: - return super(VEvent, cls).validate(obj, raiseException, *args) + return super(VEvent, cls).validate(obj, raiseException, complainUnrecognized) registerBehavior(VEvent) @@ -1266,7 +1266,7 @@ class VTodo(RecurringBehavior): } @classmethod - def validate(cls, obj, raiseException, *args): + def validate(cls, obj, raiseException=False, complainUnrecognized=False): if "due" in obj.contents and "duration" in obj.contents: if raiseException: m = "VTODO components cannot contain both DUE and DURATION\ @@ -1274,7 +1274,7 @@ def validate(cls, obj, raiseException, *args): raise ValidateError(m) return False else: - return super(VTodo, cls).validate(obj, raiseException, *args) + return super(VTodo, cls).validate(obj, raiseException, complainUnrecognized) registerBehavior(VTodo) @@ -1362,8 +1362,8 @@ class VAlarm(VCalendarComponentBehavior): "DESCRIPTION": (0, 1, None), } - @staticmethod - def generateImplicitParameters(obj): + @classmethod + def generateImplicitParameters(cls, obj): """ Create default ACTION and TRIGGER if they're not set. """ @@ -1377,7 +1377,7 @@ def generateImplicitParameters(obj): obj.add("trigger").value = datetime.timedelta(0) @classmethod - def validate(cls, obj, raiseException, *args): + def validate(cls, obj, raiseException=False, complainUnrecognized=False): """ # TODO if obj.contents.has_key('dtend') and obj.contents.has_key('duration'): @@ -1387,7 +1387,7 @@ def validate(cls, obj, raiseException, *args): raise ValidateError(m) return False else: - return super(VEvent, cls).validate(obj, raiseException, *args) + return super(VEvent, cls).validate(obj, raiseException, complainUnrecognized) """ return True @@ -1425,14 +1425,14 @@ class VAvailability(VCalendarComponentBehavior): } @classmethod - def validate(cls, obj, raiseException, *args): + def validate(cls, obj, raiseException=False, complainUnrecognized=False): if "dtend" in obj.contents and "duration" in obj.contents: if raiseException: m = "VAVAILABILITY components cannot contain both DTEND and DURATION components" raise ValidateError(m) return False else: - return super(VAvailability, cls).validate(obj, raiseException, *args) + return super(VAvailability, cls).validate(obj, raiseException, complainUnrecognized) registerBehavior(VAvailability) @@ -1465,7 +1465,7 @@ class Available(RecurringBehavior): } @classmethod - def validate(cls, obj, raiseException, *args): + def validate(cls, obj, raiseException=False, complainUnrecognized=False): has_dtend = "dtend" in obj.contents has_duration = "duration" in obj.contents if has_dtend and has_duration: @@ -1481,7 +1481,7 @@ def validate(cls, obj, raiseException, *args): raise ValidateError(m) return False else: - return super(Available, cls).validate(obj, raiseException, *args) + return super(Available, cls).validate(obj, raiseException, complainUnrecognized) registerBehavior(Available) @@ -1495,8 +1495,8 @@ class Duration(behavior.Behavior): name = "DURATION" hasNative = True - @staticmethod - def transformToNative(obj): + @classmethod + def transformToNative(cls, obj): """ Turn obj.value into a datetime.timedelta. """ @@ -1515,8 +1515,8 @@ def transformToNative(obj): else: raise ParseError("DURATION must have a single duration string.") - @staticmethod - def transformFromNative(obj): + @classmethod + def transformFromNative(cls, obj): """ Replace the datetime.timedelta in obj.value with an RFC2445 string. """ @@ -1540,8 +1540,8 @@ class Trigger(behavior.Behavior): hasNative = True forceUTC = True - @staticmethod - def transformToNative(obj): + @classmethod + def transformToNative(cls, obj): """ Turn obj.value into a timedelta or datetime. """ @@ -1576,8 +1576,8 @@ def transformToNative(obj): else: raise ParseError("VALUE must be DURATION or DATE-TIME") - @staticmethod - def transformFromNative(obj): + @classmethod + def transformFromNative(cls, obj): if type(obj.value) is datetime.datetime: obj.value_param = "DATE-TIME" return UTCDateTimeBehavior.transformFromNative(obj) @@ -1597,8 +1597,8 @@ class PeriodBehavior(behavior.Behavior): hasNative = True - @staticmethod - def transformToNative(obj): + @classmethod + def transformToNative(cls, obj): """ Convert comma separated periods into tuples. """ @@ -2165,10 +2165,3 @@ def dt_test(dt): if t1 != t2 or not dt_test(t1): return False return True - - -# ------------------- Testing and running functions ---------------------------- -if __name__ == "__main__": - import tests - - tests._test() diff --git a/vobject/vcard.py b/vobject/vcard.py index 7ac402f..ddb1fc4 100644 --- a/vobject/vcard.py +++ b/vobject/vcard.py @@ -237,7 +237,7 @@ def valueRepr(cls, line): return f" (BINARY PHOTO DATA at 0x{id(line.value)}) " @classmethod - def serialize(cls, obj, buf, lineLength, validate, *args, **kwargs): + def serialize(cls, obj, buf, lineLength, validate=True, *args, **kwargs): """ Apple's Address Book is *really* weird with images, it expects base64 data to have very specific whitespace. It seems Address Book @@ -300,8 +300,8 @@ class NameBehavior(VCardBehavior): hasNative = True - @staticmethod - def transformToNative(obj): + @classmethod + def transformToNative(cls, obj): """ Turn obj.value into a Name. """ @@ -311,8 +311,8 @@ def transformToNative(obj): obj.value = Name(**dict(zip(NAME_ORDER, splitFields(obj.value)))) return obj - @staticmethod - def transformFromNative(obj): + @classmethod + def transformFromNative(cls, obj): """ Replace the Name in obj.value with a string. """ @@ -331,8 +331,8 @@ class AddressBehavior(VCardBehavior): hasNative = True - @staticmethod - def transformToNative(obj): + @classmethod + def transformToNative(cls, obj): """ Turn obj.value into an Address. """ @@ -342,8 +342,8 @@ def transformToNative(obj): obj.value = Address(**dict(zip(ADDRESS_ORDER, splitFields(obj.value)))) return obj - @staticmethod - def transformFromNative(obj): + @classmethod + def transformFromNative(cls, obj): """ Replace the Address in obj.value with a string. """ @@ -362,8 +362,8 @@ class OrgBehavior(VCardBehavior): hasNative = True - @staticmethod - def transformToNative(obj): + @classmethod + def transformToNative(cls, obj): """ Turn obj.value into a list. """ @@ -373,8 +373,8 @@ def transformToNative(obj): obj.value = splitFields(obj.value) return obj - @staticmethod - def transformFromNative(obj): + @classmethod + def transformFromNative(cls, obj): """ Replace the list in obj.value with a string. """