Page MenuHomePhabricator

-user fails when -lang not set for single site family
Open, Needs TriagePublic


BaseSite.__init__ has some special logic to support single site families, where it updates the global configuration variable "mylang" to the sites declared 'code' for its only site.

This allows users to only specify -family:mediawiki without needing to also specify -lang:mediawiki . However this breaks when the -user option is also used. The global argument -user is handled in bot.handle_args, which is before any BaseSite is initialised, so the incorrect lang code is used in bot.handle_args to add the username, but then in the lang has changed so it doesnt find the stored and raises NoUsername.


python replace -family:mediawiki -user:JVbot -search:pywikipedia pywikipedia pywikibot
WARNING: .../pywikibot/ UserWarning: Global configuration variable "mylang" changed to "mediawiki" while instantiating site mediawiki:mediawiki
WARNING: .../pywikibot/ UserWarning: Site mediawiki:mediawiki instantiated using different code "en"
  self._site = pywikibot.Site()

The summary message for the command line replacements will be something like: Bot: Automated text replacement  (-pywikipedia +pywikibot)
Press Enter to use this automatic message, or enter a description of the
changes your bot will make: 
Traceback (most recent call last):
  File "", line 256, in <module>
    if not main():
  File "", line 250, in main
    run_python_file(filename, [filename] + args, argvu, file_package)
  File "", line 121, in run_python_file
  File "./scripts/", line 1131, in <module>
  File "./scripts/", line 1121, in main
  File ".../pywikibot/", line 2056, in login
  File ".../pywikibot/tools/", line 1368, in wrapper
    return obj(*__args, **__kw)
  File ".../pywikibot/", line 115, in __init__
pywikibot.exceptions.NoUsername: ERROR: Username for mediawiki:mediawiki is undefined.
If you have an account for that site, please add a line to

usernames['mediawiki']['mediawiki'] = 'myUsername'
<class 'pywikibot.exceptions.NoUsername'>
CRITICAL: Closing network session.

Essentially, instantiating a class shouldnt change global configuration, as it is unreliable (especially if used in a multi threaded app).

The same situation can be reliably without -user:. If the user-config sets to be a single site family like commons, and config.mylang is en:

  1. Instantiate an APISite for 'wikipedia:' + config.mylang
  2. Instantiate an APISite for commons (mylang is now 'commons')
  3. use 'wikipedia:' + config.mylang assuming it refers to the same site instantiated in step 1, which would try to access non-existent site wikipedia:commons

Any usage of in pywikibot core , except in pywikibot.Site, should be audited to ensure it works correctly if config.mylang is changed after the pywikibot bootstrap and 'bot'-strap.

Event Timeline

One workaround is to update bot.handle_args to load the Family defined by and adjust config.mylang if it is a single site family. Then BaseSite.__init__ doesnt need to update it. At least then the change to the global variable only occurs once, during the parsing of the command line options.
However, some uses of the library do not call bot.handle_args, so a lower level initialisation hook would be better.

Another workaround is to add more patchy code into BaseSite.__init__ to also fix the config.usernames dict after it has updated config.mylang.

It's 2019 and this isn't even mentioned in the documentation page yet.

Please link the documentation page, where it is missing so we can add it there! :)

I assume the

WARNING: /opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/pywikibot/ UserWarning: Global configuration variable "mylang" changed to "royalfamily" while instantiating site royalfamily:royalfamily

in to be based on ths issue has no reference of this issue. It might be sensible to link a "known problems" section.