def error_handling_callback(request): """ Raise exceptions and log alerts. @param request: Request that has completed @type request: L{threadedhttp.HttpRequest} """ # TODO: do some error correcting stuff if isinstance(request.data, requests.exceptions.SSLError): if SSL_CERT_VERIFY_FAILED_MSG in str(request.data): raise FatalServerError(str(request.data)) # if all else fails if isinstance(request.data, Exception): raise request.data if request.status == 504: raise Server504Error("Server %s timed out" % request.hostname) if request.status == 414: raise Server414Error('Too long GET request') # HTTP status 207 is also a success status for Webdav FINDPROP, # used by the version module. if request.status not in (200, 207): warning('Http response status {0}'.format(request.data.status_code))
def error_handling_callback(request): """ Raise exceptions and log alerts. @param request: Request that has completed @type request: L{threadedhttp.HttpRequest} """ # TODO: do some error correcting stuff if isinstance(request.data, requests.exceptions.SSLError): if SSL_CERT_VERIFY_FAILED_MSG in str(request.data): raise FatalServerError(str(request.data)) if request.status_code == 504: raise Server504Error('Server {} timed out'.format( urlparse(request.url).netloc)) if request.status_code == 414: raise Server414Error('Too long GET request') if isinstance(request.data, Exception): error('An error occurred for uri ' + request.url) raise request.data from None # HTTP status 207 is also a success status for Webdav FINDPROP, # used by the version module. if request.status_code not in (200, 207): warning('Http response status {}'.format(request.status_code))
def _code_fam_from_url(url: str, name: Optional[str] = None): """Set url to cache and get code and family from cache. Site helper method. @param url: The site URL to get code and family @param name: A family name used by AutoFamily """ matched_sites = [] # Iterate through all families and look, which does apply to # the given URL for fam in config.family_files: family = Family.load(fam) code = family.from_url(url) if code is not None: matched_sites.append((code, family)) if not matched_sites: if not name: # create a name from url name = urlparse(url).netloc.split('.')[-2] name = removesuffix(name, 'wiki') family = AutoFamily(name, url) matched_sites.append((family.code, family)) if len(matched_sites) > 1: warning('Found multiple matches for URL "{}": {} (use first)'.format( url, ', '.join(str(s) for s in matched_sites))) return matched_sites[0]
def error_handling_callback(response): """ Raise exceptions and log alerts. :param response: Response returned by Session.request(). :type response: :py:obj:`requests.Response` """ # TODO: do some error correcting stuff if isinstance(response, requests.exceptions.SSLError): if SSL_CERT_VERIFY_FAILED_MSG in str(response): raise FatalServerError(str(response)) if isinstance(response, Exception): with suppress(Exception): # request exception may contain response and request attribute error('An error occurred for uri ' + response.request.url) raise response from None if response.status_code == HTTPStatus.GATEWAY_TIMEOUT: raise Server504Error('Server {} timed out'.format( urlparse(response.url).netloc)) if response.status_code == HTTPStatus.REQUEST_URI_TOO_LONG: raise Server414Error('Too long GET request') # TODO: shall it raise? this might break some code, TBC # response.raise_for_status() # HTTP status 207 is also a success status for Webdav FINDPROP, # used by the version module. if response.status_code not in (HTTPStatus.OK, HTTPStatus.MULTI_STATUS): warning('Http response status {}'.format(response.status_code))
def _code_fam_from_url(url): """Set url to cache and get code and family from cache. Site helper method. @param url: The site URL to get code and family @type url: str @raises SiteDefinitionError: Unknown URL """ if url not in _url_cache: matched_sites = [] # Iterate through all families and look, which does apply to # the given URL for fam in config.family_files: if fam == 'test': # test_family.py is deprecated continue family = Family.load(fam) code = family.from_url(url) if code is not None: matched_sites.append((code, family)) if not matched_sites: # TODO: As soon as AutoFamily is ready, try and use an # AutoFamily raise SiteDefinitionError("Unknown URL '{0}'.".format(url)) if len(matched_sites) > 1: warning('Found multiple matches for URL "{0}": {1} (use first)' .format(url, ', '.join(str(s) for s in matched_sites))) _url_cache[url] = matched_sites[0] return _url_cache[url]
def _code_fam_from_url(url): """Set url to cache and get code and family from cache. Site helper method. @param url: The site URL to get code and family @type url: str @raises SiteDefinitionError: Unknown URL """ if url not in _url_cache: matched_sites = [] # Iterate through all families and look, which does apply to # the given URL for fam in config.family_files: family = Family.load(fam) code = family.from_url(url) if code is not None: matched_sites.append((code, family)) if not matched_sites: # TODO: As soon as AutoFamily is ready, try and use an # AutoFamily raise SiteDefinitionError("Unknown URL '{0}'.".format(url)) if len(matched_sites) > 1: warning('Found multiple matches for URL "{0}": {1} (use first)' .format(url, ', '.join(str(s) for s in matched_sites))) _url_cache[url] = matched_sites[0] return _url_cache[url]
def _require_errors(site: DataSite) -> bool: """ Check if Wikibase site is so old it requires error bounds to be given. If no site item is supplied it raises a warning and returns True. @param site: The Wikibase site """ if not site: warning( "WbQuantity now expects a 'site' parameter. This is needed to " 'ensure correct handling of error bounds.') return False return site.mw_version < '1.29.0-wmf.2'
def _require_errors(site): """ Check if the Wikibase site is so old it requires error bounds to be given. If no site item is supplied it raises a warning and returns True. @param site: The Wikibase site @type site: pywikibot.site.DataSite @rtype: bool """ if not site: warning( "WbQuantity now expects a 'site' parameter. This is needed to " "ensure correct handling of error bounds.") return False return MediaWikiVersion(site.version()) < MediaWikiVersion('1.29.0-wmf.2')
def error_handling_callback(response): """ Raise exceptions and log alerts. @param response: Response returned by Session.request(). @type response: L{requests.Response} """ # TODO: do some error correcting stuff if isinstance(response, requests.exceptions.SSLError): if SSL_CERT_VERIFY_FAILED_MSG in str(response): raise FatalServerError(str(response)) if isinstance(response, Exception): with suppress(Exception): # request.data exception may contain response and request attribute error('An error occurred for uri ' + response.request.url) raise response from None if response.status_code == 504: raise Server504Error('Server {} timed out'.format( urlparse(response.url).netloc)) if response.status_code == 414: raise Server414Error('Too long GET request') # TODO: shall it raise? this might break some code, TBC # response.raise_for_status() # HTTP status 207 is also a success status for Webdav FINDPROP, # used by the version module. if response.status_code not in (200, 207): warning('Http response status {}'.format(response.status_code)) if isinstance(response.encoding, UnicodeDecodeError): error('An error occurred for uri {}: ' 'no encoding detected!'.format(response.request.url)) raise response.encoding from None
def _code_fam_from_url(url: str): """Set url to cache and get code and family from cache. Site helper method. @param url: The site URL to get code and family @raises pywikibot.exceptions.SiteDefinitionError: Unknown URL """ matched_sites = [] # Iterate through all families and look, which does apply to # the given URL for fam in config.family_files: family = Family.load(fam) code = family.from_url(url) if code is not None: matched_sites.append((code, family)) if not matched_sites: # TODO: As soon as AutoFamily is ready, try and use an # AutoFamily raise SiteDefinitionError("Unknown URL '{}'.".format(url)) if len(matched_sites) > 1: warning('Found multiple matches for URL "{}": {} (use first)' .format(url, ', '.join(str(s) for s in matched_sites))) return matched_sites[0]
def Site(code=None, fam=None, user=None, sysop=None, interface=None, url=None): """A factory method to obtain a Site object. Site objects are cached and reused by this method. By default rely on config settings. These defaults may all be overridden using the method parameters. @param code: language code (override config.mylang) @type code: str @param fam: family name or object (override config.family) @type fam: str or Family @param user: bot user name to use on this site (override config.usernames) @type user: str @param sysop: sysop user to use on this site (override config.sysopnames) @type sysop: str @param interface: site class or name of class in pywikibot.site (override config.site_interface) @type interface: subclass of L{pywikibot.site.BaseSite} or string @param url: Instead of code and fam, does try to get a Site based on the URL. Still requires that the family supporting that URL exists. @type url: str @rtype: pywikibot.site.APISite @raises ValueError: URL and pair of code and family given @raises ValueError: Invalid interface name @raises SiteDefinitionError: Unknown URL """ _logger = 'wiki' if url: # Either code and fam or only url if code or fam: raise ValueError( 'URL to the wiki OR a pair of code and family name ' 'should be provided') code, fam = _code_fam_from_url(url) else: # Fallback to config defaults code = code or config.mylang fam = fam or config.family if not isinstance(fam, Family): fam = Family.load(fam) interface = interface or fam.interface(code) # config.usernames is initialised with a defaultdict for each family name family_name = str(fam) code_to_user = config.usernames['*'].copy() code_to_user.update(config.usernames[family_name]) user = user or code_to_user.get(code) or code_to_user.get('*') code_to_sysop = config.sysopnames['*'].copy() code_to_sysop.update(config.sysopnames[family_name]) sysop = sysop or code_to_sysop.get(code) or code_to_sysop.get('*') if not isinstance(interface, type): # If it isn't a class, assume it is a string if PY2: # Must not be unicode in Python 2 interface = str(interface) try: tmp = __import__('pywikibot.site', fromlist=[interface]) except ImportError: raise ValueError('Invalid interface name: {0}'.format(interface)) else: interface = getattr(tmp, interface) if not issubclass(interface, BaseSite): warning('Site called with interface=%s' % interface.__name__) user = normalize_username(user) key = '%s:%s:%s:%s' % (interface.__name__, fam, code, user) if key not in _sites or not isinstance(_sites[key], interface): _sites[key] = interface(code=code, fam=fam, user=user, sysop=sysop) debug("Instantiated %s object '%s'" % (interface.__name__, _sites[key]), _logger) if _sites[key].code != code: warn('Site %s instantiated using different code "%s"' % (_sites[key], code), UserWarning, 2) return _sites[key]
for _key, _val in _glv.items(): if isinstance(_val, dict): if isinstance(_val, collections.defaultdict): _uc[_key] = collections.defaultdict(dict) else: _uc[_key] = {} if len(_val) > 0: _uc[_key].update(_val) else: _uc[_key] = _val # Get the user files _thislevel = 0 if __no_user_config: if __no_user_config != '2': warning('Skipping loading of user-config.py.') _fns = [] else: _fns = [os.path.join(_base_dir, "user-config.py")] for _filename in _fns: _thislevel += 1 if os.path.exists(_filename): _filestatus = os.stat(_filename) _filemode = _filestatus[0] _fileuid = _filestatus[4] if OSWIN32 or _fileuid in [os.getuid(), 0]: if OSWIN32 or _filemode & 0o02 == 0: with open(_filename, 'rb') as f: exec(compile(f.read(), _filename, 'exec'), _uc) else: warning("Skipped '%(fn)s': writeable by others." %
def Site(code=None, fam=None, user=None, sysop=None, interface=None, url=None): """A factory method to obtain a Site object. Site objects are cached and reused by this method. By default rely on config settings. These defaults may all be overridden using the method parameters. @param code: language code (override config.mylang) @type code: string @param fam: family name or object (override config.family) @type fam: string or Family @param user: bot user name to use on this site (override config.usernames) @type user: unicode @param sysop: sysop user to use on this site (override config.sysopnames) @type sysop: unicode @param interface: site class or name of class in pywikibot.site (override config.site_interface) @type interface: subclass of L{pywikibot.site.BaseSite} or string @param url: Instead of code and fam, does try to get a Site based on the URL. Still requires that the family supporting that URL exists. @type url: string @rtype: pywikibot.site.APISite """ # Either code and fam or only url if url and (code or fam): raise ValueError('URL to the wiki OR a pair of code and family name ' 'should be provided') _logger = "wiki" if url: if url not in _url_cache: matched_sites = [] # Iterate through all families and look, which does apply to # the given URL for fam in config.family_files: family = Family.load(fam) code = family.from_url(url) if code is not None: matched_sites += [(code, family)] if matched_sites: if len(matched_sites) > 1: warning( 'Found multiple matches for URL "{0}": {1} (use first)' .format(url, ', '.join(str(s) for s in matched_sites))) _url_cache[url] = matched_sites[0] else: # TODO: As soon as AutoFamily is ready, try and use an # AutoFamily _url_cache[url] = None cached = _url_cache[url] if cached: code = cached[0] fam = cached[1] else: raise SiteDefinitionError("Unknown URL '{0}'.".format(url)) else: # Fallback to config defaults code = code or config.mylang fam = fam or config.family if not isinstance(fam, Family): fam = Family.load(fam) interface = interface or fam.interface(code) # config.usernames is initialised with a defaultdict for each family name family_name = str(fam) code_to_user = config.usernames['*'].copy() code_to_user.update(config.usernames[family_name]) user = user or code_to_user.get(code) or code_to_user.get('*') code_to_sysop = config.sysopnames['*'].copy() code_to_sysop.update(config.sysopnames[family_name]) sysop = sysop or code_to_sysop.get(code) or code_to_sysop.get('*') if not isinstance(interface, type): # If it isnt a class, assume it is a string try: tmp = __import__('pywikibot.site', fromlist=[interface]) interface = getattr(tmp, interface) except ImportError: raise ValueError('Invalid interface name: {0}'.format(interface)) if not issubclass(interface, BaseSite): warning('Site called with interface=%s' % interface.__name__) user = normalize_username(user) key = '%s:%s:%s:%s' % (interface.__name__, fam, code, user) if key not in _sites or not isinstance(_sites[key], interface): _sites[key] = interface(code=code, fam=fam, user=user, sysop=sysop) debug(u"Instantiated %s object '%s'" % (interface.__name__, _sites[key]), _logger) if _sites[key].code != code: warn('Site %s instantiated using different code "%s"' % (_sites[key], code), UserWarning, 2) return _sites[key]
# System-level and User-level changes. # Store current variables and their types. _public_globals = { _key: _val for _key, _val in globals().items() if _key[0] != '_' and _key not in _imports} # Create an environment for user-config.py which is # a deep copy of the core config settings, so that # we can detect modified config items easily. _exec_globals = copy.deepcopy(_public_globals) # Get the user files if __no_user_config: if __no_user_config != '2': warning('Skipping loading of user-config.py.') else: _filename = os.path.join(base_dir, 'user-config.py') if os.path.exists(_filename): _filestatus = os.stat(_filename) _filemode = _filestatus[0] _fileuid = _filestatus[4] if OSWIN32 or _fileuid in [os.getuid(), 0]: if OSWIN32 or _filemode & 0o02 == 0: with open(_filename, 'rb') as f: exec(compile(f.read(), _filename, 'exec'), _exec_globals) else: warning("Skipped '%(fn)s': writeable by others." % {'fn': _filename}) else: warning("Skipped '%(fn)s': owned by someone else."
# Store current variables and their types. _public_globals = { _key: _val for _key, _val in globals().items() if _key[0] != '_' and _key not in _imports } # Create an environment for user-config.py which is # a deep copy of the core config settings, so that # we can detect modified config items easily. _exec_globals = copy.deepcopy(_public_globals) # Get the user files if __no_user_config: if __no_user_config != '2': warning('Skipping loading of user-config.py.') else: _filename = os.path.join(base_dir, 'user-config.py') def read_user_config(): with open(_filename, 'rb') as f: exec(compile(f.read(), _filename, 'exec'), _exec_globals) if os.path.exists(_filename): _filestatus = os.stat(_filename) _filemode = _filestatus[0] _fileuid = _filestatus[4] if OSWIN32 or _fileuid in [os.getuid(), 0]: if OSWIN32 or _filemode & 0o02 == 0: read_user_config() else:
for _key, _val in _glv.items(): if isinstance(_val, dict): if isinstance(_val, collections.defaultdict): _uc[_key] = collections.defaultdict(dict) else: _uc[_key] = {} if len(_val) > 0: _uc[_key].update(_val) else: _uc[_key] = _val # Get the user files _thislevel = 0 if __no_user_config: if __no_user_config != "2": warning("Skipping loading of user-config.py.") _fns = [] else: _fns = [os.path.join(_base_dir, "user-config.py")] for _filename in _fns: _thislevel += 1 if os.path.exists(_filename): _filestatus = os.stat(_filename) _filemode = _filestatus[0] _fileuid = _filestatus[4] if OSWIN32 or _fileuid in [os.getuid(), 0]: if OSWIN32 or _filemode & 0o02 == 0: with open(_filename, "rb") as f: exec(compile(f.read(), _filename, "exec"), _uc) else: warning("Skipped '%(fn)s': writeable by others." % {"fn": _filename})
def Site(code: Optional[str] = None, fam=None, user: Optional[str] = None, *, interface=None, url: Optional[str] = None) -> Union[APISite, DataSite, ClosedSite]: """A factory method to obtain a Site object. Site objects are cached and reused by this method. By default rely on config settings. These defaults may all be overridden using the method parameters. @param code: language code (override config.mylang) code may also be a sitename like 'wikipedia:test' @param fam: family name or object (override config.family) @type fam: str or pywikibot.family.Family @param user: bot user name to use on this site (override config.usernames) @param interface: site class or name of class in pywikibot.site (override config.site_interface) @type interface: subclass of L{pywikibot.site.BaseSite} or string @param url: Instead of code and fam, does try to get a Site based on the URL. Still requires that the family supporting that URL exists. @raises ValueError: URL and pair of code and family given @raises ValueError: Invalid interface name """ _logger = 'wiki' if url: # Either code and fam or url with optional fam for AutoFamily name if code: raise ValueError( 'URL to the wiki OR a pair of code and family name ' 'should be provided') code, fam = _code_fam_from_url(url, fam) elif code and ':' in code: if fam: raise ValueError('sitename OR a pair of code and family name ' 'should be provided') fam, _, code = code.partition(':') else: # Fallback to config defaults code = code or config.mylang fam = fam or config.family if not isinstance(fam, Family): fam = Family.load(fam) interface = interface or fam.interface(code) # config.usernames is initialised with a defaultdict for each family name family_name = str(fam) code_to_user = {} if '*' in config.usernames: # T253127: usernames is a defaultdict code_to_user = config.usernames['*'].copy() code_to_user.update(config.usernames[family_name]) user = user or code_to_user.get(code) or code_to_user.get('*') if not isinstance(interface, type): # If it isn't a class, assume it is a string try: tmp = __import__('pywikibot.site', fromlist=[interface]) except ImportError: raise ValueError('Invalid interface name: {0}'.format(interface)) else: interface = getattr(tmp, interface) if not issubclass(interface, BaseSite): warning('Site called with interface=%s' % interface.__name__) user = normalize_username(user) key = '%s:%s:%s:%s' % (interface.__name__, fam, code, user) if key not in _sites or not isinstance(_sites[key], interface): _sites[key] = interface(code=code, fam=fam, user=user) debug( "Instantiated %s object '%s'" % (interface.__name__, _sites[key]), _logger) if _sites[key].code != code: warn( 'Site %s instantiated using different code "%s"' % (_sites[key], code), UserWarning, 2) return _sites[key]
) from pywikibot.logging import critical, debug, error, log, warning from pywikibot.tools import deprecate_arg, issue_deprecation_warning, PY2 import pywikibot.version # The error message for failed SSL certificate verification # 'certificate verify failed' is a commonly detectable string SSL_CERT_VERIFY_FAILED_MSG = 'certificate verify failed' _logger = "comm.http" if (isinstance(config.socket_timeout, tuple) and StrictVersion(requests.__version__) < StrictVersion('2.4.0')): warning('The configured timeout is a tuple but requests does not ' 'support a tuple as a timeout. It uses the lower of the ' 'two.') config.socket_timeout = min(config.socket_timeout) cookie_jar = cookielib.LWPCookieJar( config.datafilepath('pywikibot.lwp')) try: cookie_jar.load() except (IOError, cookielib.LoadError): debug('Loading cookies failed.', _logger) else: debug('Loaded cookies from file.', _logger) session = requests.Session() session.cookies = cookie_jar
def Site(code=None, fam=None, user=None, sysop=None, interface=None, url=None): """A factory method to obtain a Site object. Site objects are cached and reused by this method. By default rely on config settings. These defaults may all be overridden using the method parameters. @param code: language code (override config.mylang) @type code: string @param fam: family name or object (override config.family) @type fam: string or Family @param user: bot user name to use on this site (override config.usernames) @type user: unicode @param sysop: sysop user to use on this site (override config.sysopnames) @type sysop: unicode @param interface: site class or name of class in pywikibot.site (override config.site_interface) @type interface: subclass of L{pywikibot.site.BaseSite} or string @param url: Instead of code and fam, does try to get a Site based on the URL. Still requires that the family supporting that URL exists. @type url: string @rtype: pywikibot.site.APISite """ # Either code and fam or only url if url and (code or fam): raise ValueError('URL to the wiki OR a pair of code and family name ' 'should be provided') _logger = "wiki" if url: if url not in _url_cache: matched_sites = [] # Iterate through all families and look, which does apply to # the given URL for fam in config.family_files: family = Family.load(fam) code = family.from_url(url) if code is not None: matched_sites += [(code, family)] if matched_sites: if len(matched_sites) > 1: warning( 'Found multiple matches for URL "{0}": {1} (use first)' .format(url, ', '.join(str(s) for s in matched_sites))) _url_cache[url] = matched_sites[0] else: # TODO: As soon as AutoFamily is ready, try and use an # AutoFamily _url_cache[url] = None cached = _url_cache[url] if cached: code = cached[0] fam = cached[1] else: raise SiteDefinitionError("Unknown URL '{0}'.".format(url)) else: # Fallback to config defaults code = code or config.mylang fam = fam or config.family if not isinstance(fam, Family): fam = Family.load(fam) interface = interface or fam.interface(code) # config.usernames is initialised with a defaultdict for each family name family_name = str(fam) code_to_user = config.usernames['*'].copy() code_to_user.update(config.usernames[family_name]) user = user or code_to_user.get(code) or code_to_user.get('*') code_to_sysop = config.sysopnames['*'].copy() code_to_sysop.update(config.sysopnames[family_name]) sysop = sysop or code_to_sysop.get(code) or code_to_sysop.get('*') if not isinstance(interface, type): # If it isnt a class, assume it is a string try: tmp = __import__('pywikibot.site', fromlist=[interface]) interface = getattr(tmp, interface) except ImportError: raise ValueError('Invalid interface name: {0}'.format(interface)) if not issubclass(interface, BaseSite): warning('Site called with interface=%s' % interface.__name__) user = normalize_username(user) key = '%s:%s:%s:%s' % (interface.__name__, fam, code, user) if key not in _sites or not isinstance(_sites[key], interface): _sites[key] = interface(code=code, fam=fam, user=user, sysop=sysop) debug( u"Instantiated %s object '%s'" % (interface.__name__, _sites[key]), _logger) if _sites[key].code != code: warn( 'Site %s instantiated using different code "%s"' % (_sites[key], code), UserWarning, 2) return _sites[key]
PY2, StringTypes, ) import pywikibot.version # The error message for failed SSL certificate verification # 'certificate verify failed' is a commonly detectable string SSL_CERT_VERIFY_FAILED_MSG = 'certificate verify failed' _logger = "comm.http" if (isinstance(config.socket_timeout, tuple) and StrictVersion(requests.__version__) < StrictVersion('2.4.0')): warning('The configured timeout is a tuple but requests does not ' 'support a tuple as a timeout. It uses the lower of the ' 'two.') config.socket_timeout = min(config.socket_timeout) cookie_jar = cookielib.LWPCookieJar(config.datafilepath('pywikibot.lwp')) try: cookie_jar.load() except (IOError, cookielib.LoadError): debug('Loading cookies failed.', _logger) else: debug('Loaded cookies from file.', _logger) session = requests.Session() session.cookies = cookie_jar
if _key[0] != '_' and _key not in _imports } # Create an environment for user-config.py which is # a deep copy of the core config settings, so that # we can detect modified config items easily. _exec_globals = copy.deepcopy(_public_globals) # Always try to get the user files _filename = os.path.join(base_dir, 'user-config.py') if os.path.exists(_filename): _filestatus = os.stat(_filename) _filemode = _filestatus[0] _fileuid = _filestatus[4] if not OSWIN32 and _fileuid not in [os.getuid(), 0]: warning('Skipped {fn!r}: owned by someone else.'.format(fn=_filename)) elif OSWIN32 or _filemode & 0o02 == 0: with open(_filename, 'rb') as f: exec(compile(f.read(), _filename, 'exec'), _exec_globals) else: warning('Skipped {fn!r}: writeable by others.'.format(fn=_filename)) elif __no_user_config and __no_user_config != '2': warning('user-config.py cannot be loaded.') class _DifferentTypeError(UserWarning, TypeError): """An error when the required type doesn't match the actual type.""" def __init__(self, name, actual_type, allowed_types): super().__init__('Configuration variable "{}" is defined as "{}" in ' 'your user-config.py but expected "{}".'.format( name, actual_type.__name__,
for _key, _val in _glv.items(): if isinstance(_val, dict): if isinstance(_val, collections.defaultdict): _uc[_key] = collections.defaultdict(dict) else: _uc[_key] = {} if len(_val) > 0: _uc[_key].update(_val) else: _uc[_key] = _val # Get the user files _thislevel = 0 if __no_user_config: if __no_user_config != '2': warning('Skipping loading of user-config.py.') _fns = [] else: _fns = [os.path.join(_base_dir, "user-config.py")] for _filename in _fns: _thislevel += 1 if os.path.exists(_filename): _filestatus = os.stat(_filename) _filemode = _filestatus[0] _fileuid = _filestatus[4] if OSWIN32 or _fileuid in [os.getuid(), 0]: if OSWIN32 or _filemode & 0o02 == 0: with open(_filename, 'rb') as f: exec(compile(f.read(), _filename, 'exec'), _uc) else: warning("Skipped '{fn!s}': writeable by others.".format(**{'fn': _filename}))
for _key, _val in _glv.items(): if isinstance(_val, dict): if isinstance(_val, collections.defaultdict): _uc[_key] = collections.defaultdict(dict) else: _uc[_key] = {} if len(_val) > 0: _uc[_key].update(_val) else: _uc[_key] = _val # Get the user files _thislevel = 0 if _no_user_config: if _no_user_config != '2': warning('Skipping loading of user-config.py.') _fns = [] else: _fns = [os.path.join(_base_dir, "user-config.py")] for _filename in _fns: _thislevel += 1 if os.path.exists(_filename): _filestatus = os.stat(_filename) _filemode = _filestatus[0] _fileuid = _filestatus[4] if sys.platform == 'win32' or _fileuid in [os.getuid(), 0]: if sys.platform == 'win32' or _filemode & 0o02 == 0: with open(_filename, 'rb') as f: exec(compile(f.read(), _filename, 'exec'), _uc) else: warning("Skipped '%(fn)s': writeable by others."
def Site(code: Optional[str] = None, fam: Union[str, 'Family', None] = None, user: Optional[str] = None, *, interface: Union[str, 'BaseSite', None] = None, url: Optional[str] = None) -> BaseSite: """A factory method to obtain a Site object. Site objects are cached and reused by this method. By default rely on config settings. These defaults may all be overridden using the method parameters. Creating the default site using config.mylang and config.family:: site = pywikibot.Site() Override default site code:: site = pywikibot.Site('fr') Override default family:: site = pywikibot.Site(family='wikisource') Setting a specific site:: site = pywikibot.Site('fr', 'wikisource') which is equal to:: site = pywikibot.Site('wikisource:fr') :Note: An already created site is cached an a new variable points to the same object if interface, family, code and user are equal: >>> import pywikibot >>> site_1 = pywikibot.Site('wikisource:fr') >>> site_2 = pywikibot.Site('fr', 'wikisource') >>> site_1 is site_2 True >>> site_1 APISite("fr", "wikisource") ``APISite`` is the default interface. Refer :py:obj:`pywikibot.site` for other interface types. **Never create a site object via interface class directly.** Always use this factory method. :param code: language code (override config.mylang) code may also be a sitename like 'wikipedia:test' :param fam: family name or object (override config.family) :param user: bot user name to use on this site (override config.usernames) :param interface: site class or name of class in :py:obj:`pywikibot.site` (override config.site_interface) :param url: Instead of code and fam, does try to get a Site based on the URL. Still requires that the family supporting that URL exists. :raises ValueError: URL and pair of code and family given :raises ValueError: Invalid interface name :raises ValueError: Missing Site code :raises ValueError: Missing Site family """ _logger = 'wiki' if url: # Either code and fam or url with optional fam for AutoFamily name if code: raise ValueError( 'URL to the wiki OR a pair of code and family name ' 'should be provided') code, fam = _code_fam_from_url(url, fam) elif code and ':' in code: if fam: raise ValueError('sitename OR a pair of code and family name ' 'should be provided') fam, _, code = code.partition(':') else: # Fallback to config defaults code = code or _config.mylang fam = fam or _config.family if not (code and fam): raise ValueError( 'Missing Site {}'.format('code' if not code else 'family')) if not isinstance(fam, Family): fam = Family.load(fam) interface = interface or fam.interface(code) # config.usernames is initialised with a defaultdict for each family name family_name = str(fam) code_to_user = {} if '*' in _config.usernames: # T253127: usernames is a defaultdict code_to_user = _config.usernames['*'].copy() code_to_user.update(_config.usernames[family_name]) user = user or code_to_user.get(code) or code_to_user.get('*') if not isinstance(interface, type): # If it isn't a class, assume it is a string try: tmp = __import__('pywikibot.site', fromlist=[interface]) except ImportError: raise ValueError('Invalid interface name: {}'.format(interface)) else: interface = getattr(tmp, interface) if not issubclass(interface, BaseSite): warning('Site called with interface={}'.format(interface.__name__)) user = normalize_username(user) key = '{}:{}:{}:{}'.format(interface.__name__, fam, code, user) if key not in _sites or not isinstance(_sites[key], interface): _sites[key] = interface(code=code, fam=fam, user=user) debug( "Instantiated {} object '{}'".format(interface.__name__, _sites[key]), _logger) if _sites[key].code != code: warn( 'Site {} instantiated using different code "{}"'.format( _sites[key], code), UserWarning, 2) return _sites[key]