1"""Objects representing interwiki map of MediaWiki site.""" 2# 3# (C) Pywikibot team, 2015-2021 4# 5# Distributed under the terms of the MIT license. 6# 7import pywikibot 8from pywikibot.backports import Set 9 10 11class _IWEntry: 12 13 """An entry of the _InterwikiMap with a lazy loading site.""" 14 15 def __init__(self, local, url, prefix=None): 16 self._site = None 17 self.local = local 18 self.url = url 19 self.prefix = prefix 20 21 @property 22 def site(self): 23 if self._site is None: 24 try: 25 self._site = pywikibot.Site( 26 url=self.url, fam=None if self.local else self.prefix) 27 except Exception as e: 28 self._site = e 29 return self._site 30 31 32class _InterwikiMap: 33 34 """A representation of the interwiki map of a site.""" 35 36 def __init__(self, site): 37 """ 38 Create an empty uninitialized interwiki map for the given site. 39 40 :param site: Given site for which interwiki map is to be created 41 :type site: pywikibot.site.APISite 42 """ 43 super().__init__() 44 self._site = site 45 self._map = None 46 47 def reset(self): 48 """Remove all mappings to force building a new mapping.""" 49 self._map = None 50 51 @property 52 def _iw_sites(self): 53 """Fill the interwikimap cache with the basic entries.""" 54 # _iw_sites is a local cache to return an APISite instance depending 55 # on the interwiki prefix of that site 56 if self._map is None: 57 self._map = {iw['prefix']: _IWEntry('local' in iw, 58 iw['url'], 59 iw['prefix']) 60 for iw in self._site.siteinfo['interwikimap']} 61 return self._map 62 63 def __getitem__(self, prefix): 64 """ 65 Return the site, locality and url for the requested prefix. 66 67 :param prefix: Interwiki prefix 68 :type prefix: Dictionary key 69 :rtype: _IWEntry 70 :raises KeyError: Prefix is not a key 71 :raises TypeError: Site for the prefix is of wrong type 72 """ 73 if prefix not in self._iw_sites: 74 raise KeyError("'{}' is not an interwiki prefix.".format(prefix)) 75 if isinstance(self._iw_sites[prefix].site, pywikibot.site.BaseSite): 76 return self._iw_sites[prefix] 77 if isinstance(self._iw_sites[prefix].site, Exception): 78 raise self._iw_sites[prefix].site 79 raise TypeError('_iw_sites[{}] is wrong type: {}' 80 .format(prefix, type(self._iw_sites[prefix].site))) 81 82 def get_by_url(self, url: str) -> Set[str]: 83 """ 84 Return a set of prefixes applying to the URL. 85 86 :param url: URL for the interwiki 87 """ 88 return {prefix for prefix, iw_entry in self._iw_sites.items() 89 if iw_entry.url == url} 90