Page MenuHomePhabricator

pywikibot: Support non-global login
Open, Needs TriagePublicFeature

Description

Feature summary: Allow logins to be encapsulated to an object, rather than being global.

Use case(s): It would allow switching between multiple logins in a single instance for the same wiki.

Benefits (why should this be implemented?): Currently, switching between multiple users for the same wiki is unsupported. Something like a webservice would require that one server can run requests for multiple identities at the same time, or without running separate processes.

Event Timeline

There are several ways to login with multiple accounts.
Refer the mailing list:
https://lists.wikimedia.org/hyperkitty/list/pywikibot@lists.wikimedia.org/thread/6BYXIFHJL7PAKLDIIKFWKWDVFZNMJ63T/

You also can have multiple config files with -config option.

What do you need additionally?

I am asking that when I login as a user, it can be stored as an object. I have written a script that is not ran by the pwb wrapper script, and it will not function without a user-config.py file. I am not interested in adding the pywikibot argument parsing logic to my script, so I have intentionally avoided loading it through that since I have my own parsing logic with argparse. What I would like is a pywikibot.login(username, password), pywikibot.login(username, oauth_consumer_key=...), and maybe for OAuth2 a pywikibot.oauth2_login(access_token) method. All of these should return some form of pywikibot.Login object which I can pass along to pywikibot.Site. Basically, I am looking for a way to sign in where if I login inside a function, that login does not persist outside of the stack of the function. Hypothetically:

def do_something():
    login = pywikibot.login(username, password)
    site = pywikibot.Site("wikidata", "wikidata", login=login)
    // Do my wikidata things here

def main():
    do_something()
    site = pywikibot.Site("wikidata", "wikidata")
    pywikibot.ItemPage(site, "Q1").addClaim(...) // Error: Not logged in!

pywikibot.Site() already has some functionality you required, you can give the user account with it and login after it:

D:\pwb\GIT\core>pwb shell
Welcome to the Pywikibot interactive shell!
>>> site = pywikibot.Site('wikipedia:de', user='xqt')
>>> site.login()
Password for user Xqt on wikipedia:de (no characters will be shown):
Logging in to wikipedia:de as Xqt
Bitte gib einen Verifizierungscode von deinem Authentifizierungsgerät ein.:
>>> site.logged_in()
True
>>>

https://doc.wikimedia.org/pywikibot/master/api_ref/pywikibot.html#pywikibot.Site
(The previous was a 2FA example)

Also site.login() has a parameter to give the user name.
https://doc.wikimedia.org/pywikibot/master/api_ref/pywikibot.site.html#pywikibot.site._apisite.APISite.login

You may use a bot password file for login parameters. user-config.py is recommended but not mandatory. You may have multiple config files using the -config global option. Global options can always be used even if you have your own option parser and you don't use pywikibot.handle_args() for example:

pwb [<global options>] <your script> [<script options>]

https://doc.wikimedia.org/pywikibot/master/utilities/scripts_ref.html#module-pywikibot.scripts.wrapper
https://doc.wikimedia.org/pywikibot/master/global_options.html#global-options

Thanks, that is really helpful. The final piece of the puzzle that would help is if I could provide the password to site.login() (for example if I collected it from a form). That would allow non-interactive logins of users unknown at initial launch.

Change 862219 had a related patch set uploaded (by Xqt; author: Xqt):

[pywikibot/core@master] [IMPR] Provide password option with Site.login()

https://gerrit.wikimedia.org/r/862219

You should not be collecting user passwords since doing so would compromise the account. Use OAuth instead.

You should not be collecting user passwords since doing so would compromise the account. Use OAuth instead.

I am aware. I am actually using OAuth2, but that still isn't implemented in pywikibot.