Source code for pandasdmx.remote
from io import BufferedIOBase, BytesIO
import logging
from warnings import warn
import requests
try:
from requests_cache import CachedSession as MaybeCachedSession
except ImportError: # pragma: no cover
warn('optional dependency requests_cache is not installed; cache options '
'to Session() have no effect', RuntimeWarning)
from requests import Session as MaybeCachedSession
logger = logging.getLogger(__name__)
[docs]class Session(MaybeCachedSession):
""":class:`requests.Session` subclass with optional caching.
If requests_cache is installed, this class caches responses.
"""
def __init__(self, timeout=30.1, proxies=None, stream=False, **kwargs):
if MaybeCachedSession is not requests.Session:
# Using requests_cache.CachedSession
# No cache keyword arguments supplied = don't use the cache
disabled = set(kwargs.keys()) <= {'get_footer_url'}
if disabled:
# Avoid creating any file
kwargs['backend'] = 'memory'
super(Session, self).__init__(**kwargs)
# Overwrite value from requests_cache.CachedSession.__init__()
self._is_cache_disabled = disabled
elif len(kwargs):
raise ValueError('Cache arguments have no effect without '
'requests_session: %s' % kwargs)
else:
# Plain requests.Session
super(Session, self).__init__()
# Overwrite values from requests.Session.__init__()
self.proxies = proxies
self.timeout = timeout
self.stream = stream
[docs]class ResponseIO(BufferedIOBase):
"""Read data from a :class:`requests.Response` object, into an in-memory or on-disk file
and expose it as a file-like object.
:class:`ResponseIO` wraps a :class:`requests.Response` object's 'content'
attribute, providing a file-like object from which bytes can be
:meth:`read` incrementally.
Parameters
----------
response : :class:`requests.Response`
HTTP response to wrap.
tee : binary, writable :py:class:`io.BufferedIOBasè`, defaults to io.BytesIO()
*tee* is exposed as *self.tee* and not closed explicitly.
"""
def __init__(self, response, tee=None):
self.response = response
if tee is None:
tee = BytesIO()
# If tee is a file-like object or tempfile, then use it as cache
if isinstance(tee, BufferedIOBase) or hasattr(tee, 'file'):
self.tee = tee
else:
# So tee must be str or os.FilePath
self.tee = open(tee, 'w+b')
self.tee.write(response.content)
self.tee.seek(0)
def readable(self):
return True
def read(self, size=-1):
"""Read and return up to *size* bytes by calling *self.tee.read()*.
*size* Defaults to -1. In this case, reads and
returns all data until EOF.
Returns an empty bytes object on EOF.
"""
return self.tee.read(size)