# Buggy code
def check_thread(self):
    kwargs = {}
    if self.app.config.linkcheck_timeout:
        kwargs["timeout"] = self.app.config.linkcheck_timeout

    kwargs["allow_redirects"] = True

    def check_uri():
        # split off anchor
        if "#" in uri:
            req_url, anchor = uri.split("#", 1)
            for rex in self.anchors_ignore:
                if rex.match(anchor):
                    anchor = None
                    break
        else:
            req_url = uri
            anchor = None

        # handle non-ASCII URIs
        try:
            req_url.encode("ascii")
        except UnicodeError:
            req_url = encode_uri(req_url)

        try:
            if anchor and self.app.config.linkcheck_anchors:
                # Read the whole document and see if #anchor exists
                response = requests.get(
                    req_url, stream=True, config=self.app.config, **kwargs
                )
                found = check_anchor(response, unquote(anchor))

                if not found:
                    raise Exception("Anchor '%s' not found" % anchor)
            else:
                try:
                    # try a HEAD request first, which should be easier on
                    # the server and the network
                    response = requests.head(req_url, config=self.app.config, **kwargs)
                    response.raise_for_status()
                except HTTPError as err:
                    # retry with GET request if that fails, some servers
                    # don't like HEAD requests.
                    response = requests.get(
                        req_url, stream=True, config=self.app.config, **kwargs
                    )
                    response.raise_for_status()
        except HTTPError as err:
            if err.response.status_code == 401:
                # We'll take "Unauthorized" as working.
                return "working", " - unauthorized", 0
            else:
                return "broken", str(err), 0
        except Exception as err:
            if is_ssl_error(err):
                return "ignored", str(err), 0
            else:
                return "broken", str(err), 0
        if response.url.rstrip("/") == req_url.rstrip("/"):
            return "working", "", 0
        else:
            new_url = response.url
            if anchor:
                new_url += "#" + anchor
            # history contains any redirects, get last
            if response.history:
                code = response.history[-1].status_code
            return "redirected", new_url, code

    def check():
        # check for various conditions without bothering the network
        if len(uri) == 0 or uri.startswith(("#", "mailto:", "ftp:")):
            return "unchecked", "", 0
        elif not uri.startswith(("http:", "https:")):
            return "local", "", 0
        elif uri in self.good:
            return "working", "old", 0
        elif uri in self.broken:
            return "broken", self.broken[uri], 0
        elif uri in self.redirected:
            return "redirected", self.redirected[uri][0], self.redirected[uri][1]
        for rex in self.to_ignore:
            if rex.match(uri):
                return "ignored", "", 0

        # need to actually check the URI
        for _ in range(self.app.config.linkcheck_retries):
            status, info, code = check_uri()
            if status != "broken":
                break

        if status == "working":
            self.good.add(uri)
        elif status == "broken":
            self.broken[uri] = info
        elif status == "redirected":
            self.redirected[uri] = (info, code)

        return (status, info, code)

    while True:
        uri, docname, lineno = self.wqueue.get()
        if uri is None:
            break
        status, info, code = check()
        self.rqueue.put((uri, docname, lineno, status, info, code))


# Traceback (UnboundLocalError)
Running Sphinx v1.5.3
loading pickled environment... done
building [mo]: targets for 0 po files that are out of date
building [linkcheck]: targets for 5 source files that are out of date
updating environment: 0 added, 0 changed, 0 removed
looking for now-outdated files... none found
preparing documents... done
writing output... [ 20%] authors
(line    5) ok        http://pawamoy.github.io/
writing output... [ 40%] changelog
writing output... [ 60%] contributing
(line   76) ok        https://travis-ci.org/Pawamoy/keycut/pull_requests
(line   11) ok        https://github.com/Pawamoy/keycut/issues
(line   40) ok        https://github.com/Pawamoy/keycut
(line   27) ok        https://github.com/Pawamoy/keycut/issues
writing output... [ 80%] index
writing output... [100%] readme
(line    8) ok        https://pypi.python.org/pypi/keycut/
(line    8) ok        https://pypi.python.org/pypi/keycut/
(line    8) ok        https://pyup.io/repos/github/Pawamoy/keycut/
(line    8) ok        https://travis-ci.org/Pawamoy/keycut/
(line    8) ok        https://gitter.im/Pawamoy/keycut
(line   17) ok        https://travis-ci.org/Pawamoy/keycut/
(line    8) ok        https://www.codacy.com/app/Pawamoy/keycut/dashboard
(line    8) ok        https://www.codacy.com/app/Pawamoy/keycut/dashboard
(line   56) ok        https://github.com/Pawamoy/keycut-data
Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "/media/pawamoy/Data/git/keycut/.tox/linkcheck/local/lib/python2.7/site-packages/sphinx/builders/linkcheck.py", line 207, in check_thread
status, info, code = check()
File "/media/pawamoy/Data/git/keycut/.tox/linkcheck/local/lib/python2.7/site-packages/sphinx/builders/linkcheck.py", line 190, in check
status, info, code = check_uri()
File "/media/pawamoy/Data/git/keycut/.tox/linkcheck/local/lib/python2.7/site-packages/sphinx/builders/linkcheck.py", line 170, in check_uri
return 'redirected', new_url, code
UnboundLocalError: local variable 'code' referenced before assignment

(line   21) ok        https://www.codacy.com/app/Pawamoy/keycut/dashboard
(line   25) ok        https://www.codacy.com/app/Pawamoy/keycut/dashboard
^CERROR: KEYBOARDINTERRUPT
^CERROR: keyboardinterrupt

# Fixed code
def check_thread(self):
    kwargs = {}
    if self.app.config.linkcheck_timeout:
        kwargs["timeout"] = self.app.config.linkcheck_timeout

    kwargs["allow_redirects"] = True

    def check_uri():
        # split off anchor
        if "#" in uri:
            req_url, anchor = uri.split("#", 1)
            for rex in self.anchors_ignore:
                if rex.match(anchor):
                    anchor = None
                    break
        else:
            req_url = uri
            anchor = None

        # handle non-ASCII URIs
        try:
            req_url.encode("ascii")
        except UnicodeError:
            req_url = encode_uri(req_url)

        try:
            if anchor and self.app.config.linkcheck_anchors:
                # Read the whole document and see if #anchor exists
                response = requests.get(
                    req_url, stream=True, config=self.app.config, **kwargs
                )
                found = check_anchor(response, unquote(anchor))

                if not found:
                    raise Exception("Anchor '%s' not found" % anchor)
            else:
                try:
                    # try a HEAD request first, which should be easier on
                    # the server and the network
                    response = requests.head(req_url, config=self.app.config, **kwargs)
                    response.raise_for_status()
                except HTTPError as err:
                    # retry with GET request if that fails, some servers
                    # don't like HEAD requests.
                    response = requests.get(
                        req_url, stream=True, config=self.app.config, **kwargs
                    )
                    response.raise_for_status()
        except HTTPError as err:
            if err.response.status_code == 401:
                # We'll take "Unauthorized" as working.
                return "working", " - unauthorized", 0
            else:
                return "broken", str(err), 0
        except Exception as err:
            if is_ssl_error(err):
                return "ignored", str(err), 0
            else:
                return "broken", str(err), 0
        if response.url.rstrip("/") == req_url.rstrip("/"):
            return "working", "", 0
        else:
            new_url = response.url
            if anchor:
                new_url += "#" + anchor
            # history contains any redirects, get last
            if response.history:
                code = response.history[-1].status_code
                return "redirected", new_url, code
            else:
                return "redirected", new_url, 0

    def check():
        # check for various conditions without bothering the network
        if len(uri) == 0 or uri.startswith(("#", "mailto:", "ftp:")):
            return "unchecked", "", 0
        elif not uri.startswith(("http:", "https:")):
            return "local", "", 0
        elif uri in self.good:
            return "working", "old", 0
        elif uri in self.broken:
            return "broken", self.broken[uri], 0
        elif uri in self.redirected:
            return "redirected", self.redirected[uri][0], self.redirected[uri][1]
        for rex in self.to_ignore:
            if rex.match(uri):
                return "ignored", "", 0

        # need to actually check the URI
        for _ in range(self.app.config.linkcheck_retries):
            status, info, code = check_uri()
            if status != "broken":
                break

        if status == "working":
            self.good.add(uri)
        elif status == "broken":
            self.broken[uri] = info
        elif status == "redirected":
            self.redirected[uri] = (info, code)

        return (status, info, code)

    while True:
        uri, docname, lineno = self.wqueue.get()
        if uri is None:
            break
        status, info, code = check()
        self.rqueue.put((uri, docname, lineno, status, info, code))