jenkins-bot merged this change.

View Change

Approvals: Xqt: Looks good to me, approved jenkins-bot: Verified
Handle closed_wikis as read-only

+ complete closed_wikis network
+ fix wikimania subdomain site

Detached from I68b5754d54f8

Bug: T74674
Change-Id: I78c538834555660becb2b304460c66d127bbbb9e
---
M pywikibot/families/wikimania_family.py
M pywikibot/family.py
M pywikibot/site.py
M tests/dry_site_tests.py
M tests/family_tests.py
M tests/site_tests.py
6 files changed, 94 insertions(+), 10 deletions(-)

diff --git a/pywikibot/families/wikimania_family.py b/pywikibot/families/wikimania_family.py
index 53d4dac..881e57e 100644
--- a/pywikibot/families/wikimania_family.py
+++ b/pywikibot/families/wikimania_family.py
@@ -8,10 +8,11 @@
from __future__ import absolute_import, division, unicode_literals

from pywikibot import family
+from pywikibot.tools import classproperty


# The Wikimania family
-class Family(family.WikimediaOrgFamily):
+class Family(family.SubdomainFamily, family.WikimediaFamily):

"""Family class for Wikimania wikis."""

@@ -19,7 +20,22 @@

closed_wikis = [
'2005', '2006', '2007', '2008', '2009', '2010', '2011', '2012', '2013',
- '2014', '2015', '2016', '2017', '2018',
+ '2014', '2015', '2016', '2017', '2018'
]

+ codes = ['wikimania']
+
+ code_aliases = {'2019': 'wikimania'}
+
interwiki_forward = 'wikipedia'
+
+ @classproperty
+ def langs(cls):
+ """Property listing family languages."""
+ codes = cls.codes + cls.closed_wikis
+
+ # shortcut this classproperty
+ cls.langs = {code: '{}{}.{}'.format(cls.name, code, cls.domain)
+ for code in codes if code != 'wikimania'}
+ cls.langs['wikimania'] = 'wikimania.{}'.format(cls.domain)
+ return cls.langs
diff --git a/pywikibot/family.py b/pywikibot/family.py
index fb9671a..7d7dd69 100644
--- a/pywikibot/family.py
+++ b/pywikibot/family.py
@@ -1258,7 +1258,10 @@
if code in self.codes:
pywikibot.warn('Interwiki removal %s is in %s codes'
% (code, self))
- return 'RemovedSite'
+ if code in self.closed_wikis:
+ return 'ClosedSite'
+ if code in self.removed_wikis:
+ return 'RemovedSite'

return config.site_interface

diff --git a/pywikibot/site.py b/pywikibot/site.py
index de25366..d9b1cc3 100644
--- a/pywikibot/site.py
+++ b/pywikibot/site.py
@@ -66,6 +66,7 @@
UnknownExtension,
UnknownSite,
UserBlocked,
+ UserRightsError,
)
from pywikibot.throttle import Throttle
from pywikibot.tools import (
@@ -1307,10 +1308,11 @@
"""
def decorator(fn):
def callee(self, *args, **kwargs):
- if self.obsolete:
- raise UnknownSite('Language %s in family %s is obsolete'
- % (self.code, self.family.name))
grp = kwargs.pop('as_group', group)
+ if self.obsolete and not self.has_group('steward'):
+ raise UserRightsError('Site {} has been closed. Only steward '
+ 'can perform requested action.'
+ .format(self.sitename))
if grp == 'user':
self.login(False)
elif grp == 'sysop':
@@ -7456,6 +7458,63 @@
class_name='APISite', since='20141218')


+class ClosedSite(APISite):
+ """Site closed to read-only mode."""
+
+ def __init__(self, code, fam, user=None, sysop=None):
+ """Initializer."""
+ super(ClosedSite, self).__init__(code, fam, user, sysop)
+
+ def _closed_error(self, notice=''):
+ """An error instead of pointless API call."""
+ pywikibot.error('Site {} has been closed. {}'.format(self.sitename,
+ notice))
+
+ def page_restrictions(self, page):
+ """Return a dictionary reflecting page protections."""
+ if not self.page_exists(page):
+ raise NoPage(page)
+ if not hasattr(page, '_protection'):
+ page._protection = {'edit': ('steward', 'infinity'),
+ 'move': ('steward', 'infinity'),
+ 'delete': ('steward', 'infinity'),
+ 'upload': ('steward', 'infinity'),
+ 'create': ('steward', 'infinity')}
+ return page._protection
+
+ def page_can_be_edited(self, page):
+ """Determine if the page can be edited."""
+ rest = self.page_restrictions(page)
+ sysop_protected = 'edit' in rest and rest['edit'][0] == 'steward'
+ try:
+ api.LoginManager(site=self, sysop=sysop_protected)
+ except NoUsername:
+ return False
+ return True
+
+ def recentchanges(self, **kwargs):
+ """An error instead of pointless API call."""
+ self._closed_error('No recent changes can be returned.')
+
+ def is_uploaddisabled(self):
+ """Return True if upload is disabled on site."""
+ if not hasattr(self, '_uploaddisabled'):
+ self._uploaddisabled = True
+ return self._uploaddisabled
+
+ def newpages(self, **kwargs):
+ """An error instead of pointless API call."""
+ self._closed_error('No new pages can be returned.')
+
+ def newfiles(self, **kwargs):
+ """An error instead of pointless API call."""
+ self._closed_error('No new files can be returned.')
+
+ def newimages(self, *args, **kwargs):
+ """An error instead of pointless API call."""
+ self._closed_error('No new images can be returned.')
+
+
class DataSite(APISite):

"""Wikibase data capable site."""
diff --git a/tests/dry_site_tests.py b/tests/dry_site_tests.py
index b49aadc..95d0ffc 100644
--- a/tests/dry_site_tests.py
+++ b/tests/dry_site_tests.py
@@ -11,7 +11,7 @@
from pywikibot.tools import deprecated
from pywikibot.site import must_be, need_version
from pywikibot.comms.http import user_agent
-from pywikibot.exceptions import UnknownSite
+from pywikibot.exceptions import UserRightsError

from tests.aspects import (
unittest,
@@ -137,6 +137,7 @@
self.code = 'test'
self.family = lambda: None
self.family.name = 'test'
+ self.sitename = self.family.name + ':' + self.code
self._logged_in_as = None
self.obsolete = False
super(TestMustBe, self).setUp()
@@ -146,6 +147,10 @@
"""Fake the log in and just store who logged in."""
self._logged_in_as = 'sysop' if sysop else 'user'

+ def has_group(self, group):
+ """Fake the groups user belongs to."""
+ return False
+
def testMockInTest(self):
"""Test that setUp and login work."""
self.assertIsNone(self._logged_in_as)
@@ -198,7 +203,7 @@
self.obsolete = True
args = (1, 2, 'a', 'b')
kwargs = {'i': 'j', 'k': 'l'}
- self.assertRaises(UnknownSite, self.call_this_user_req_function,
+ self.assertRaises(UserRightsError, self.call_this_user_req_function,
args, kwargs)


diff --git a/tests/family_tests.py b/tests/family_tests.py
index 43db8ed..8361090 100644
--- a/tests/family_tests.py
+++ b/tests/family_tests.py
@@ -53,7 +53,7 @@
self.assertIsInstance(f.languages_by_size, list)
self.assertGreaterEqual(set(f.langs), set(f.languages_by_size))
if len(f.langs) > 2 and f.name not in {
- 'wikimediachapter', 'vikidia', 'wikidata',
+ 'wikimediachapter', 'vikidia', 'wikidata', 'wikimania'
}:
self.assertNotEqual(f.languages_by_size, [])
if isinstance(f, SingleSiteFamily):
diff --git a/tests/site_tests.py b/tests/site_tests.py
index 63d5cc2..6c177b5 100644
--- a/tests/site_tests.py
+++ b/tests/site_tests.py
@@ -3390,10 +3390,11 @@
self.assertEqual(site.code, 'mh')
self.assertIsInstance(site.obsolete, bool)
self.assertTrue(site.obsolete)
- self.assertRaises(KeyError, site.hostname)
+ self.assertIsNotNone(site.hostname)
r = http.fetch(uri='http://mh.wikipedia.org/w/api.php',
default_error_handling=False)
self.assertEqual(r.status, 200)
+ self.assertEqual(site.siteinfo['lang'], 'mh')

def test_removed_site(self):
"""Test Wikimedia offline site."""

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

Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: I78c538834555660becb2b304460c66d127bbbb9e
Gerrit-Change-Number: 517031
Gerrit-PatchSet: 13
Gerrit-Owner: Dvorapa <dvorapa@seznam.cz>
Gerrit-Reviewer: Alex Monk <krenair@gmail.com>
Gerrit-Reviewer: Dvorapa <dvorapa@seznam.cz>
Gerrit-Reviewer: Framawiki <framawiki@tools.wmflabs.org>
Gerrit-Reviewer: JAn Dudík <jan.dudik@gmail.com>
Gerrit-Reviewer: John Vandenberg <jayvdb@gmail.com>
Gerrit-Reviewer: Kronf <wolpi.kronf@web.de>
Gerrit-Reviewer: Liuxinyu970226 <541329866@qq.com>
Gerrit-Reviewer: MZMcBride <w@mzmcbride.com>
Gerrit-Reviewer: Masti <mastigm@gmail.com>
Gerrit-Reviewer: Matěj Suchánek <matejsuchanek97@gmail.com>
Gerrit-Reviewer: Mpaa <mpaa.wiki@gmail.com>
Gerrit-Reviewer: Nemo bis <federicoleva@tiscali.it>
Gerrit-Reviewer: Octahedron80 <octahedron80@hotmail.com>
Gerrit-Reviewer: Ricordisamoa <ricordisamoa@openmailbox.org>
Gerrit-Reviewer: Thibaut120094 <thibaut120094@outlook.fr>
Gerrit-Reviewer: XZise <CommodoreFabianus@gmx.de>
Gerrit-Reviewer: Xqt <info@gno.de>
Gerrit-Reviewer: Zhuyifei1999 <zhuyifei1999@gmail.com>
Gerrit-Reviewer: Zppix <Megadev44s.mail@gmail.com>
Gerrit-Reviewer: jenkins-bot (75)