<commit_before>import datetime
import json
import platform
import ssl
import time
from urllib.parse import urlencode

from easypost.constant import SUPPORT_EMAIL, TIMEOUT, USER_AGENT
from easypost.easypost_object import EasyPostObject
from easypost.error import Error


class Requestor:
    def __init__(self, local_api_key=None):
        self._api_key = local_api_key

    @classmethod
    def _objects_to_ids(cls, param):
        if isinstance(param, EasyPostObject):
            return {"id": param.id}
        elif isinstance(param, dict):
            return {k: cls._objects_to_ids(v) for k, v in param.items()}
        elif isinstance(param, list):
            return [cls._objects_to_ids(v) for v in param]
        else:
            return param

    def request(self, method, url, params=None, api_key_required=True):
        if params is None:
            params = {}
        http_body, http_status, my_api_key = self.request_raw(method, url, params, api_key_required)
        response = self.interpret_response(http_body, http_status)
        return response, my_api_key

    def request_raw(self, method, url, params=None, api_key_required=True):
        # Importing here to avoid circular imports
        from easypost import VERSION, api_base, api_key

        if params is None:
            params = {}
        my_api_key = self._api_key or api_key

        if api_key_required and my_api_key is None:
            raise Error(
                "No API key provided. Set an API key via \"easypost.api_key = 'APIKEY'. "
                "Your API keys can be found in your EasyPost dashboard, or you can email us "
                f"at {SUPPORT_EMAIL} for assistance."
            )

        abs_url = "%s%s" % (api_base, url or "")
        params = self._objects_to_ids(params)

        ua = {
            "client_version": VERSION,
            "lang": "python",
            "publisher": "easypost",
            "request_lib": request_lib,
        }
        for attr, func in (
            ("lang_version", platform.python_version),
            ("platform", platform.platform),
            ("uname", lambda: " ".join(platform.uname())),
        ):
            try:
                val = func()
            except Exception as e:
                val = "!! %s" % e
            ua[attr] = val

        if hasattr(ssl, "OPENSSL_VERSION"):
            ua["openssl_version"] = ssl.OPENSSL_VERSION

        headers = {
            "X-Client-User-Agent": json.dumps(ua),
            "User-Agent": USER_AGENT,
            "Authorization": "Bearer %s" % my_api_key,
            "Content-type": "application/json",<commit_msg>collect python_implementation in easypost-python user-agent<commit_after>import datetime
import json
import platform
import ssl
import time
from urllib.parse import urlencode

from easypost.constant import SUPPORT_EMAIL, TIMEOUT, USER_AGENT
from easypost.easypost_object import EasyPostObject
from easypost.error import Error


class Requestor:
    def __init__(self, local_api_key=None):
        self._api_key = local_api_key

    @classmethod
    def _objects_to_ids(cls, param):
        if isinstance(param, EasyPostObject):
            return {"id": param.id}
        elif isinstance(param, dict):
            return {k: cls._objects_to_ids(v) for k, v in param.items()}
        elif isinstance(param, list):
            return [cls._objects_to_ids(v) for v in param]
        else:
            return param

    def request(self, method, url, params=None, api_key_required=True):
        if params is None:
            params = {}
        http_body, http_status, my_api_key = self.request_raw(method, url, params, api_key_required)
        response = self.interpret_response(http_body, http_status)
        return response, my_api_key

    def request_raw(self, method, url, params=None, api_key_required=True):
        # Importing here to avoid circular imports
        from easypost import VERSION, api_base, api_key

        if params is None:
            params = {}
        my_api_key = self._api_key or api_key

        if api_key_required and my_api_key is None:
            raise Error(
                "No API key provided. Set an API key via \"easypost.api_key = 'APIKEY'. "
                "Your API keys can be found in your EasyPost dashboard, or you can email us "
                f"at {SUPPORT_EMAIL} for assistance."
            )

        abs_url = "%s%s" % (api_base, url or "")
        params = self._objects_to_ids(params)

        ua = {
            "client_version": VERSION,
            "lang": "python",
            "publisher": "easypost",
            "request_lib": request_lib,
        }
        for attr, func in (
            ("lang_version", platform.python_version),
            ("platform", platform.platform),
            ("uname", lambda: " ".join(platform.uname())),
            ("implementation", platform.python_implementation),
        ):
            try:
                val = func()
            except Exception as e:
                val = "!! %s" % e
            ua[attr] = val

        if hasattr(ssl, "OPENSSL_VERSION"):
            ua["openssl_version"] = ssl.OPENSSL_VERSION

        headers = {
            "X-Client-User-Agent": json.dumps(ua),
            "User-Agent": USER_AGENT,
            "Authorization": "Bearer %s" % my_api_key,
            "Content-type": "application/json",
{'fraction_non_alphanumeric': 0.09641924654979485, 'fraction_numerical': 0.0, 'mean_word_length': 2.162146226415094, 'pattern_counts': {'":': 18, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4187669', 'n_tokens_mistral': 1587, 'n_tokens_neox': 1545, 'n_words': 429}