'get_info(params, default = UNDEFINED, get_bytes = False)
Queries the control socket for the given GETINFO option. If provided a
default then that\'s returned if the GETINFO option is undefined or the
call fails for any reason (error response, control port closed, initiated,
etc).
.. versionchanged:: 1.1.0
Added the get_bytes argument.
:param str,list params: GETINFO option or options to be queried
:param object default: response if the query fails
:param bool get_bytes: provides **bytes** values rather than a **str** under python 3.x
:returns:
Response depends upon how we were called as follows...
* **str** with the response if our param was a **str**
* **dict** with the \'param => response\' mapping if our param was a **list**
* default if one was provided and our call failed
:raises:
* :class:`stem.ControllerError` if the call fails and we weren\'t
provided a default response
* :class:`stem.InvalidArguments` if the \'params\' requested was
invalid
* :class:`stem.ProtocolError` if the geoip database is known to be
unavailable'

@with_default()
def get_info(self, params, default=UNDEFINED, get_bytes=False):

    start_time = time.time()
    reply = {}
    if isinstance(params, (bytes, str_type)):
        is_multiple = False
        params = set([params])
    else:
        if (not params):
            return {}
        is_multiple = True
        params = set(params)
    from_cache = [param.lower() for param in params]
    cached_results = self._get_cache_map(from_cache, 'getinfo')
    for key in cached_results:
        user_expected_key = _case_insensitive_lookup(params, key)
        reply[user_expected_key] = cached_results[key]
        params.remove(user_expected_key)
    for param in params:
        if (param.startswith('ip-to-country/') and self.is_geoip_unavailable()):
            raise stem.ProtocolError('Tor    geoip    database    is    unavailable')
    if (not params):
        log.trace(('GETINFO    %s    (cache    fetch)' % '    '.join(reply.keys())))
        if is_multiple:
            return reply
        else:
            return list(reply.values())[0]
    try:
        response = self.msg(('GETINFO    %s' % '    '.join(params)))
        stem.response.convert('GETINFO', response)
        response._assert_matches(params)
        if (stem.prereq.is_python_3() and (not get_bytes)):
            response.entries = dict(((k, stem.util.str_tools._to_unicode(v)) for (k, v) in response.entries.items()))
        reply.update(response.entries)
        if self.is_caching_enabled():
            to_cache = {}
            for (key, value) in response.entries.items():
                key = key.lower()
                if (key in CACHEABLE_GETINFO_PARAMS):
                    to_cache[key] = value
                elif key.startswith('ip-to-country/'):
                    to_cache[key] = value
                    self._geoip_failure_count = (-1)
            self._set_cache(to_cache, 'getinfo')
        log.debug(('GETINFO    %s    (runtime:    %0.4f)' % ('    '.join(params), (time.time() - start_time))))
        if is_multiple:
            return reply
        else:
            return list(reply.values())[0]
    except stem.ControllerError as exc:
        is_geoip_request = ((len(params) == 1) and list(params)[0].startswith('ip-to-country/'))
        if (is_geoip_request and self.is_caching_enabled() and (self._geoip_failure_count != (-1))):
            self._geoip_failure_count += 1
            if self.is_geoip_unavailable():
                log.warn("Tor's    geoip    database    is    unavailable.")
        log.debug(('GETINFO    %s    (failed:    %s)' % ('    '.join(params), exc)))
        raise exc
