Xqt submitted this change.

View Change


Approvals: Xqt: Verified; Looks good to me, approved
[bugfix] No longer lazy load cookies

Backport from master

Lazy load of cookies was introduced with ba56084 when cookie files for
each user was introduced because the username was needed first load the
cookie. But this change needs an explicit login() call and was a
regression against Pywikibot 7.6.

- always make a cookie-only login when a Site was initialzed
- try to login if API response is 'notloggedin'; this is the
same behaviour as for 'readapidenied'

Bug: T331315
Bug: T330488
Bug: T329132
Bug: T326779
Bug: T271858
Change-Id: I27421439d542df1ca5512998b364fa87b8a69537
---
M tests/utils.py
M pywikibot/site/_apisite.py
M pywikibot/data/api/_requests.py
3 files changed, 71 insertions(+), 25 deletions(-)

diff --git a/pywikibot/data/api/_requests.py b/pywikibot/data/api/_requests.py
index 9d4dc8e..fc3a23c 100644
--- a/pywikibot/data/api/_requests.py
+++ b/pywikibot/data/api/_requests.py
@@ -947,8 +947,11 @@
return True

def submit(self) -> dict:
- """
- Submit a query and parse the response.
+ """Submit a query and parse the response.
+
+ .. versionchanged:: 8.0.4
+ in addition to *readapidenied* also try to login when API
+ response is *notloggedin*.

:return: a dict containing data retrieved from api.php
"""
@@ -1042,8 +1045,8 @@
self._ratelimited()
continue

- # If readapidenied is returned try to login
- if code == 'readapidenied' \
+ # If notloggedin or readapidenied is returned try to login
+ if code in ('notloggedin', 'readapidenied') \
and self.site._loginstatus in (LoginStatus.NOT_ATTEMPTED,
LoginStatus.NOT_LOGGED_IN):
self.site.login()
diff --git a/pywikibot/site/_apisite.py b/pywikibot/site/_apisite.py
index 01ee1ac..793aaf9 100644
--- a/pywikibot/site/_apisite.py
+++ b/pywikibot/site/_apisite.py
@@ -118,11 +118,13 @@
super().__init__(code, fam, user)
self._globaluserinfo: Dict[Union[int, str], Any] = {}
self._interwikimap = _InterwikiMap(self)
- self._loginstatus = login.LoginStatus.NOT_ATTEMPTED
self._msgcache: Dict[str, str] = {}
self._paraminfo = api.ParamInfo(self)
self._siteinfo = Siteinfo(self)
self._tokens = TokenWallet(self)
+ self._loginstatus = login.LoginStatus.NOT_ATTEMPTED
+ with suppress(SiteDefinitionError):
+ self.login(cookie_only=True)

def __getstate__(self) -> Dict[str, Any]:
"""Remove TokenWallet before pickling, for security reasons."""
@@ -324,12 +326,17 @@
def login(
self,
autocreate: bool = False,
- user: Optional[str] = None
+ user: Optional[str] = None,
+ *,
+ cookie_only: bool = False
) -> None:
"""Log the user in if not already logged in.

- .. versionchanged:: 8.0
- lazy load cookies when logging in.
+ .. versionchanged:: 8.0.0
+ lazy load cookies when logging in. This was dropped in 8.0.4
+ .. versionchanged:: 8.0.4
+ the *cookie_only* parameter was added and cookies are loaded
+ whenever the site is initialized.

.. seealso:: :api:`Login`

@@ -337,6 +344,8 @@
using unified login
:param user: bot user name. Overrides the username set by
BaseSite initializer parameter or user config setting
+ :param cookie_only: Only try to login from cookie but do not
+ force to login with username/password settings.

:raises pywikibot.exceptions.NoUsernameError: Username is not
recognised by the site.
@@ -404,23 +413,22 @@

raise NoUsernameError(error_msg)

- login_manager = login.ClientLoginManager(site=self,
- user=self.username())
- if login_manager.login(retry=True, autocreate=autocreate):
- self._username = login_manager.username
- del self.userinfo # force reloading
+ if not cookie_only:
+ login_manager = login.ClientLoginManager(site=self,
+ user=self.username())
+ if login_manager.login(retry=True, autocreate=autocreate):
+ self._username = login_manager.username
+ del self.userinfo # force reloading

- # load userinfo
- if self.userinfo['name'] == self.username():
- self._loginstatus = login.LoginStatus.AS_USER
- return
+ # load userinfo
+ if self.userinfo['name'] == self.username():
+ self._loginstatus = login.LoginStatus.AS_USER
+ return

- pywikibot.error('{} != {} after {}.login() and successful '
- '{}.login()'
- .format(self.userinfo['name'],
- self.username(),
- type(self).__name__,
- type(login_manager).__name__))
+ pywikibot.error(
+ f"{self.userinfo['name']} != {self.username()} after "
+ f'{type(self).__name__}.login() and successful '
+ f'{type(login_manager).__name__}.login()')

self._loginstatus = login.LoginStatus.NOT_LOGGED_IN # failure

@@ -538,7 +546,8 @@
assert 'userinfo' in uidata['query'], \
"API userinfo response lacks 'userinfo' key"
self._userinfo = uidata['query']['userinfo']
- if 'anon' in self._userinfo or not self._userinfo.get('id'):
+ if self._loginstatus != login.LoginStatus.IN_PROGRESS \
+ and ('anon' in self._userinfo or not self._userinfo.get('id')):
pywikibot.warning('No user is logged in on site {}'
.format(self))
return self._userinfo
diff --git a/tests/utils.py b/tests/utils.py
index c71658d..5a49e16 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -1,6 +1,6 @@
"""Test utilities."""
#
-# (C) Pywikibot team, 2013-2022
+# (C) Pywikibot team, 2013-2023
#
# Distributed under the terms of the MIT license.
#
@@ -400,6 +400,15 @@
interface=DryDataSite)
return None

+ def login(self, *args, cookie_only=False, **kwargs):
+ """Overwrite login which is called when a site is initialized.
+
+ .. versionadded: 8.0.4
+ """
+ if cookie_only:
+ return
+ raise Exception(f'Attempting to login with {type(self).__name__}')
+

class DryDataSite(DrySite, pywikibot.site.DataSite):


To view, visit change 908207. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: pywikibot/core
Gerrit-Branch: stable
Gerrit-Change-Id: I27421439d542df1ca5512998b364fa87b8a69537
Gerrit-Change-Number: 908207
Gerrit-PatchSet: 3
Gerrit-Owner: Xqt <info@gno.de>
Gerrit-Reviewer: Xqt <info@gno.de>
Gerrit-Reviewer: jenkins-bot
Gerrit-MessageType: merged