def _lookup(self, name, cls, type, timeout):
        """
        Build a L{dns.Query} for the given parameters and dispatch it via UDP.

        If this query is already outstanding, it will not be re-issued.
        Instead, when the outstanding query receives a response, that response
        will be re-used for this query as well.

        @type name: C{str}
        @type type: C{int}
        @type cls: C{int}

        @return: A L{Deferred} which fires with a three-tuple giving the
            answer, authority, and additional sections of the response or with
            a L{Failure} if the response code is anything other than C{dns.OK}.
        """
        key = (name, type, cls)
        waiting = self._waiting.get(key)
        if waiting is None:
            self._waiting[key] = []
            d = self.queryUDP([dns.Query(name, type, cls)], timeout)
            def cbResult(result):
                for d in self._waiting.pop(key):
                    d.callback(result)
                return result
            d.addCallback(self.filterAnswers)
            d.addBoth(cbResult)
        else:
            d = defer.Deferred()
            waiting.append(d)
        return d

        Build a L{dns.Query} for the given parameters and dispatch it via UDP.

        If this query is already outstanding, it will not be re-issued.
        Instead, when the outstanding query receives a response, that response
        will be re-used for this query as well.

        @type name: C{str}
        @type type: C{int}
        @type cls: C{int}

        @return: A L{Deferred} which fires with a three-tuple giving the
            answer, authority, and additional sections of the response or with
            a L{Failure} if the response code is anything other than C{dns.OK}.
        
stackoverflow/venv/lib/python3.6/site-packages/twisted/names/client.py