コード例 #1
0
    def run_test_multipart_data_with_file(self, test_file):
        params = {
            "key1": b"ASCII value",
            "key2": u"Üñìçôdé value",
            "key3": test_file
        }
        generator = MultipartDataGenerator()
        generator.add_params(params)
        http_body = generator.get_post_data()

        if six.PY3:
            http_body = http_body.decode('utf-8')

        assert re.search(r"Content-Disposition: form-data; name=\"key1\"",
                         http_body)
        assert re.search(r"ASCII value", http_body)
        assert re.search(r"Content-Disposition: form-data; name=\"key2\"",
                         http_body)
        assert re.search(r"Üñìçôdé value", http_body)
        assert re.search(
            r"Content-Disposition: form-data; name=\"key3\"; "
            r"filename=\".+\"", http_body)
        assert re.search(r"Content-Type: application/octet-stream", http_body)

        test_file.seek(0)
        file_contents = test_file.read()

        if six.PY3 and isinstance(file_contents, bytes):
            file_contents = file_contents.decode('utf-8')

        assert http_body.find(file_contents) != -1
コード例 #2
0
    def test_generate_simple_multipart_data(self):
        with open(__file__) as test_file:
            params = {
                "key1": "value1",
                "key2": "value2",
                "key3": test_file
                }
            generator = MultipartDataGenerator()
            generator.add_params(params)
            post_data = generator.get_post_data()

            if sys.version_info < (3, 0):
                http_body = "".join([line for line in post_data])
            else:
                byte_array = bytearray([i for i in post_data])
                http_body = byte_array.decode('utf-8')

            self.assertTrue(re.search(
                r"Content-Disposition: form-data; name=\"key1\"", http_body))
            self.assertTrue(re.search(
                r"Content-Disposition: form-data; name=\"key2\"", http_body))
            self.assertTrue(re.search(
                r"Content-Disposition: form-data; name=\"key3\"; "
                r"filename=\".+\"",
                http_body))
            self.assertTrue(re.search(
                r"Content-Type: application/octet-stream", http_body))

            test_file.seek(0)
            file_contents = test_file.read()
            self.assertNotEqual(-1, http_body.find(file_contents))
コード例 #3
0
    def run_test_multipart_data_with_file(self, test_file):
        params = {
            "key1": b"ASCII value",
            "key2": u"Üñìçôdé value",
            "key3": test_file
        }
        generator = MultipartDataGenerator()
        generator.add_params(params)
        http_body = generator.get_post_data()

        if sys.version_info >= (3,):
            http_body = http_body.decode('utf-8')

        self.assertTrue(re.search(
            r"Content-Disposition: form-data; name=\"key1\"", http_body))
        self.assertTrue(re.search(r"ASCII value", http_body))
        self.assertTrue(re.search(
            r"Content-Disposition: form-data; name=\"key2\"", http_body))
        self.assertTrue(re.search(r"Üñìçôdé value", http_body))
        self.assertTrue(re.search(
            r"Content-Disposition: form-data; name=\"key3\"; "
            r"filename=\".+\"",
            http_body))
        self.assertTrue(re.search(
            r"Content-Type: application/octet-stream", http_body))

        test_file.seek(0)
        file_contents = test_file.read()

        if sys.version_info >= (3,) and isinstance(file_contents, bytes):
            file_contents = file_contents.decode('utf-8')

        self.assertNotEqual(-1, http_body.find(file_contents))
コード例 #4
0
    def test_generate_simple_multipart_data(self):
        test_file = open(__file__)

        params = {"key1": "value1", "key2": "value2", "key3": test_file}
        generator = MultipartDataGenerator()
        generator.add_params(params)
        post_data = generator.get_post_data()

        if sys.version_info < (3, 0):
            http_body = "".join([line for line in post_data])
        else:
            byte_array = bytearray([i for i in post_data])
            http_body = byte_array.decode('utf-8')

        self.assertTrue(
            re.search(r"Content-Disposition: form-data; name=\"key1\"",
                      http_body))
        self.assertTrue(
            re.search(r"Content-Disposition: form-data; name=\"key2\"",
                      http_body))
        self.assertTrue(
            re.search(
                r"Content-Disposition: form-data; name=\"key3\"; filename=\".+\"",
                http_body))
        self.assertTrue(
            re.search(r"Content-Type: application/octet-stream", http_body))

        test_file.seek(0)
        file_contents = test_file.read()
        self.assertNotEqual(-1, http_body.find(file_contents))
コード例 #5
0
    def request_raw(self, method, url, params=None, supplied_headers=None):
        """
        Mechanism for issuing an API call
        """
        from stripe import api_version

        if self.api_key:
            my_api_key = self.api_key
        else:
            from stripe import api_key
            my_api_key = api_key

        if my_api_key is None:
            raise error.AuthenticationError(
                'No API key provided. (HINT: set your API key using '
                '"stripe.api_key = <API-KEY>"). You can generate API keys '
                'from the Stripe web interface.  See https://stripe.com/api '
                'for details, or email [email protected] if you have any '
                'questions.')

        abs_url = '%s%s' % (self.api_base, url)

        encoded_params = urllib.urlencode(list(_api_encode(params or {})))

        if method == 'get' or method == 'delete':
            if params:
                abs_url = _build_api_url(abs_url, encoded_params)
            post_data = None
        elif method == 'post':
            if supplied_headers is not None and \
                    supplied_headers.get("Content-Type") == \
                    "multipart/form-data":
                generator = MultipartDataGenerator()
                generator.add_params(params or {})
                post_data = generator.get_post_data()
                supplied_headers["Content-Type"] = \
                    "multipart/form-data; boundary=%s" % (generator.boundary,)
            else:
                post_data = encoded_params
        else:
            raise error.APIConnectionError(
                'Unrecognized HTTP method %r.  This may indicate a bug in the '
                'Stripe bindings.  Please contact [email protected] for '
                'assistance.' % (method,))

        ua = {
            'bindings_version': version.VERSION,
            'lang': 'python',
            'publisher': 'stripe',
            'httplib': self._client.name,
        }
        for attr, func in [['lang_version', platform.python_version],
                           ['platform', platform.platform],
                           ['uname', lambda: ' '.join(platform.uname())]]:
            try:
                val = func()
            except Exception, e:
                val = "!! %s" % (e,)
            ua[attr] = val
コード例 #6
0
ファイル: api_requestor.py プロジェクト: tanshihui/Giggle
    def request_raw(self, method, url, params=None, supplied_headers=None):
        """
        Mechanism for issuing an API call
        """
        from stripe import api_version

        if self.api_key:
            my_api_key = self.api_key
        else:
            from stripe import api_key
            my_api_key = api_key

        if my_api_key is None:
            raise error.AuthenticationError(
                'No API key provided. (HINT: set your API key using '
                '"stripe.api_key = <API-KEY>"). You can generate API keys '
                'from the Stripe web interface.  See https://stripe.com/api '
                'for details, or email [email protected] if you have any '
                'questions.')

        abs_url = '%s%s' % (self.api_base, url)

        encoded_params = urllib.urlencode(list(_api_encode(params or {})))

        if method == 'get' or method == 'delete':
            if params:
                abs_url = _build_api_url(abs_url, encoded_params)
            post_data = None
        elif method == 'post':
            if supplied_headers is not None and \
                    supplied_headers.get("Content-Type") == \
                    "multipart/form-data":
                generator = MultipartDataGenerator()
                generator.add_params(params or {})
                post_data = generator.get_post_data()
                supplied_headers["Content-Type"] = \
                    "multipart/form-data; boundary=%s" % (generator.boundary,)
            else:
                post_data = encoded_params
        else:
            raise error.APIConnectionError(
                'Unrecognized HTTP method %r.  This may indicate a bug in the '
                'Stripe bindings.  Please contact [email protected] for '
                'assistance.' % (method, ))

        ua = {
            'bindings_version': version.VERSION,
            'lang': 'python',
            'publisher': 'stripe',
            'httplib': self._client.name,
        }
        for attr, func in [['lang_version', platform.python_version],
                           ['platform', platform.platform],
                           ['uname', lambda: ' '.join(platform.uname())]]:
            try:
                val = func()
            except Exception, e:
                val = "!! %s" % (e, )
            ua[attr] = val
コード例 #7
0
    def request_raw(self, method, url, params=None, supplied_headers=None):
        """
        Mechanism for issuing an API call
        """

        if self.api_key:
            my_api_key = self.api_key
        else:
            from stripe import api_key

            my_api_key = api_key

        if my_api_key is None:
            raise error.AuthenticationError(
                "No API key provided. (HINT: set your API key using "
                '"stripe.api_key = <API-KEY>"). You can generate API keys '
                "from the Stripe web interface.  See https://stripe.com/api "
                "for details, or email [email protected] if you have any "
                "questions.")

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

        encoded_params = urlencode(list(_api_encode(params or {})))

        # Don't use strict form encoding by changing the square bracket control
        # characters back to their literals. This is fine by the server, and
        # makes these parameter strings easier to read.
        encoded_params = encoded_params.replace("%5B", "[").replace("%5D", "]")

        if method == "get" or method == "delete":
            if params:
                abs_url = _build_api_url(abs_url, encoded_params)
            post_data = None
        elif method == "post":
            if (supplied_headers is not None
                    and supplied_headers.get("Content-Type")
                    == "multipart/form-data"):
                generator = MultipartDataGenerator()
                generator.add_params(params or {})
                post_data = generator.get_post_data()
                supplied_headers[
                    "Content-Type"] = "multipart/form-data; boundary=%s" % (
                        generator.boundary, )
            else:
                post_data = encoded_params
        else:
            raise error.APIConnectionError(
                "Unrecognized HTTP method %r.  This may indicate a bug in the "
                "Stripe bindings.  Please contact [email protected] for "
                "assistance." % (method, ))

        headers = self.request_headers(my_api_key, method)
        if supplied_headers is not None:
            for key, value in six.iteritems(supplied_headers):
                headers[key] = value

        util.log_info("Request to Stripe api", method=method, path=abs_url)
        util.log_debug(
            "Post details",
            post_data=encoded_params,
            api_version=self.api_version,
        )

        request_start = _now_ms()

        rbody, rcode, rheaders = self._client.request_with_retries(
            method, abs_url, headers, post_data)

        util.log_info("Stripe API response", path=abs_url, response_code=rcode)
        util.log_debug("API response body", body=rbody)

        if "Request-Id" in rheaders:
            request_id = rheaders["Request-Id"]
            util.log_debug(
                "Dashboard link for request",
                link=util.dashboard_link(request_id),
            )
            if stripe.enable_telemetry:
                request_duration_ms = _now_ms() - request_start
                self._last_request_metrics = RequestMetrics(
                    request_id, request_duration_ms)

        return rbody, rcode, rheaders, my_api_key
コード例 #8
0
    def request_raw(self, method, url, params=None, supplied_headers=None):
        """
        Mechanism for issuing an API call
        """

        if self.api_key:
            my_api_key = self.api_key
        else:
            from stripe import api_key
            my_api_key = api_key

        if my_api_key is None:
            raise error.AuthenticationError(
                'No API key provided. (HINT: set your API key using '
                '"stripe.api_key = <API-KEY>"). You can generate API keys '
                'from the Stripe web interface.  See https://stripe.com/api '
                'for details, or email [email protected] if you have any '
                'questions.')

        abs_url = '%s%s' % (self.api_base, url)

        encoded_params = urlencode(list(_api_encode(params or {})))

        # Don't use strict form encoding by changing the square bracket control
        # characters back to their literals. This is fine by the server, and
        # makes these parameter strings easier to read.
        encoded_params = encoded_params.replace('%5B', '[').replace('%5D', ']')

        if method == 'get' or method == 'delete':
            if params:
                abs_url = _build_api_url(abs_url, encoded_params)
            post_data = None
        elif method == 'post':
            if supplied_headers is not None and \
                    supplied_headers.get("Content-Type") == \
                    "multipart/form-data":
                generator = MultipartDataGenerator()
                generator.add_params(params or {})
                post_data = generator.get_post_data()
                supplied_headers["Content-Type"] = \
                    "multipart/form-data; boundary=%s" % (generator.boundary,)
            else:
                post_data = encoded_params
        else:
            raise error.APIConnectionError(
                'Unrecognized HTTP method %r.  This may indicate a bug in the '
                'Stripe bindings.  Please contact [email protected] for '
                'assistance.' % (method, ))

        headers = self.request_headers(my_api_key, method)
        if supplied_headers is not None:
            for key, value in six.iteritems(supplied_headers):
                headers[key] = value

        util.log_info('Request to Stripe api', method=method, path=abs_url)
        util.log_debug('Post details',
                       post_data=encoded_params,
                       api_version=self.api_version)

        rbody, rcode, rheaders = self._client.request_with_retries(
            method, abs_url, headers, post_data)

        util.log_info('Stripe API response', path=abs_url, response_code=rcode)
        util.log_debug('API response body', body=rbody)
        if 'Request-Id' in rheaders:
            util.log_debug('Dashboard link for request',
                           link=util.dashboard_link(rheaders['Request-Id']))
        return rbody, rcode, rheaders, my_api_key
コード例 #9
0
    def request_raw(self, method, url, params=None, supplied_headers=None):
        """
        Mechanism for issuing an API call
        """

        if self.api_key:
            my_api_key = self.api_key
        else:
            from stripe import api_key
            my_api_key = api_key

        if my_api_key is None:
            raise error.AuthenticationError(
                'No API key provided. (HINT: set your API key using '
                '"stripe.api_key = <API-KEY>"). You can generate API keys '
                'from the Stripe web interface.  See https://stripe.com/api '
                'for details, or email [email protected] if you have any '
                'questions.')

        abs_url = '%s%s' % (self.api_base, url)

        encoded_params = urllib.urlencode(list(_api_encode(params or {})))

        if method == 'get' or method == 'delete':
            if params:
                abs_url = _build_api_url(abs_url, encoded_params)
            post_data = None
        elif method == 'post':
            if supplied_headers is not None and \
                    supplied_headers.get("Content-Type") == \
                    "multipart/form-data":
                generator = MultipartDataGenerator()
                generator.add_params(params or {})
                post_data = generator.get_post_data()
                supplied_headers["Content-Type"] = \
                    "multipart/form-data; boundary=%s" % (generator.boundary,)
            else:
                post_data = encoded_params
        else:
            raise error.APIConnectionError(
                'Unrecognized HTTP method %r.  This may indicate a bug in the '
                'Stripe bindings.  Please contact [email protected] for '
                'assistance.' % (method,))

        ua = {
            'bindings_version': version.VERSION,
            'lang': 'python',
            'publisher': 'stripe',
            'httplib': self._client.name,
        }
        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

        headers = {
            'X-Stripe-Client-User-Agent': util.json.dumps(ua),
            'User-Agent': 'Stripe/v1 PythonBindings/%s' % (version.VERSION,),
            'Authorization': 'Bearer %s' % (my_api_key,)
        }

        if self.stripe_account:
            headers['Stripe-Account'] = self.stripe_account

        if method == 'post':
            headers['Content-Type'] = 'application/x-www-form-urlencoded'

        if self.api_version is not None:
            headers['Stripe-Version'] = self.api_version

        if supplied_headers is not None:
            for key, value in supplied_headers.items():
                headers[key] = value

        util.log_info('Request to Stripe api', method=method, path=abs_url)
        util.log_debug(
            'Post details', post_data=post_data, api_version=self.api_version)

        rbody, rcode, rheaders = self._client.request(
            method, abs_url, headers, post_data)

        util.log_info(
            'Stripe API response', path=abs_url, response_code=rcode)
        util.log_debug('API response body', body=rbody)
        if 'Request-Id' in rheaders:
            util.log_debug('Dashboard link for request',
                           link=util.dashboard_link(rheaders['Request-Id']))
        return rbody, rcode, rheaders, my_api_key
コード例 #10
0
    def run_test_multipart_data_with_file(self, test_file):
        params = {
            "key1": b"ASCII value",
            "key2": u"Üñìçôdé value",
            "key3": test_file,
            "key4": {
                "string": "Hello!",
                "int": 234,
                "float": 3.14159,
                "bool": True,
                "dict": {"foo": "bar"},
            },
        }
        generator = MultipartDataGenerator()
        generator.add_params(params)
        http_body = generator.get_post_data()

        if six.PY3:
            http_body = http_body.decode("utf-8")

        assert re.search(
            r"Content-Disposition: form-data; name=\"key1\"", http_body
        )
        assert re.search(r"ASCII value", http_body)
        assert re.search(
            r"Content-Disposition: form-data; name=\"key2\"", http_body
        )
        assert re.search(r"Üñìçôdé value", http_body)
        assert re.search(
            r"Content-Disposition: form-data; name=\"key3\"; "
            r"filename=\".+\"",
            http_body,
        )
        assert re.search(r"Content-Type: application/octet-stream", http_body)
        assert re.search(
            r"Content-Disposition: form-data; name=\"key4\[string\]\"",
            http_body,
        )
        assert re.search(r"Hello!", http_body)
        assert re.search(
            r"Content-Disposition: form-data; name=\"key4\[int\]\"", http_body
        )
        assert re.search(r"234", http_body)
        assert re.search(
            r"Content-Disposition: form-data; name=\"key4\[float\]\"",
            http_body,
        )
        assert re.search(r"3.14159", http_body)
        assert re.search(
            r"Content-Disposition: form-data; name=\"key4\[bool\]\"", http_body
        )
        assert re.search(r"True", http_body)
        assert re.search(
            r"Content-Disposition: form-data; name=\"key4\[dict\]\[foo\]\"",
            http_body,
        )
        assert re.search(r"bar", http_body)

        test_file.seek(0)
        file_contents = test_file.read()

        if six.PY3 and isinstance(file_contents, bytes):
            file_contents = file_contents.decode("utf-8")

        assert http_body.find(file_contents) != -1
コード例 #11
0
    def request_raw(self, method, url, params=None, supplied_headers=None):
        """
        Mechanism for issuing an API call
        """
        from stripe import api_version

        if self.api_key:
            my_api_key = self.api_key
        else:
            from stripe import api_key
            my_api_key = api_key

        if my_api_key is None:
            raise error.AuthenticationError(
                'No API key provided. (HINT: set your API key using '
                '"stripe.api_key = <API-KEY>"). You can generate API keys '
                'from the Stripe web interface.  See https://stripe.com/api '
                'for details, or email [email protected] if you have any '
                'questions.')

        abs_url = '%s%s' % (self.api_base, url)

        encoded_params = urllib.urlencode(list(_api_encode(params or {})))

        if method == 'get' or method == 'delete':
            if params:
                abs_url = _build_api_url(abs_url, encoded_params)
            post_data = None
        elif method == 'post':
            if supplied_headers is not None and \
                    supplied_headers.get("Content-Type") == \
                    "multipart/form-data":
                generator = MultipartDataGenerator()
                generator.add_params(params or {})
                post_data = generator.get_post_data()
                supplied_headers["Content-Type"] = \
                    "multipart/form-data; boundary=%s" % (generator.boundary,)
            else:
                post_data = encoded_params
        else:
            raise error.APIConnectionError(
                'Unrecognized HTTP method %r.  This may indicate a bug in the '
                'Stripe bindings.  Please contact [email protected] for '
                'assistance.' % (method,))

        ua = {
            'bindings_version': version.VERSION,
            'lang': 'python',
            'publisher': 'stripe',
            'httplib': self._client.name,
        }
        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

        headers = {
            'X-Stripe-Client-User-Agent': util.json.dumps(ua),
            'User-Agent': 'Stripe/v1 PythonBindings/%s' % (version.VERSION,),
            'Authorization': 'Bearer %s' % (my_api_key,)
        }

        if self.stripe_account:
            headers['Stripe-Account'] = self.stripe_account

        if method == 'post':
            headers['Content-Type'] = 'application/x-www-form-urlencoded'

        if api_version is not None:
            headers['Stripe-Version'] = api_version

        if supplied_headers is not None:
            for key, value in supplied_headers.items():
                headers[key] = value

        util.log_info('Request to Stripe api', method=method, path=abs_url)
        util.log_debug(
            'Post details', post_data=post_data, api_version=api_version)

        rbody, rcode, rheaders = self._client.request(
            method, abs_url, headers, post_data)

        util.log_info(
            'Stripe API response', path=abs_url, response_code=rcode)
        util.log_debug('API response body', body=rbody)
        if 'Request-Id' in rheaders:
            util.log_debug('Dashboard link for request',
                           link=util.dashboard_link(rheaders['Request-Id']))
        return rbody, rcode, rheaders, my_api_key
コード例 #12
0
ファイル: api_requestor.py プロジェクト: stripe/stripe-python
    def request_raw(self, method, url, params=None, supplied_headers=None):
        """
        Mechanism for issuing an API call
        """

        if self.api_key:
            my_api_key = self.api_key
        else:
            from stripe import api_key

            my_api_key = api_key

        if my_api_key is None:
            raise error.AuthenticationError(
                "No API key provided. (HINT: set your API key using "
                '"stripe.api_key = <API-KEY>"). You can generate API keys '
                "from the Stripe web interface.  See https://stripe.com/api "
                "for details, or email [email protected] if you have any "
                "questions."
            )

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

        encoded_params = urlencode(list(_api_encode(params or {})))

        # Don't use strict form encoding by changing the square bracket control
        # characters back to their literals. This is fine by the server, and
        # makes these parameter strings easier to read.
        encoded_params = encoded_params.replace("%5B", "[").replace("%5D", "]")

        if method == "get" or method == "delete":
            if params:
                abs_url = _build_api_url(abs_url, encoded_params)
            post_data = None
        elif method == "post":
            if (
                supplied_headers is not None
                and supplied_headers.get("Content-Type")
                == "multipart/form-data"
            ):
                generator = MultipartDataGenerator()
                generator.add_params(params or {})
                post_data = generator.get_post_data()
                supplied_headers[
                    "Content-Type"
                ] = "multipart/form-data; boundary=%s" % (generator.boundary,)
            else:
                post_data = encoded_params
        else:
            raise error.APIConnectionError(
                "Unrecognized HTTP method %r.  This may indicate a bug in the "
                "Stripe bindings.  Please contact [email protected] for "
                "assistance." % (method,)
            )

        headers = self.request_headers(my_api_key, method)
        if supplied_headers is not None:
            for key, value in six.iteritems(supplied_headers):
                headers[key] = value

        util.log_info("Request to Stripe api", method=method, path=abs_url)
        util.log_debug(
            "Post details",
            post_data=encoded_params,
            api_version=self.api_version,
        )

        rbody, rcode, rheaders = self._client.request_with_retries(
            method, abs_url, headers, post_data
        )

        util.log_info("Stripe API response", path=abs_url, response_code=rcode)
        util.log_debug("API response body", body=rbody)

        if "Request-Id" in rheaders:
            request_id = rheaders["Request-Id"]
            util.log_debug(
                "Dashboard link for request",
                link=util.dashboard_link(request_id),
            )

        return rbody, rcode, rheaders, my_api_key
コード例 #13
0
ファイル: api_requestor.py プロジェクト: liupeng0518/market
    def request_raw(self, method, url, params=None, supplied_headers=None):
        """
        Mechanism for issuing an API call
        """
        from stripe import api_version

        if self.api_key:
            my_api_key = self.api_key
        else:
            from stripe import api_key

            my_api_key = api_key

        if my_api_key is None:
            raise error.AuthenticationError(
                "No API key provided. (HINT: set your API key using "
                '"stripe.api_key = <API-KEY>"). You can generate API keys '
                "from the Stripe web interface.  See https://stripe.com/api "
                "for details, or email [email protected] if you have any "
                "questions."
            )

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

        encoded_params = urllib.urlencode(list(_api_encode(params or {})))

        if method == "get" or method == "delete":
            if params:
                abs_url = _build_api_url(abs_url, encoded_params)
            post_data = None
        elif method == "post":
            if supplied_headers is not None and supplied_headers.get("Content-Type") == "multipart/form-data":
                generator = MultipartDataGenerator()
                generator.add_params(params or {})
                post_data = generator.get_post_data()
                supplied_headers["Content-Type"] = "multipart/form-data; boundary=%s" % (generator.boundary,)
            else:
                post_data = encoded_params
        else:
            raise error.APIConnectionError(
                "Unrecognized HTTP method %r.  This may indicate a bug in the "
                "Stripe bindings.  Please contact [email protected] for "
                "assistance." % (method,)
            )

        ua = {
            "bindings_version": version.VERSION,
            "lang": "python",
            "publisher": "stripe",
            "httplib": self._client.name,
        }
        for attr, func in [
            ["lang_version", platform.python_version],
            ["platform", platform.platform],
            ["uname", lambda: " ".join(platform.uname())],
        ]:
            try:
                val = func()
            except Exception, e:
                val = "!! %s" % (e,)
            ua[attr] = val