<commit_before># Copyright 2015 Planet Labs, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Manage data for requests and responses."""
import copy
import datetime
import json
import logging
import mimetypes
import random
import re
import string

import httpx
from tqdm.asyncio import tqdm

LOGGER = logging.getLogger(__name__)


class RequestException(Exception):
    """Exceptions thrown by RequestException"""
    pass


class Request():
    '''Handles a HTTP request for the Planet server.

    :param url: URL of API endpoint
    :type url: str
    :param params: Values to send in the query string. Defaults to None.
    :type params: dict, list of tuples, or bytes, optional
    :param data: Object to send in the body. Defaults to None.
    :type data: dict, list of tuples, bytes, or file-like object, optional
    :param json: JSON to send. Defaults to None.
    :type json: dict, optional
    :param method: HTTP request method. Defaults to 'GET'
    :type method: str, optional
    :raises RequestException: When provided `body_type` is not a subclass of
        :py:class:`planet.api.models.Body`
    '''
    def __init__(self, url, params=None, data=None, json=None, method='GET'):
        if data or json:
            headers = {'Content-Type': 'application/json'}
        else:
            headers = None

        self.http_request = httpx.Request(
            method,
            url,
            params=params,
            data=data,
            json=json,
            headers=headers)

    @property
    def url(self):
        return self.http_request.url

    @url.setter
    def url(self, url):
        '''Set the url.

        :param url: URL of API endpoint
        :type url: str
        '''
        self.http_request.url = httpx.URL(url)


class Response():
    '''Handles the Planet server's response to a HTTP request

    :param request: Request that was submitted to the server
    :type request: :py:Class:`Request`
    :param http_response: Response that was received from the server
    :type http_response: :py:Class:`requests.models.Response`
    '''
    def __init__(self, request, http_response):
        self.request = request
        self.http_response = http_response

    def __repr__(self):
        return f'<models.Response [{self.status_code}]>'

    @property
    def status_code(self):
        '''HTTP status code.

        :returns: status code
        :rtype: int
        '''
        return self.http_response.status_code

    def json(self):
        '''Get response json.

        :returns:response json
        :rtype: dict
        '''
        return self.http_response.json()

    async def aclose(self):
        await self.http_response.aclose()


class StreamingBody():
    '''A representation of a streaming resource from the API.

    :param response: Response that was received from the server
    :type response: :py:Class:`requests.models.Response`
        '''
    def __init__(self, response):
        self.response = response.http_response
        self.url = response.request.url

    @property
    def name(self):
        '''The name of this resource.

        The default is to use the content-disposition header value from the
        response. If not found, falls back to resolving the name from the url
        or generating a random name with the type from the response.

        :returns: name of this resource
        :rtype: str
        '''
        name = (_get_filename_from_headers(self.response.headers) or
                _get_filename_from_url(self.url) or
                _get_random_filename(
                    self.response.headers.get('content-type')))
        return name

    @property
    def size(self):
        '''The size of the body.

        :returns: size of the body
        :rtype: int
        '''
        return int(self.response.headers['Content-Length'])

    @property
    def num_bytes_downloaded(self):
        '''The number of bytes downloaded.

        :returns: number of bytes downloaded
        :rtype: int
        '''
        return self.response.num_bytes_downloaded

    def last_modified(self):
        '''Read the last-modified header as a datetime, if present.

        :returns: last-modified header
        :rtype: datatime or None
        '''
        lm = self.response.headers.get('last-modified', None)
        return datetime.strptime(lm, '%a, %d %b %Y %H:%M:%S GMT') if lm \
            else None

    async def aiter_bytes(self):
        async for c in self.response.aiter_bytes():
            yield c

    async def write(self, filename, overwrite=True, progress_bar=True):
        '''Write the body to a file.

        :param filename: Name to assign to downloaded file.
        :type filename: str<commit_msg>deleted last_modified function in models.py as it is not being used. Deleted datetime package import as it is also not being used<commit_after># Copyright 2015 Planet Labs, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Manage data for requests and responses."""
import copy
import json
import logging
import mimetypes
import random
import re
import string

import httpx
from tqdm.asyncio import tqdm

LOGGER = logging.getLogger(__name__)


class RequestException(Exception):
    """Exceptions thrown by RequestException"""
    pass


class Request():
    '''Handles a HTTP request for the Planet server.

    :param url: URL of API endpoint
    :type url: str
    :param params: Values to send in the query string. Defaults to None.
    :type params: dict, list of tuples, or bytes, optional
    :param data: Object to send in the body. Defaults to None.
    :type data: dict, list of tuples, bytes, or file-like object, optional
    :param json: JSON to send. Defaults to None.
    :type json: dict, optional
    :param method: HTTP request method. Defaults to 'GET'
    :type method: str, optional
    :raises RequestException: When provided `body_type` is not a subclass of
        :py:class:`planet.api.models.Body`
    '''
    def __init__(self, url, params=None, data=None, json=None, method='GET'):
        if data or json:
            headers = {'Content-Type': 'application/json'}
        else:
            headers = None

        self.http_request = httpx.Request(
            method,
            url,
            params=params,
            data=data,
            json=json,
            headers=headers)

    @property
    def url(self):
        return self.http_request.url

    @url.setter
    def url(self, url):
        '''Set the url.

        :param url: URL of API endpoint
        :type url: str
        '''
        self.http_request.url = httpx.URL(url)


class Response():
    '''Handles the Planet server's response to a HTTP request

    :param request: Request that was submitted to the server
    :type request: :py:Class:`Request`
    :param http_response: Response that was received from the server
    :type http_response: :py:Class:`requests.models.Response`
    '''
    def __init__(self, request, http_response):
        self.request = request
        self.http_response = http_response

    def __repr__(self):
        return f'<models.Response [{self.status_code}]>'

    @property
    def status_code(self):
        '''HTTP status code.

        :returns: status code
        :rtype: int
        '''
        return self.http_response.status_code

    def json(self):
        '''Get response json.

        :returns:response json
        :rtype: dict
        '''
        return self.http_response.json()

    async def aclose(self):
        await self.http_response.aclose()


class StreamingBody():
    '''A representation of a streaming resource from the API.

    :param response: Response that was received from the server
    :type response: :py:Class:`requests.models.Response`
        '''
    def __init__(self, response):
        self.response = response.http_response
        self.url = response.request.url

    @property
    def name(self):
        '''The name of this resource.

        The default is to use the content-disposition header value from the
        response. If not found, falls back to resolving the name from the url
        or generating a random name with the type from the response.

        :returns: name of this resource
        :rtype: str
        '''
        name = (_get_filename_from_headers(self.response.headers) or
                _get_filename_from_url(self.url) or
                _get_random_filename(
                    self.response.headers.get('content-type')))
        return name

    @property
    def size(self):
        '''The size of the body.

        :returns: size of the body
        :rtype: int
        '''
        return int(self.response.headers['Content-Length'])

    @property
    def num_bytes_downloaded(self):
        '''The number of bytes downloaded.

        :returns: number of bytes downloaded
        :rtype: int
        '''
        return self.response.num_bytes_downloaded

    async def aiter_bytes(self):
        async for c in self.response.aiter_bytes():
            yield c

    async def write(self, filename, overwrite=True, progress_bar=True):
        '''Write the body to a file.

        :param filename: Name to assign to downloaded file.
        :type filename: str
{'fraction_non_alphanumeric': 0.08764550523329746, 'fraction_numerical': 0.0015650983077374547, 'mean_word_length': 2.5243019648397103, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3660745', 'n_tokens_mistral': 2809, 'n_tokens_neox': 2715, 'n_words': 1049}