class Timestamp(datetime.datetime): """Class for handling MediaWiki timestamps. This inherits from datetime.datetime, so it can use all of the methods and operations of a datetime object. To ensure that the results of any operation are also a Timestamp object, be sure to use only Timestamp objects (and datetime.timedeltas) in any operation. Use Timestamp.fromISOformat() and Timestamp.fromtimestampformat() to create Timestamp objects from MediaWiki string formats. As these constructors are typically used to create objects using data passed provided by site and page methods, some of which return a Timestamp when previously they returned a MediaWiki string representation, these methods also accept a Timestamp object, in which case they return a clone. Use Site.getcurrenttime() for the current time; this is more reliable than using Timestamp.utcnow(). """ mediawikiTSFormat = '%Y%m%d%H%M%S' _ISO8601Format_new = '{0:+05d}-{1:02d}-{2:02d}T{3:02d}:{4:02d}:{5:02d}Z' def clone(self): """Clone this instance.""" return self.replace(microsecond=self.microsecond) @classproperty def ISO8601Format(cls): """ISO8601 format string class property for compatibility purpose.""" return cls._ISO8601Format() @classmethod def _ISO8601Format(cls, sep='T'): """ISO8601 format string. @param sep: one-character separator, placed between the date and time @type sep: str @return: ISO8601 format string @rtype: str """ assert(len(sep) == 1) return '%Y-%m-%d{0}%H:%M:%SZ'.format(sep) @classmethod def fromISOformat(cls, ts, sep='T'): """Convert an ISO 8601 timestamp to a Timestamp object. @param ts: ISO 8601 timestamp or a Timestamp object already @type ts: str or Timestamp @param sep: one-character separator, placed between the date and time @type sep: str @return: Timestamp object @rtype: Timestamp """ # If inadvertently passed a Timestamp object, use replace() # to create a clone. if isinstance(ts, cls): return ts.clone() return cls.strptime(ts, cls._ISO8601Format(sep)) @classmethod def fromtimestampformat(cls, ts): """Convert a MediaWiki internal timestamp to a Timestamp object.""" # If inadvertently passed a Timestamp object, use replace() # to create a clone. if isinstance(ts, cls): return ts.clone() if len(ts) == 8: # year, month and day are given only ts += '000' return cls.strptime(ts, cls.mediawikiTSFormat) def isoformat(self, sep='T'): """ Convert object to an ISO 8601 timestamp accepted by MediaWiki. datetime.datetime.isoformat does not postfix the ISO formatted date with a 'Z' unless a timezone is included, which causes MediaWiki ~1.19 and earlier to fail. """ return self.strftime(self._ISO8601Format(sep)) toISOformat = redirect_func(isoformat, old_name='toISOformat', class_name='Timestamp', since='20141219') def totimestampformat(self): """Convert object to a MediaWiki internal timestamp.""" return self.strftime(self.mediawikiTSFormat) def __str__(self): """Return a string format recognized by the API.""" return self.isoformat() def __add__(self, other): """Perform addition, returning a Timestamp instead of datetime.""" newdt = super(Timestamp, self).__add__(other) if isinstance(newdt, datetime.datetime): return Timestamp(newdt.year, newdt.month, newdt.day, newdt.hour, newdt.minute, newdt.second, newdt.microsecond, newdt.tzinfo) else: return newdt def __sub__(self, other): """Perform subtraction, returning a Timestamp instead of datetime.""" newdt = super(Timestamp, self).__sub__(other) if isinstance(newdt, datetime.datetime): return Timestamp(newdt.year, newdt.month, newdt.day, newdt.hour, newdt.minute, newdt.second, newdt.microsecond, newdt.tzinfo) else: return newdt
'UploadWarning', 'ServerError', 'FatalServerError', 'Server504Error', 'CaptchaError', 'SpamfilterError', 'CircularRedirect', 'InterwikiRedirectPage', 'WikiBaseError', 'CoordinateGlobeUnknownException', 'QuitKeyboardInterrupt', ) __all__ += textlib_methods if PY2: # T111615: Python 2 requires __all__ is bytes globals()['__all__'] = tuple(bytes(item) for item in __all__) for _name in textlib_methods: target = getattr(textlib, _name) wrapped_func = redirect_func(target) globals()[_name] = wrapped_func deprecated = redirect_func(__deprecated) deprecate_arg = redirect_func(_deprecate_arg) class Timestamp(datetime.datetime): """Class for handling MediaWiki timestamps. This inherits from datetime.datetime, so it can use all of the methods and operations of a datetime object. To ensure that the results of any operation are also a Timestamp object, be sure to use only Timestamp objects (and datetime.timedeltas) in any operation.
if PY2: # T111615: Python 2 requires __all__ is bytes globals()['__all__'] = tuple(bytes(item) for item in __all__) import sys warn(""" Python {version} will be dropped {when}. It is recommended to use Python 3.5 or above. See T213287 for further information. """.format(version=sys.version.split(None, 1)[0], when='soon' if PYTHON_VERSION < (2, 7, 9) else 'in 2020'), FutureWarning) for _name in textlib_methods: target = getattr(textlib, _name) wrapped_func = redirect_func(target, since='20140820') globals()[_name] = wrapped_func deprecated = redirect_func(__deprecated) deprecate_arg = redirect_func(_deprecate_arg) class Timestamp(datetime.datetime): """Class for handling MediaWiki timestamps. This inherits from datetime.datetime, so it can use all of the methods and operations of a datetime object. To ensure that the results of any operation are also a Timestamp object, be sure to use only Timestamp objects (and datetime.timedeltas) in any operation.
'TitleblacklistError', 'CircularRedirect', 'InterwikiRedirectPage', 'WikiBaseError', 'CoordinateGlobeUnknownException', 'QuitKeyboardInterrupt', ) __all__ += textlib_methods if PY2: # T111615: Python 2 requires __all__ is bytes globals()['__all__'] = tuple(bytes(item) for item in __all__) for _name in textlib_methods: target = getattr(textlib, _name) wrapped_func = redirect_func(target) globals()[_name] = wrapped_func deprecated = redirect_func(__deprecated) deprecate_arg = redirect_func(_deprecate_arg) if sys.version_info[:2] == (2, 7) and sys.version_info[2] in (2, 3): warn( 'Pywikibot will soon drop support for Python 2.7.2 and 2.7.3, ' 'please update your Python.', DeprecationWarning, ) class Timestamp(datetime.datetime): """Class for handling MediaWiki timestamps.
_sites[key] = interface(code=code, fam=fam, user=user) debug( "Instantiated %s object '%s'" % (interface.__name__, _sites[key]), _logger) if _sites[key].code != code: warn( 'Site %s instantiated using different code "%s"' % (_sites[key], code), UserWarning, 2) return _sites[key] # alias for backwards-compability getSite = redirect_func(Site, old_name='getSite', since='20150924', future_warning=True) # These imports depend on Wb* classes above. from pywikibot.page import ( # noqa: E402 Page, FilePage, Category, Link, SiteLink, User, ItemPage, PropertyPage, Claim, ) from pywikibot.page import ( # noqa: E402 html2unicode, url2unicode, unicode2html) link_regex = re.compile(r'\[\[(?P<title>[^\]|[<>{}]*)(\|.*?)?\]\]') def showDiff(oldtext, newtext, context=0): """
'UploadWarning', 'ServerError', 'FatalServerError', 'Server504Error', 'CaptchaError', 'SpamfilterError', 'CircularRedirect', 'WikiBaseError', 'CoordinateGlobeUnknownException', 'QuitKeyboardInterrupt', ) # flake8 is unable to detect concatenation in the same operation # like: # ) + textlib_methods # pep257 also doesn't support __all__ multiple times in a document # so instead use this trick globals()['__all__'] = globals()['__all__'] + textlib_methods for _name in textlib_methods: target = getattr(textlib, _name) wrapped_func = redirect_func(target) globals()[_name] = wrapped_func deprecated = redirect_func(pywikibot.tools.deprecated) deprecate_arg = redirect_func(pywikibot.tools.deprecate_arg) class Timestamp(datetime.datetime): """Class for handling MediaWiki timestamps. This inherits from datetime.datetime, so it can use all of the methods and operations of a datetime object. To ensure that the results of any operation are also a Timestamp object, be sure to use only Timestamp objects (and datetime.timedeltas) in any operation.
class Timestamp(datetime.datetime): """Class for handling MediaWiki timestamps. This inherits from datetime.datetime, so it can use all of the methods and operations of a datetime object. To ensure that the results of any operation are also a Timestamp object, be sure to use only Timestamp objects (and datetime.timedeltas) in any operation. Use Timestamp.fromISOformat() and Timestamp.fromtimestampformat() to create Timestamp objects from MediaWiki string formats. As these constructors are typically used to create objects using data passed provided by site and page methods, some of which return a Timestamp when previously they returned a MediaWiki string representation, these methods also accept a Timestamp object, in which case they return a clone. Use Site.getcurrenttime() for the current time; this is more reliable than using Timestamp.utcnow(). """ mediawikiTSFormat = "%Y%m%d%H%M%S" ISO8601Format = "%Y-%m-%dT%H:%M:%SZ" def clone(self): """Clone this instance.""" return self.replace(microsecond=self.microsecond) @classmethod def fromISOformat(cls, ts): """Convert an ISO 8601 timestamp to a Timestamp object.""" # If inadvertantly passed a Timestamp object, use replace() # to create a clone. if isinstance(ts, cls): return ts.clone() return cls.strptime(ts, cls.ISO8601Format) @classmethod def fromtimestampformat(cls, ts): """Convert a MediaWiki internal timestamp to a Timestamp object.""" # If inadvertantly passed a Timestamp object, use replace() # to create a clone. if isinstance(ts, cls): return ts.clone() return cls.strptime(ts, cls.mediawikiTSFormat) def isoformat(self): """ Convert object to an ISO 8601 timestamp accepted by MediaWiki. datetime.datetime.isoformat does not postfix the ISO formatted date with a 'Z' unless a timezone is included, which causes MediaWiki ~1.19 and earlier to fail. """ return self.strftime(self.ISO8601Format) toISOformat = redirect_func(isoformat, old_name='toISOformat', class_name='Timestamp') def totimestampformat(self): """Convert object to a MediaWiki internal timestamp.""" return self.strftime(self.mediawikiTSFormat) def __str__(self): """Return a string format recognized by the API.""" return self.isoformat() def __add__(self, other): """Perform addition, returning a Timestamp instead of datetime.""" newdt = super(Timestamp, self).__add__(other) if isinstance(newdt, datetime.datetime): return Timestamp(newdt.year, newdt.month, newdt.day, newdt.hour, newdt.minute, newdt.second, newdt.microsecond, newdt.tzinfo) else: return newdt def __sub__(self, other): """Perform substraction, returning a Timestamp instead of datetime.""" newdt = super(Timestamp, self).__sub__(other) if isinstance(newdt, datetime.datetime): return Timestamp(newdt.year, newdt.month, newdt.day, newdt.hour, newdt.minute, newdt.second, newdt.microsecond, newdt.tzinfo) else: return newdt