about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/python_http_client
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/python_http_client
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/python_http_client')
-rw-r--r--.venv/lib/python3.12/site-packages/python_http_client/VERSION.txt1
-rw-r--r--.venv/lib/python3.12/site-packages/python_http_client/__init__.py23
-rw-r--r--.venv/lib/python3.12/site-packages/python_http_client/client.py296
-rw-r--r--.venv/lib/python3.12/site-packages/python_http_client/exceptions.py97
4 files changed, 417 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/python_http_client/VERSION.txt b/.venv/lib/python3.12/site-packages/python_http_client/VERSION.txt
new file mode 100644
index 00000000..86fb6504
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/python_http_client/VERSION.txt
@@ -0,0 +1 @@
+3.3.7
diff --git a/.venv/lib/python3.12/site-packages/python_http_client/__init__.py b/.venv/lib/python3.12/site-packages/python_http_client/__init__.py
new file mode 100644
index 00000000..79b74b27
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/python_http_client/__init__.py
@@ -0,0 +1,23 @@
+import os
+
+from .client import Client  # noqa
+from .exceptions import (  # noqa
+    HTTPError,
+    BadRequestsError,
+    UnauthorizedError,
+    ForbiddenError,
+    NotFoundError,
+    MethodNotAllowedError,
+    PayloadTooLargeError,
+    UnsupportedMediaTypeError,
+    TooManyRequestsError,
+    InternalServerError,
+    ServiceUnavailableError,
+    GatewayTimeoutError
+)
+
+
+dir_path = os.path.dirname(os.path.realpath(__file__))
+if os.path.isfile(os.path.join(dir_path, 'VERSION.txt')):
+    with open(os.path.join(dir_path, 'VERSION.txt')) as version_file:
+        __version__ = version_file.read().strip()
diff --git a/.venv/lib/python3.12/site-packages/python_http_client/client.py b/.venv/lib/python3.12/site-packages/python_http_client/client.py
new file mode 100644
index 00000000..3a562351
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/python_http_client/client.py
@@ -0,0 +1,296 @@
+"""HTTP Client library"""
+import json
+import logging
+from .exceptions import handle_error
+
+try:
+    # Python 3
+    import urllib.request as urllib
+    from urllib.parse import urlencode
+    from urllib.error import HTTPError
+except ImportError:
+    # Python 2
+    import urllib2 as urllib
+    from urllib2 import HTTPError
+    from urllib import urlencode
+
+_logger = logging.getLogger(__name__)
+
+
+class Response(object):
+    """Holds the response from an API call."""
+
+    def __init__(self, response):
+        """
+        :param response: The return value from a open call
+                         on a urllib.build_opener()
+        :type response:  urllib response object
+        """
+        self._status_code = response.getcode()
+        self._body = response.read()
+        self._headers = response.info()
+
+    @property
+    def status_code(self):
+        """
+        :return: integer, status code of API call
+        """
+        return self._status_code
+
+    @property
+    def body(self):
+        """
+        :return: response from the API
+        """
+        return self._body
+
+    @property
+    def headers(self):
+        """
+        :return: dict of response headers
+        """
+        return self._headers
+
+    @property
+    def to_dict(self):
+        """
+        :return: dict of response from the API
+        """
+        if self.body:
+            return json.loads(self.body.decode('utf-8'))
+        else:
+            return None
+
+
+class Client(object):
+    """Quickly and easily access any REST or REST-like API."""
+
+    # These are the supported HTTP verbs
+    methods = {'delete', 'get', 'patch', 'post', 'put'}
+
+    def __init__(self,
+                 host,
+                 request_headers=None,
+                 version=None,
+                 url_path=None,
+                 append_slash=False,
+                 timeout=None):
+        """
+        :param host: Base URL for the api. (e.g. https://api.sendgrid.com)
+        :type host:  string
+        :param request_headers: A dictionary of the headers you want
+                                applied on all calls
+        :type request_headers: dictionary
+        :param version: The version number of the API.
+                        Subclass _build_versioned_url for custom behavior.
+                        Or just pass the version as part of the URL
+                        (e.g. client._("/v3"))
+        :type version: integer
+        :param url_path: A list of the url path segments
+        :type url_path: list of strings
+        """
+        self.host = host
+        self.request_headers = request_headers or {}
+        self._version = version
+        # _url_path keeps track of the dynamically built url
+        self._url_path = url_path or []
+        # APPEND SLASH set
+        self.append_slash = append_slash
+        self.timeout = timeout
+
+    def _build_versioned_url(self, url):
+        """Subclass this function for your own needs.
+           Or just pass the version as part of the URL
+           (e.g. client._('/v3'))
+        :param url: URI portion of the full URL being requested
+        :type url: string
+        :return: string
+        """
+        return '{}/v{}{}'.format(self.host, str(self._version), url)
+
+    def _build_url(self, query_params):
+        """Build the final URL to be passed to urllib
+
+        :param query_params: A dictionary of all the query parameters
+        :type query_params: dictionary
+        :return: string
+        """
+        url = ''
+        count = 0
+        while count < len(self._url_path):
+            url += '/{}'.format(self._url_path[count])
+            count += 1
+
+        # add slash
+        if self.append_slash:
+            url += '/'
+
+        if query_params:
+            url_values = urlencode(sorted(query_params.items()), True)
+            url = '{}?{}'.format(url, url_values)
+
+        if self._version:
+            url = self._build_versioned_url(url)
+        else:
+            url = '{}{}'.format(self.host, url)
+        return url
+
+    def _update_headers(self, request_headers):
+        """Update the headers for the request
+
+        :param request_headers: headers to set for the API call
+        :type request_headers: dictionary
+        :return: dictionary
+        """
+        self.request_headers.update(request_headers)
+
+    def _build_client(self, name=None):
+        """Make a new Client object
+
+        :param name: Name of the url segment
+        :type name: string
+        :return: A Client object
+        """
+        url_path = self._url_path + [name] if name else self._url_path
+        return Client(host=self.host,
+                      version=self._version,
+                      request_headers=self.request_headers,
+                      url_path=url_path,
+                      append_slash=self.append_slash,
+                      timeout=self.timeout)
+
+    def _make_request(self, opener, request, timeout=None):
+        """Make the API call and return the response. This is separated into
+           it's own function, so we can mock it easily for testing.
+
+        :param opener:
+        :type opener:
+        :param request: url payload to request
+        :type request: urllib.Request object
+        :param timeout: timeout value or None
+        :type timeout: float
+        :return: urllib response
+        """
+        timeout = timeout or self.timeout
+        try:
+            return opener.open(request, timeout=timeout)
+        except HTTPError as err:
+            exc = handle_error(err)
+            exc.__cause__ = None
+            _logger.debug('{method} Response: {status} {body}'.format(
+                method=request.get_method(),
+                status=exc.status_code,
+                body=exc.body))
+            raise exc
+
+    def _(self, name):
+        """Add variable values to the url.
+           (e.g. /your/api/{variable_value}/call)
+           Another example: if you have a Python reserved word, such as global,
+           in your url, you must use this method.
+
+        :param name: Name of the url segment
+        :type name: string
+        :return: Client object
+        """
+        return self._build_client(name)
+
+    def __getattr__(self, name):
+        """Dynamically add method calls to the url, then call a method.
+           (e.g. client.name.name.method())
+           You can also add a version number by using .version(<int>)
+
+        :param name: Name of the url segment or method call
+        :type name: string or integer if name == version
+        :return: mixed
+        """
+        if name == 'version':
+            def get_version(*args, **kwargs):
+                """
+                :param args: dict of settings
+                :param kwargs: unused
+                :return: string, version
+                """
+                self._version = args[0]
+                return self._build_client()
+            return get_version
+
+        # We have reached the end of the method chain, make the API call
+        if name in self.methods:
+            method = name.upper()
+
+            def http_request(
+                    request_body=None,
+                    query_params=None,
+                    request_headers=None,
+                    timeout=None,
+                    **_):
+                """Make the API call
+                :param timeout: HTTP request timeout. Will be propagated to
+                    urllib client
+                :type timeout: float
+                :param request_headers: HTTP headers. Will be merged into
+                    current client object state
+                :type request_headers: dict
+                :param query_params: HTTP query parameters
+                :type query_params: dict
+                :param request_body: HTTP request body
+                :type request_body: string or json-serializable object
+                :param kwargs:
+                :return: Response object
+                """
+                if request_headers:
+                    self._update_headers(request_headers)
+
+                if request_body is None:
+                    data = None
+                else:
+                    # Don't serialize to a JSON formatted str
+                    # if we don't have a JSON Content-Type
+                    if 'Content-Type' in self.request_headers and \
+                            self.request_headers['Content-Type'] != \
+                            'application/json':
+                        data = request_body.encode('utf-8')
+                    else:
+                        self.request_headers.setdefault(
+                            'Content-Type', 'application/json')
+                        data = json.dumps(request_body).encode('utf-8')
+
+                opener = urllib.build_opener()
+                request = urllib.Request(
+                    self._build_url(query_params),
+                    headers=self.request_headers,
+                    data=data,
+                )
+                request.get_method = lambda: method
+
+                _logger.debug('{method} Request: {url}'.format(
+                    method=method,
+                    url=request.get_full_url()))
+                if request.data:
+                    _logger.debug('PAYLOAD: {data}'.format(
+                        data=request.data))
+                _logger.debug('HEADERS: {headers}'.format(
+                    headers=request.headers))
+
+                response = Response(
+                    self._make_request(opener, request, timeout=timeout)
+                )
+
+                _logger.debug('{method} Response: {status} {body}'.format(
+                    method=method,
+                    status=response.status_code,
+                    body=response.body))
+
+                return response
+
+            return http_request
+        else:
+            # Add a segment to the URL
+            return self._(name)
+
+    def __getstate__(self):
+        return self.__dict__
+
+    def __setstate__(self, state):
+        self.__dict__ = state
diff --git a/.venv/lib/python3.12/site-packages/python_http_client/exceptions.py b/.venv/lib/python3.12/site-packages/python_http_client/exceptions.py
new file mode 100644
index 00000000..2a8c179b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/python_http_client/exceptions.py
@@ -0,0 +1,97 @@
+import json
+
+
+class HTTPError(Exception):
+    """ Base of all other errors"""
+
+    def __init__(self, *args):
+        if len(args) == 4:
+            self.status_code = args[0]
+            self.reason = args[1]
+            self.body = args[2]
+            self.headers = args[3]
+        else:
+            self.status_code = args[0].code
+            self.reason = args[0].reason
+            self.body = args[0].read()
+            self.headers = args[0].hdrs
+
+    def __reduce__(self):
+        return (
+            HTTPError,
+            (self.status_code, self.reason, self.body, self.headers)
+        )
+
+    @property
+    def to_dict(self):
+        """
+        :return: dict of response error from the API
+        """
+        return json.loads(self.body.decode('utf-8'))
+
+
+class BadRequestsError(HTTPError):
+    pass
+
+
+class UnauthorizedError(HTTPError):
+    pass
+
+
+class ForbiddenError(HTTPError):
+    pass
+
+
+class NotFoundError(HTTPError):
+    pass
+
+
+class MethodNotAllowedError(HTTPError):
+    pass
+
+
+class PayloadTooLargeError(HTTPError):
+    pass
+
+
+class UnsupportedMediaTypeError(HTTPError):
+    pass
+
+
+class TooManyRequestsError(HTTPError):
+    pass
+
+
+class InternalServerError(HTTPError):
+    pass
+
+
+class ServiceUnavailableError(HTTPError):
+    pass
+
+
+class GatewayTimeoutError(HTTPError):
+    pass
+
+
+err_dict = {
+    400: BadRequestsError,
+    401: UnauthorizedError,
+    403: ForbiddenError,
+    404: NotFoundError,
+    405: MethodNotAllowedError,
+    413: PayloadTooLargeError,
+    415: UnsupportedMediaTypeError,
+    429: TooManyRequestsError,
+    500: InternalServerError,
+    503: ServiceUnavailableError,
+    504: GatewayTimeoutError
+}
+
+
+def handle_error(error):
+    try:
+        exc = err_dict[error.code](error)
+    except KeyError:
+        return HTTPError(error)
+    return exc