Convert to Python 3 super()

This commit is contained in:
Chris Mayo 2020-06-03 20:06:36 +01:00
parent cec9b78f5e
commit a6b1eb45b1
46 changed files with 83 additions and 85 deletions

View file

@ -286,7 +286,7 @@ class ColoredStreamHandler(logging.StreamHandler):
"""Log to given stream (a file-like object) or to stderr if
strm is None.
"""
super(ColoredStreamHandler, self).__init__(strm)
super().__init__(strm)
self.stream = Colorizer(self.stream)
# standard log level colors (used by get_color)
self.colors = {

View file

@ -107,7 +107,7 @@ class FileUrl(urlbase.UrlBase):
extern,
):
"""Initialize the scheme."""
super(FileUrl, self).init(
super().init(
base_ref,
base_url,
parent_url,
@ -170,7 +170,7 @@ class FileUrl(urlbase.UrlBase):
# ignore query part for filesystem urls
urlparts[3] = ''
self.base_url = urlutil.urlunsplit(urlparts)
super(FileUrl, self).build_url()
super().build_url()
# ignore query and fragment url parts for filesystem urls
self.urlparts[3] = self.urlparts[4] = ''
if self.is_directory() and not self.urlparts[2].endswith('/'):
@ -237,7 +237,7 @@ class FileUrl(urlbase.UrlBase):
if isinstance(data, str):
data = data.encode("iso8859-1", "ignore")
else:
data = super(FileUrl, self).read_content()
data = super().read_content()
return data
def get_os_filename(self):
@ -312,6 +312,4 @@ class FileUrl(urlbase.UrlBase):
if webroot and url and url.startswith("/"):
url = webroot + url[1:]
log.debug(LOG_CHECK, "Applied local webroot `%s' to `%s'.", webroot, url)
super(FileUrl, self).add_url(
url, line=line, column=column, page=page, name=name, base=base
)
super().add_url(url, line=line, column=column, page=page, name=name, base=base)

View file

@ -34,7 +34,7 @@ class FtpUrl(internpaturl.InternPatternUrl, proxysupport.ProxySupport):
"""
Initialize FTP url data.
"""
super(FtpUrl, self).reset()
super().reset()
# list of files for recursion
self.files = []
# last part of URL filename

View file

@ -66,7 +66,7 @@ class HttpUrl(internpaturl.InternPatternUrl, proxysupport.ProxySupport):
"""
Initialize HTTP specific variables.
"""
super(HttpUrl, self).reset()
super().reset()
# initialize check data
# server headers
self.headers = {}

View file

@ -26,7 +26,7 @@ class ItmsServicesUrl(urlbase.UrlBase):
def check_syntax(self):
"""Only logs that this URL is unknown."""
super(ItmsServicesUrl, self).check_syntax()
super().check_syntax()
if "url=" not in self.urlparts[3]:
self.set_result(_("Missing required url parameter"), valid=False)

View file

@ -74,7 +74,7 @@ class MailtoUrl(urlbase.UrlBase):
"""Call super.build_url(), extract list of mail addresses from URL,
and check their syntax.
"""
super(MailtoUrl, self).build_url()
super().build_url()
self.addresses = set()
self.subject = None
self.parse_addresses()

View file

@ -37,7 +37,7 @@ class TelnetUrl(urlbase.UrlBase):
Call super.build_url(), set default telnet port and initialize
the login credentials.
"""
super(TelnetUrl, self).build_url()
super().build_url()
# default port
if self.port is None:
self.port = 23
@ -51,7 +51,7 @@ class TelnetUrl(urlbase.UrlBase):
if not self.host:
self.set_result(_("Host is empty"), valid=False)
return
super(TelnetUrl, self).local_check()
super().local_check()
def check_connection(self):
"""

View file

@ -26,7 +26,7 @@ class UnknownUrl(urlbase.UrlBase):
def build_url(self):
"""Only logs that this URL is unknown."""
super(UnknownUrl, self).build_url()
super().build_url()
if self.is_ignored():
self.add_info(
_("%(scheme)s URL ignored.") % {"scheme": self.scheme.capitalize()}

View file

@ -160,7 +160,7 @@ class Configuration(dict):
"""
Initialize the default options.
"""
super(Configuration, self).__init__()
super().__init__()
# checking options
self["allowedschemes"] = []
self['cookiefile'] = None

View file

@ -45,7 +45,7 @@ class LCConfigParser(RawConfigParser):
def __init__(self, config):
"""Initialize configuration."""
super(LCConfigParser, self).__init__()
super().__init__()
self.config = config
def read(self, files):
@ -55,7 +55,7 @@ class LCConfigParser(RawConfigParser):
"""
assert isinstance(files, list), "Invalid file list %r" % files
try:
self.read_ok = super(LCConfigParser, self).read(files)
self.read_ok = super().read(files)
if len(self.read_ok) < len(files):
failed_files = set(files) - set(self.read_ok)
log.warn(

View file

@ -23,7 +23,7 @@ class LFUCache(dict):
def __init__(self, size=1000):
"""Initialize internal LFU cache."""
super(LFUCache, self).__init__()
super().__init__()
if size < 1:
raise ValueError("invalid cache size %d" % size)
self.size = size
@ -32,9 +32,9 @@ class LFUCache(dict):
"""Store given key/value."""
if key in self:
# store value, do not increase number of uses
super(LFUCache, self).__getitem__(key)[1] = val
super().__getitem__(key)[1] = val
else:
super(LFUCache, self).__setitem__(key, [0, val])
super().__setitem__(key, [0, val])
# check for size limit
if len(self) > self.size:
self.shrink()
@ -43,7 +43,7 @@ class LFUCache(dict):
"""Shrink ca. 5% of entries."""
trim = int(0.05 * len(self))
if trim:
items = super(LFUCache, self).items()
items = super().items()
# sorting function for items
def keyfunc(x): return x[1][0]
values = sorted(items, key=keyfunc)
@ -52,14 +52,14 @@ class LFUCache(dict):
def __getitem__(self, key):
"""Update key usage and return value."""
entry = super(LFUCache, self).__getitem__(key)
entry = super().__getitem__(key)
entry[0] += 1
return entry[1]
def uses(self, key):
"""Get number of uses for given key (without increasing the number of
uses)"""
return super(LFUCache, self).__getitem__(key)[0]
return super().__getitem__(key)[0]
def get(self, key, def_val=None):
"""Update key usage if found and return value, else return default."""
@ -77,28 +77,28 @@ class LFUCache(dict):
def items(self):
"""Return list of items, not updating usage count."""
return [(key, value[1]) for key, value in super(LFUCache, self).items()]
return [(key, value[1]) for key, value in super().items()]
def iteritems(self):
"""Return iterator of items, not updating usage count."""
for key, value in super(LFUCache, self).items():
for key, value in super().items():
yield (key, value[1])
def values(self):
"""Return list of values, not updating usage count."""
return [value[1] for value in super(LFUCache, self).values()]
return [value[1] for value in super().values()]
def itervalues(self):
"""Return iterator of values, not updating usage count."""
for value in super(LFUCache, self).values():
for value in super().values():
yield value[1]
def popitem(self):
"""Remove and return an item."""
key, value = super(LFUCache, self).popitem()
key, value = super().popitem()
return (key, value[1])
def pop(self):
"""Remove and return a value."""
value = super(LFUCache, self).pop()
value = super().pop()
return value[1]

View file

@ -82,7 +82,7 @@ class Checker(task.LoggedCheckedTask):
def __init__(self, urlqueue, logger, add_request_session):
"""Store URL queue and logger."""
super(Checker, self).__init__(logger)
super().__init__(logger)
self.urlqueue = urlqueue
self.origname = self.getName()
self.add_request_session = add_request_session

View file

@ -32,7 +32,7 @@ class Interrupt(task.CheckedTask):
@param duration: raise KeyboardInterrupt after given number of seconds
@ptype duration: int
"""
super(Interrupt, self).__init__()
super().__init__()
self.duration = duration
def run_checked(self):

View file

@ -31,7 +31,7 @@ class Status(task.LoggedCheckedTask):
@ptype wait_seconds: int
"""
logger = aggregator.config.status_logger
super(Status, self).__init__(logger)
super().__init__(logger)
self.aggregator = aggregator
self.wait_seconds = wait_seconds
assert self.wait_seconds >= 1

View file

@ -48,7 +48,7 @@ class LoggedCheckedTask(CheckedTask):
def __init__(self, logger):
"""Initialize super instance and store given logger."""
super(CheckedTask, self).__init__()
super().__init__()
self.logger = logger
def internal_error(self):

View file

@ -39,7 +39,7 @@ class BlacklistLogger(_Logger):
def __init__(self, **kwargs):
"""Intialize with old blacklist data (if found, else not)."""
args = self.get_args(kwargs)
super(BlacklistLogger, self).__init__(**args)
super().__init__(**args)
self.init_fileoutput(args)
self.blacklist = {}
if self.filename is not None and os.path.exists(self.filename):

View file

@ -62,7 +62,7 @@ class CSVLogger(_Logger):
def __init__(self, **kwargs):
"""Store default separator and (os dependent) line terminator."""
args = self.get_args(kwargs)
super(CSVLogger, self).__init__(**args)
super().__init__(**args)
self.init_fileoutput(args)
self.separator = args['separator']
self.quotechar = args['quotechar']
@ -75,7 +75,7 @@ class CSVLogger(_Logger):
def start_output(self):
"""Write checking start info as csv comment."""
super(CSVLogger, self).start_output()
super().start_output()
row = []
if self.has_part("intro"):
self.write_intro()

View file

@ -35,7 +35,7 @@ class CustomXMLLogger(xmllog._XMLLogger):
"""
Write start of checking info as xml comment.
"""
super(CustomXMLLogger, self).start_output()
super().start_output()
self.xml_start_output()
attrs = {"created": strformat.strtime(self.starttime)}
self.xml_starttag('linkchecker', attrs)

View file

@ -34,7 +34,7 @@ class DOTLogger(_GraphLogger):
def start_output(self):
"""Write start of checking info as DOT comment."""
super(DOTLogger, self).start_output()
super().start_output()
if self.has_part("intro"):
self.write_intro()
self.writeln()

View file

@ -31,7 +31,7 @@ class GMLLogger(_GraphLogger):
def start_output(self):
"""Write start of checking info as gml comment."""
super(GMLLogger, self).start_output()
super().start_output()
if self.has_part("intro"):
self.write_intro()
self.writeln()

View file

@ -27,7 +27,7 @@ class _GraphLogger(_Logger):
def __init__(self, **kwargs):
"""Initialize graph node list and internal id counter."""
args = self.get_args(kwargs)
super(_GraphLogger, self).__init__(**args)
super().__init__(**args)
self.init_fileoutput(args)
self.nodes = {}
self.nodeid = 0

View file

@ -34,13 +34,13 @@ class GraphXMLLogger(_XMLLogger, _GraphLogger):
def __init__(self, **kwargs):
"""Initialize graph node list and internal id counter."""
args = self.get_args(kwargs)
super(GraphXMLLogger, self).__init__(**args)
super().__init__(**args)
self.nodes = {}
self.nodeid = 0
def start_output(self):
"""Write start of checking info as xml comment."""
super(GraphXMLLogger, self).start_output()
super().start_output()
self.xml_start_output()
self.xml_starttag('GraphXML')
self.xml_starttag('graph', attrs={"isDirected": "true"})

View file

@ -80,7 +80,7 @@ class HtmlLogger(_Logger):
def __init__(self, **kwargs):
"""Initialize default HTML color values."""
args = self.get_args(kwargs)
super(HtmlLogger, self).__init__(**args)
super().__init__(**args)
self.init_fileoutput(args)
self.colorbackground = args['colorbackground']
self.colorurl = args['colorurl']
@ -92,7 +92,7 @@ class HtmlLogger(_Logger):
def part(self, name):
"""Return non-space-breakable part name."""
return super(HtmlLogger, self).part(name).replace(" ", "&nbsp;")
return super().part(name).replace(" ", "&nbsp;")
def comment(self, s, **args):
"""Write HTML comment."""
@ -102,7 +102,7 @@ class HtmlLogger(_Logger):
def start_output(self):
"""Write start of checking info."""
super(HtmlLogger, self).start_output()
super().start_output()
header = {
"encoding": self.get_charset_encoding(),
"title": configuration.App,

View file

@ -47,7 +47,7 @@ class SitemapXmlLogger(xmllog._XMLLogger):
def __init__(self, **kwargs):
"""Initialize graph node list and internal id counter."""
args = self.get_args(kwargs)
super(SitemapXmlLogger, self).__init__(**args)
super().__init__(**args)
# All URLs must have the given prefix, which is determined
# by the first logged URL.
self.prefix = None
@ -66,7 +66,7 @@ class SitemapXmlLogger(xmllog._XMLLogger):
def start_output(self):
"""Write start of checking info as xml comment."""
super(SitemapXmlLogger, self).start_output()
super().start_output()
self.xml_start_output()
attrs = {"xmlns": "http://www.sitemaps.org/schemas/sitemap/0.9"}
self.xml_starttag('urlset', attrs)

View file

@ -61,7 +61,7 @@ class SQLLogger(_Logger):
def __init__(self, **kwargs):
"""Initialize database access data."""
args = self.get_args(kwargs)
super(SQLLogger, self).__init__(**args)
super().__init__(**args)
self.init_fileoutput(args)
self.dbname = args['dbname']
self.separator = args['separator']
@ -77,7 +77,7 @@ class SQLLogger(_Logger):
"""
Write start of checking info as sql comment.
"""
super(SQLLogger, self).start_output()
super().start_output()
if self.has_part("intro"):
self.write_intro()
self.writeln()

View file

@ -55,7 +55,7 @@ class TextLogger(_Logger):
def __init__(self, **kwargs):
"""Initialize error counter and optional file output."""
args = self.get_args(kwargs)
super(TextLogger, self).__init__(**args)
super().__init__(**args)
self.output_encoding = args.get("encoding", i18n.default_encoding)
self.init_fileoutput(args)
self.colorparent = args.get('colorparent', 'default')
@ -73,20 +73,20 @@ class TextLogger(_Logger):
def init_fileoutput(self, args):
"""Colorize file output if possible."""
super(TextLogger, self).init_fileoutput(args)
super().init_fileoutput(args)
if self.fd is not None:
self.fd = ansicolor.Colorizer(self.fd)
def start_fileoutput(self):
"""Needed to make file descriptor color aware."""
init_color = self.fd is None
super(TextLogger, self).start_fileoutput()
super().start_fileoutput()
if init_color:
self.fd = ansicolor.Colorizer(self.fd)
def start_output(self):
"""Write generic start checking info."""
super(TextLogger, self).start_output()
super().start_output()
if self.has_part('intro'):
self.write_intro()
self.flush()

View file

@ -49,7 +49,7 @@ class _XMLLogger(_Logger):
def __init__(self, **kwargs):
""" Initialize graph node list and internal id counter. """
args = self.get_args(kwargs)
super(_XMLLogger, self).__init__(**args)
super().__init__(**args)
self.init_fileoutput(args)
self.indent = " "
self.level = 0

View file

@ -24,7 +24,7 @@ class HttpHeaderInfo(_ConnectionPlugin):
def __init__(self, config):
"""Initialize configuration."""
super(HttpHeaderInfo, self).__init__(config)
super().__init__(config)
self.prefixes = tuple(config["prefixes"])
def applies_to(self, url_data):

View file

@ -34,7 +34,7 @@ class LocationInfo(_ConnectionPlugin):
"""Check for geoip module."""
if not geoip:
log.warn(LOG_PLUGIN, "GeoIP or pygeoip not found for LocationInfo plugin.")
super(LocationInfo, self).__init__(config)
super().__init__(config)
def applies_to(self, url_data):
"""Check for validity, host existence and geoip module."""

View file

@ -78,7 +78,7 @@ class MarkdownCheck(_ContentPlugin):
)
def __init__(self, config):
super(MarkdownCheck, self).__init__(config)
super().__init__(config)
self.filename_re = self._default_filename_re
pattern = config.get(self._filename_re_key)
if pattern:

View file

@ -68,7 +68,7 @@ class PdfParser(_ParserPlugin):
"""Check for pdfminer."""
if not has_pdflib:
log.warn(LOG_PLUGIN, "pdfminer not found for PdfParser plugin")
super(PdfParser, self).__init__(config)
super().__init__(config)
def applies_to(self, url_data, pagetype=None):
"""Check for PDF pagetype."""

View file

@ -119,7 +119,7 @@ class WordParser(_ParserPlugin):
init_win32com()
if not has_word():
log.warn(LOG_PLUGIN, "Microsoft Word not found for WordParser plugin")
super(WordParser, self).__init__(config)
super().__init__(config)
def applies_to(self, url_data, pagetype=None):
"""Check for Word pagetype."""

View file

@ -35,7 +35,7 @@ class RegexCheck(_ContentPlugin):
def __init__(self, config):
"""Set warning regex from config."""
super(RegexCheck, self).__init__(config)
super().__init__(config)
self.warningregex = None
pattern = config["warningregex"]
if pattern:

View file

@ -37,7 +37,7 @@ class SslCertificateCheck(_ConnectionPlugin):
def __init__(self, config):
"""Initialize clamav configuration."""
super(SslCertificateCheck, self).__init__(config)
super().__init__(config)
self.warn_ssl_cert_secs_valid = (
config[sslcertwarndays] * strformat.SECONDS_PER_DAY
)

View file

@ -50,7 +50,7 @@ class HtmlSyntaxCheck(_ContentPlugin):
def __init__(self, config):
"""Initialize plugin."""
super(HtmlSyntaxCheck, self).__init__(config)
super().__init__(config)
self.timer = W3Timer()
def applies_to(self, url_data):
@ -84,7 +84,7 @@ class CssSyntaxCheck(_ContentPlugin):
def __init__(self, config):
"""Initialize plugin."""
super(CssSyntaxCheck, self).__init__(config)
super().__init__(config)
self.timer = W3Timer()
def applies_to(self, url_data):

View file

@ -29,7 +29,7 @@ class VirusCheck(_ContentPlugin):
def __init__(self, config):
"""Initialize clamav configuration."""
super(VirusCheck, self).__init__(config)
super().__init__(config)
# XXX read config
self.clamav_conf = get_clamav_conf(canonical_clamav_conf())
if not self.clamav_conf:
@ -154,7 +154,7 @@ class ClamavConfig(dict):
def __init__(self, filename):
"""Parse clamav configuration file."""
super(ClamavConfig, self).__init__()
super().__init__()
self.parseconf(filename)
if self.get('ScannerDaemonOutputFormat'):
raise ClamavError(_("ScannerDaemonOutputFormat must be disabled"))

View file

@ -25,7 +25,7 @@ class StoppableThread(threading.Thread):
def __init__(self):
"""Store stop event."""
super(StoppableThread, self).__init__()
super().__init__()
self._stopper = threading.Event()
def stop(self):

View file

@ -102,7 +102,7 @@ class MyInstallLib(install_lib):
def install(self):
"""Install the generated config file."""
outs = super(MyInstallLib, self).install()
outs = super().install()
infile = self.create_conf_file()
outfile = os.path.join(self.install_dir, os.path.basename(infile))
self.copy_file(infile, outfile)
@ -149,7 +149,7 @@ class MyInstallLib(install_lib):
def get_outputs(self):
"""Add the generated config file to the list of outputs."""
outs = super(MyInstallLib, self).get_outputs()
outs = super().get_outputs()
conf_output = self.get_conf_output()
outs.append(conf_output)
if self.compile:
@ -163,7 +163,7 @@ class MyInstallData(install_data):
def run(self):
"""Adjust permissions on POSIX systems."""
self.install_translations()
super(MyInstallData, self).run()
super().run()
self.fix_permissions()
def install_translations(self):
@ -212,7 +212,7 @@ class MyDistribution(Distribution):
def __init__(self, attrs):
"""Set console and windows scripts."""
super(MyDistribution, self).__init__(attrs)
super().__init__(attrs)
self.console = ["linkchecker"]
def run_commands(self):
@ -223,7 +223,7 @@ class MyDistribution(Distribution):
data.append("install_data = %r" % cwd)
data.append("install_scripts = %r" % cwd)
self.create_conf_file(data)
super(MyDistribution, self).run_commands()
super().run_commands()
def get_conf_filename(self, directory):
"""Get name for config file."""

View file

@ -59,7 +59,7 @@ class TestLogger(linkcheck.logger._Logger):
"""
args = self.get_args(kwargs)
args["parts"] = self.logparts
super(TestLogger, self).__init__(**args)
super().__init__(**args)
# list of expected output lines
self.expected = args["expected"]
# list of real output lines
@ -204,7 +204,7 @@ class LinkCheckTest(unittest.TestCase):
def setUp(self):
"""Ensure the current locale setting is the default.
Otherwise, warnings will get translated and will break tests."""
super(LinkCheckTest, self).setUp()
super().setUp()
linkcheck.init_i18n(loc="C")
def norm(self, url, encoding="utf-8"):

View file

@ -32,7 +32,7 @@ class FtpServerTest(LinkCheckTest):
def __init__(self, methodName="runTest"):
"""Init test class and store default ftp server port."""
super(FtpServerTest, self).__init__(methodName=methodName)
super().__init__(methodName=methodName)
self.host = "localhost"
self.port = None

View file

@ -103,7 +103,7 @@ class NoQueryHttpRequestHandler(StoppableHttpRequestHandler):
if status >= 200 and status not in (204, 304):
self.wfile.write(b"testcontent")
else:
super(NoQueryHttpRequestHandler, self).do_GET()
super().do_GET()
def do_HEAD(self):
"""
@ -114,7 +114,7 @@ class NoQueryHttpRequestHandler(StoppableHttpRequestHandler):
self.send_response(self.get_status())
self.end_headers()
else:
super(NoQueryHttpRequestHandler, self).do_HEAD()
super().do_HEAD()
def list_directory(self, path):
"""Helper to produce a directory listing (absent index.html).
@ -157,7 +157,7 @@ class HttpServerTest(LinkCheckTest):
"""
Init test class and store default http server port.
"""
super(HttpServerTest, self).__init__(methodName=methodName)
super().__init__(methodName=methodName)
self.port = None
self.handler = NoQueryHttpRequestHandler
@ -256,7 +256,7 @@ class CookieRedirectHttpRequestHandler(NoQueryHttpRequestHandler):
"""Send cookie before ending headers."""
self.send_header("Set-Cookie", get_cookie())
self.send_header("Set-Cookie", get_cookie(maxage=0))
super(CookieRedirectHttpRequestHandler, self).end_headers()
super().end_headers()
def redirect(self):
"""Redirect request."""
@ -291,7 +291,7 @@ class CookieRedirectHttpRequestHandler(NoQueryHttpRequestHandler):
elif "redirect" in self.path:
self.redirect()
else:
super(CookieRedirectHttpRequestHandler, self).do_GET()
super().do_GET()
def do_HEAD(self):
"""Handle redirections for HEAD."""
@ -302,7 +302,7 @@ class CookieRedirectHttpRequestHandler(NoQueryHttpRequestHandler):
elif "redirect" in self.path:
self.redirect()
else:
super(CookieRedirectHttpRequestHandler, self).do_HEAD()
super().do_HEAD()
class CGIHandler(CGIHTTPRequestHandler, StoppableHttpRequestHandler):

View file

@ -31,7 +31,7 @@ class TelnetServerTest(LinkCheckTest):
def __init__(self, methodName="runTest"):
"""Init test class and store default ftp server port."""
super(TelnetServerTest, self).__init__(methodName=methodName)
super().__init__(methodName=methodName)
self.host = "localhost"
self.port = None
self.stop_event = threading.Event()

View file

@ -25,7 +25,7 @@ class TestHttp(HttpServerTest):
"""Test http:// link checking."""
def __init__(self, methodName="runTest"):
super(TestHttp, self).__init__(methodName=methodName)
super().__init__(methodName=methodName)
self.handler = CookieRedirectHttpRequestHandler
@need_network

View file

@ -24,7 +24,7 @@ class TestHttpRedirect(HttpServerTest):
"""Test http:// link redirection checking."""
def __init__(self, methodName="runTest"):
super(TestHttpRedirect, self).__init__(methodName=methodName)
super().__init__(methodName=methodName)
self.handler = CookieRedirectHttpRequestHandler
@need_network

View file

@ -30,7 +30,7 @@ class TestHttps(HttpsServerTest):
"""
def __init__(self, methodName="runTest"):
super(TestHttps, self).__init__(methodName=methodName)
super().__init__(methodName=methodName)
self.handler = CookieRedirectHttpRequestHandler
@classmethod

View file

@ -23,7 +23,7 @@ class TestHttpsRedirect(HttpServerTest):
"""Test https:// link redirection checking."""
def __init__(self, methodName="runTest"):
super(TestHttpsRedirect, self).__init__(methodName=methodName)
super().__init__(methodName=methodName)
self.handler = RedirectHttpsRequestHandler
def test_redirect(self):