jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/626873 )
Change subject: [bugfix] setuptools does not have svn_utils any longer
......................................................................
[bugfix] setuptools does not have svn_utils any longer
- svn_utils support of setuptools was removed with v33.0.0 (01 Jan 2017);
setuptools_svn is required for that
- pip 10.0.0 (2018-04-14) does not support that old setuptools;
current release is 20.2.3
Change-Id: Ib6bd99fc851ddd313be1d3ef1217ae1afd207423
---
M pywikibot/version.py
1 file changed, 1 insertion(+), 4 deletions(-)
Approvals:
Matěj Suchánek: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/version.py b/pywikibot/version.py
index a0d5eb0..376c8c5 100644
--- a/pywikibot/version.py
+++ b/pywikibot/version.py
@@ -224,10 +224,7 @@
- hash (git hash for the Subversion revision)
@rtype: C{tuple} of three C{str} and a C{time.struct_time}
"""
- try:
- from setuptools import svn_utils
- except ImportError:
- from setuptools_svn import svn_utils
+ from setuptools_svn import svn_utils
tag = 'pywikibot-core'
_program_dir = path or _get_program_dir()
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/626873
To unsubscribe, or for help writing mail filters, visit https://gerrit.wikimedia.org/r/settings
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: Ib6bd99fc851ddd313be1d3ef1217ae1afd207423
Gerrit-Change-Number: 626873
Gerrit-PatchSet: 1
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: Matěj Suchánek <matejsuchanek97(a)gmail.com>
Gerrit-Reviewer: jenkins-bot
Gerrit-MessageType: merged
jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/625720 )
Change subject: [IMPR] Print login status to log file if 'badtoken' API error occures
......................................................................
[IMPR] Print login status to log file if 'badtoken' API error occures
Bug: T261050
Change-Id: Idf69faf2fdb4e77242bd76bbfd97f4c40f28e99a
---
M pywikibot/data/api.py
1 file changed, 16 insertions(+), 12 deletions(-)
Approvals:
Matěj Suchánek: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/data/api.py b/pywikibot/data/api.py
index 4c896fd..9063528 100644
--- a/pywikibot/data/api.py
+++ b/pywikibot/data/api.py
@@ -1870,8 +1870,12 @@
def _bad_token(self, code) -> bool:
"""Check for bad token."""
- if (code != 'badtoken' or self.site._loginstatus
- == pywikibot.site.LoginStatus.IN_PROGRESS):
+ if code != 'badtoken': # Other code not handled here
+ return False
+
+ if self.site._loginstatus == pywikibot.site.LoginStatus.IN_PROGRESS:
+ pywikibot.log('Login status: {}'
+ .format(self.site._loginstatus.name))
return False
user_tokens = self.site.tokens._tokens[self.site.user()]
@@ -1897,16 +1901,16 @@
for name, t_type in invalid_param.items():
self[name] = self.site.tokens[t_type]
return True
- else:
- # otherwise couldn't find any … weird there is nothing what
- # can be done here because it doesn't know which parameters
- # to fix
- pywikibot.log(
- 'Bad token error for {} but no parameter is using a '
- 'token. Current tokens: {}'
- .format(self.site.user(),
- ', '.join('{}: {}'.format(*e)
- for e in user_tokens.items())))
+
+ # otherwise couldn't find any … weird there is nothing what
+ # can be done here because it doesn't know which parameters
+ # to fix
+ pywikibot.log(
+ 'Bad token error for {} but no parameter is using a '
+ 'token. Current tokens: {}'
+ .format(self.site.user(),
+ ', '.join('{}: {}'.format(*e)
+ for e in user_tokens.items())))
return False
def submit(self) -> dict:
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/625720
To unsubscribe, or for help writing mail filters, visit https://gerrit.wikimedia.org/r/settings
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: Idf69faf2fdb4e77242bd76bbfd97f4c40f28e99a
Gerrit-Change-Number: 625720
Gerrit-PatchSet: 6
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: Matěj Suchánek <matejsuchanek97(a)gmail.com>
Gerrit-Reviewer: Multichill <maarten(a)mdammers.nl>
Gerrit-Reviewer: jenkins-bot
Gerrit-MessageType: merged
jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/620504 )
Change subject: [bugfix] load siteinfo from API if expiry=True in Siteinfo.get() method
......................................................................
[bugfix] load siteinfo from API if expiry=True in Siteinfo.get() method
- Siteinfo._is_expired(): follow boolean expire value
- Siteinfo.get(): test for not isinstance(expiry, (bool, timedelta))
because a boolean variable is an instance of int too
- Siteinfo.get(): do not load siteinfof from cache if expiry is True
- assign force to Siteinfo.get() in __call__ method
- use expiry=True instead of expiry=0
- fix result in Site.live_version method according to the doc typing hint
- simplify some code
- add some type hints
Bug: T260490
Change-Id: I2d7214996cfc5197a3eddc9495d50106ef726fa4
---
M pywikibot/site/__init__.py
1 file changed, 51 insertions(+), 54 deletions(-)
Approvals:
Matěj Suchánek: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/site/__init__.py b/pywikibot/site/__init__.py
index 8a4200e..6b1c978 100644
--- a/pywikibot/site/__init__.py
+++ b/pywikibot/site/__init__.py
@@ -30,6 +30,7 @@
from enum import IntEnum
from itertools import zip_longest
from textwrap import fill
+from typing import Optional
from urllib.parse import urlparse
from warnings import warn
@@ -1253,7 +1254,7 @@
self._cache = {}
@staticmethod
- def _get_default(key):
+ def _get_default(key: str):
"""
Return the default value for different properties.
@@ -1265,7 +1266,6 @@
Otherwise it returns L{pywikibot.tools.EMPTY_DEFAULT}.
@param key: The property name
- @type key: str
@return: The default value
@rtype: dict or L{pywikibot.tools.EmptyDefault}
"""
@@ -1277,11 +1277,12 @@
'levels': ['', 'autoconfirmed', 'sysop'],
'types': ['create', 'edit', 'move', 'upload']
}
- elif key == 'fileextensions':
+
+ if key == 'fileextensions':
# the default file extensions in MediaWiki
return [{'ext': ext} for ext in ['png', 'gif', 'jpg', 'jpeg']]
- else:
- return pywikibot.tools.EMPTY_DEFAULT
+
+ return pywikibot.tools.EMPTY_DEFAULT
@staticmethod
def _post_process(prop, data):
@@ -1309,7 +1310,7 @@
for p in Siteinfo.BOOLEAN_PROPS[prop]:
data[p] = p in data
- def _get_siteinfo(self, prop, expiry):
+ def _get_siteinfo(self, prop, expiry) -> dict:
"""
Retrieve a siteinfo property.
@@ -1325,7 +1326,6 @@
@return: A dictionary with the properties of the site. Each entry in
the dictionary is a tuple of the value and a boolean to save if it
is the default value.
- @rtype: dict (the values)
@see: U{https://www.mediawiki.org/wiki/API:Meta#siteinfo_.2F_si}
"""
def warn_handler(mod, message):
@@ -1338,12 +1338,10 @@
else:
return False
- if isinstance(prop, str):
- props = [prop]
- else:
- props = prop
- if len(props) == 0:
+ props = [prop] if isinstance(prop, str) else prop
+ if not props:
raise ValueError('At least one property name must be provided.')
+
invalid_properties = []
request = self._site._request(
expiry=pywikibot.config.API_config_expiry
@@ -1373,8 +1371,7 @@
for prop in props:
results.update(self._get_siteinfo(prop, expiry))
return results
- else:
- raise
+ raise
else:
result = {}
if invalid_properties:
@@ -1395,15 +1392,16 @@
@staticmethod
def _is_expired(cache_date, expire):
"""Return true if the cache date is expired."""
- if expire is False: # can never expire
- return False
- elif not cache_date: # default values are always expired
- return True
- else:
- # cached date + expiry are in the past if it's expired
- return cache_date + expire < datetime.datetime.utcnow()
+ if isinstance(expire, bool):
+ return expire
- def _get_general(self, key, expiry):
+ if not cache_date: # default values are always expired
+ return True
+
+ # cached date + expiry are in the past if it's expired
+ return cache_date + expire < datetime.datetime.utcnow()
+
+ def _get_general(self, key: str, expiry):
"""
Return a siteinfo property which is loaded by default.
@@ -1413,7 +1411,6 @@
always all results.
@param key: The key to search for.
- @type key: str
@param expiry: If the cache is older than the expiry it ignores the
cache and queries the server to get the newest value.
@type expiry: int (days), L{datetime.timedelta}, False (never)
@@ -1445,11 +1442,12 @@
else:
return None
- def __getitem__(self, key):
+ def __getitem__(self, key: str):
"""Return a siteinfo property, caching and not forcing it."""
return self.get(key, False) # caches and doesn't force it
- def get(self, key, get_default=True, cache=True, expiry=False):
+ def get(self, key: str, get_default: bool = True, cache: bool = True,
+ expiry=False):
"""
Return a siteinfo property.
@@ -1457,28 +1455,28 @@
property doesn't exist. Instead it will use the default value.
@param key: The name of the siteinfo property.
- @type key: str
@param get_default: Whether to throw an KeyError if the key is invalid.
- @type get_default: bool
@param cache: Caches the result internally so that future accesses via
this method won't query the server.
- @type cache: bool
@param expiry: If the cache is older than the expiry it ignores the
cache and queries the server to get the newest value.
- @type expiry: int/float (days), L{datetime.timedelta}, False (never)
+ @type expiry: int/float (days), L{datetime.timedelta},
+ False (never expired), True (always expired)
@return: The gathered property
@rtype: various
@raises KeyError: If the key is not a valid siteinfo property and the
get_default option is set to False.
@see: L{_get_siteinfo}
"""
+ # If expiry is a float or int convert to timedelta
+ # Note: bool is an instance of int
+ if isinstance(expiry, float) or type(expiry) == int:
+ expiry = datetime.timedelta(expiry)
+
# expire = 0 (or timedelta(0)) are always expired and their bool is
# False, so skip them EXCEPT if it's literally False, then they expire
- # never: "expiry is False" is different than "not expiry"!
- # if it's a int convert to timedelta
- if expiry is not False and isinstance(expiry, (int, float)):
- expiry = datetime.timedelta(expiry)
- if expiry or expiry is False:
+ # never.
+ if expiry and expiry is not True or expiry is False:
try:
cached = self._get_cached(key)
except KeyError:
@@ -1487,21 +1485,24 @@
# is a default value, but isn't accepted
if not cached[1] and not get_default:
raise KeyError(key)
- elif not Siteinfo._is_expired(cached[1], expiry):
+ if not Siteinfo._is_expired(cached[1], expiry):
return copy.deepcopy(cached[0])
+
preloaded = self._get_general(key, expiry)
if not preloaded:
preloaded = self._get_siteinfo(key, expiry)[key]
else:
cache = False
+
if not preloaded[1] and not get_default:
raise KeyError(key)
- else:
- if cache:
- self._cache[key] = preloaded
- return copy.deepcopy(preloaded[0])
- def _get_cached(self, key):
+ if cache:
+ self._cache[key] = preloaded
+
+ return copy.deepcopy(preloaded[0])
+
+ def _get_cached(self, key: str):
"""Return the cached value or a KeyError exception if not cached."""
if 'general' in self._cache:
if key in self._cache['general'][0]:
@@ -1511,7 +1512,7 @@
return self._cache[key]
raise KeyError(key)
- def __contains__(self, key):
+ def __contains__(self, key: str) -> bool:
"""Return whether the value is cached."""
try:
self._get_cached(key)
@@ -1520,15 +1521,12 @@
else:
return True
- def is_recognised(self, key):
+ def is_recognised(self, key: str) -> Optional[bool]:
"""Return if 'key' is a valid property name. 'None' if not cached."""
time = self.get_requested_time(key)
- if time is None:
- return None
- else:
- return bool(time)
+ return None if time is None else bool(time)
- def get_requested_time(self, key):
+ def get_requested_time(self, key: str):
"""
Return when 'key' was successfully requested from the server.
@@ -1536,24 +1534,23 @@
last request from the 'general' siprop.
@param key: The siprop value or a property of 'general'.
- @type key: basestring
@return: The last time the siprop of 'key' was requested.
@rtype: None (never), False (default), L{datetime.datetime} (cached)
"""
- try:
+ with suppress(KeyError):
return self._get_cached(key)[1]
- except KeyError:
- return None
+
+ return None
def __call__(self, key='general', force=False, dump=False):
"""DEPRECATED: Return the entry for key or dump the complete cache."""
issue_deprecation_warning(
'Calling siteinfo', 'itself as a dictionary', since='20161221'
)
+ result = self.get(key, expiry=force)
if not dump:
- return self.get(key, expiry=0 if force else False)
+ return result
else:
- self.get(key, expiry=0 if force else False)
return self._cache
@@ -2351,7 +2348,7 @@
"""
if self.mw_version >= '1.16':
return pywikibot.Timestamp.fromISOformat(
- self.siteinfo.get('time', expiry=0))
+ self.siteinfo.get('time', expiry=True))
else:
return pywikibot.Timestamp.fromtimestampformat(
self.expand_text('{{CURRENTTIMESTAMP}}'))
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/620504
To unsubscribe, or for help writing mail filters, visit https://gerrit.wikimedia.org/r/settings
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: I2d7214996cfc5197a3eddc9495d50106ef726fa4
Gerrit-Change-Number: 620504
Gerrit-PatchSet: 7
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: D3r1ck01 <xsavitar.wiki(a)aol.com>
Gerrit-Reviewer: Matěj Suchánek <matejsuchanek97(a)gmail.com>
Gerrit-Reviewer: jenkins-bot
Gerrit-MessageType: merged
jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/625647 )
Change subject: [doc] Update ROADMAP.rst
......................................................................
[doc] Update ROADMAP.rst
Change-Id: I370a9c32c819f6b93e535dd362f81fc374347b7a
---
M ROADMAP.rst
1 file changed, 8 insertions(+), 1 deletion(-)
Approvals:
Matěj Suchánek: Looks good to me, approved
jenkins-bot: Verified
diff --git a/ROADMAP.rst b/ROADMAP.rst
index 898d948..b0ce70e 100644
--- a/ROADMAP.rst
+++ b/ROADMAP.rst
@@ -1,13 +1,21 @@
Current release changes
~~~~~~~~~~~~~~~~~~~~~~~
+* Move latest revision id handling to WikibaseEntity (T233406)
+* Load wikibase entities when necessary (T245809)
+* Fix path for stable release in version.getversion() (T262558)
+* "since" parameter in EventStreams given as Timestamp or MediaWiki timestamp string has been fixed
+* Some methods deprecated for 6 years or longer were removed
+* Page.getVersionHistory and Page.fullVersionHistory() methods were removed (T136513, T151110)
* Allow multiple types of contributors parameter given for Page.revision_count()
* Deprecated tools.UnicodeMixin and tools.IteratorNextMixin has been removed
+* Localisation updates
Future release notes
~~~~~~~~~~~~~~~~~~~~
+* 4.3.0: Unsused UserBlocked exception will be removed
* 4.3.0: Deprecated Page.contributingUsers() will be removed
* 4.2.0: tools.StringTypes will be removed
* 4.1.0: Deprecated editor.command will be removed
@@ -15,5 +23,4 @@
* 4.1.0: comms.PywikibotCookieJar and comms.mode_check_decorator will be removed
* 4.0.0: Unused parameters of page methods like forceReload, insite, throttle, step will be removed
* 4.0.0: Methods deprecated for 6 years or longer will be removed
-* 3.0.20200508: Page.getVersionHistory and Page.fullVersionHistory() methods will be removed (T136513, T151110)
* 3.0.20200306: Support of MediaWiki releases below 1.19 will be dropped (T245350)
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/625647
To unsubscribe, or for help writing mail filters, visit https://gerrit.wikimedia.org/r/settings
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: I370a9c32c819f6b93e535dd362f81fc374347b7a
Gerrit-Change-Number: 625647
Gerrit-PatchSet: 3
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: Matěj Suchánek <matejsuchanek97(a)gmail.com>
Gerrit-Reviewer: jenkins-bot
Gerrit-MessageType: merged
jenkins-bot has submitted this change. ( https://gerrit.wikimedia.org/r/c/pywikibot/core/+/599292 )
Change subject: [IMPR] Move latest revision id handling to WikibaseEntity
......................................................................
[IMPR] Move latest revision id handling to WikibaseEntity
Nevertheless, users should avoid relying on this. The
implementation seems hacky because unlike standard MediaWiki
pages, Pywikibot doesn't strictly bind Wikibase entities
with revisions.
Bug: T233406
Change-Id: I8353d31d744cdff5a980d9f179cf9f6c3e30095f
---
M pywikibot/page/__init__.py
1 file changed, 38 insertions(+), 11 deletions(-)
Approvals:
Xqt: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/page/__init__.py b/pywikibot/page/__init__.py
index e6dbf17..9ad8bb2 100644
--- a/pywikibot/page/__init__.py
+++ b/pywikibot/page/__init__.py
@@ -3830,6 +3830,29 @@
norm_data[key] = attr.normalizeData(data[key])
return norm_data
+ @property
+ def latest_revision_id(self) -> Optional[int]:
+ """
+ Get the revision identifier for the most recent revision of the entity.
+
+ @rtype: int or None if it cannot be determined
+ @raise NoWikibaseEntity: if the entity doesn't exist
+ """
+ if not hasattr(self, '_revid'):
+ # fixme: unlike BasePage.latest_revision_id, this raises
+ # exception when entity is redirect, cannot use get_redirect
+ self.get()
+ return self._revid
+
+ @latest_revision_id.setter
+ def latest_revision_id(self, value: Optional[int]) -> None:
+ self._revid = value
+
+ @latest_revision_id.deleter
+ def latest_revision_id(self) -> None:
+ if hasattr(self, '_revid'):
+ del self._revid
+
def exists(self) -> bool:
"""Determine if an entity exists in the data repository."""
if not hasattr(self, '_content'):
@@ -3865,6 +3888,8 @@
if 'missing' in self._content:
raise pywikibot.NoWikibaseEntity(self)
+ self.latest_revision_id = self._content.get('lastrevid')
+
data = {}
for key, cls in self.DATA_ATTRIBUTES.items():
value = cls.fromJSON(self._content.get(key, {}), self.repo)
@@ -3884,7 +3909,10 @@
else:
data = self._normalizeData(data)
- updates = self.repo.editEntity(self, data, **kwargs)
+ baserevid = getattr(self, '_revid', None)
+
+ updates = self.repo.editEntity(
+ self, data, baserevid=baserevid, **kwargs)
# the attribute may have been unset in ItemPage
if getattr(self, 'id', '-1') == '-1':
@@ -4099,9 +4127,6 @@
# todo: raise a nicer exception here (T87345)
raise pywikibot.NoPage(self)
- if 'lastrevid' in self._content:
- self.latest_revision_id = self._content['lastrevid']
-
if 'pageid' in self._content:
self._pageid = self._content['pageid']
@@ -4113,7 +4138,12 @@
@property
def latest_revision_id(self) -> int:
- """Get revision identifier for the most recent revision of entity."""
+ """
+ Get the revision identifier for the most recent revision of the entity.
+
+ @rtype: int
+ @raise pywikibot.exceptions.NoPage: if the entity doesn't exist
+ """
if not hasattr(self, '_revid'):
self.get()
return self._revid
@@ -4124,6 +4154,7 @@
@latest_revision_id.deleter
def latest_revision_id(self):
+ # fixme: this seems too destructive in comparison to the parent
self.clear_cache()
@allow_asynchronous
@@ -4149,12 +4180,8 @@
by bots that need to keep track of which saves were successful.
@type callback: callable
"""
- if hasattr(self, '_revid'):
- baserevid = self.latest_revision_id
- else:
- baserevid = None
-
- super().editEntity(data, baserevid=baserevid, **kwargs)
+ # kept for the decorator
+ super().editEntity(data, **kwargs)
def editLabels(self, labels, **kwargs):
"""
--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/599292
To unsubscribe, or for help writing mail filters, visit https://gerrit.wikimedia.org/r/settings
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: I8353d31d744cdff5a980d9f179cf9f6c3e30095f
Gerrit-Change-Number: 599292
Gerrit-PatchSet: 2
Gerrit-Owner: Matěj Suchánek <matejsuchanek97(a)gmail.com>
Gerrit-Reviewer: Matěj Suchánek <matejsuchanek97(a)gmail.com>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot
Gerrit-MessageType: merged