-
Notifications
You must be signed in to change notification settings - Fork 410
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add raw_request * wip * add deserialize method, tests, format * encoding default None * Move common fixtures into conftest, better raw_request tests * README * add 'preview' module * Rename encoding=json -> api_mode=preview * Use the preview API version * tests * Add stripe context * default to preview api version if api_mode is preview * Add test * test datetime encoding * add timezone, lint * fix tests? * Remove stripe_version default in preview.py * how about now * fix tests for real * fix test / lint again * again * feedback * orderedict * use global client override * remove client * remove empty params * more ordereddicts * json.dumps * Use JSONMatcher and QueryMatcher --------- Co-authored-by: Annie Li <[email protected]> Co-authored-by: Richard Marmorstein <[email protected]>
- Loading branch information
1 parent
5f12c0e
commit 08fc8ff
Showing
11 changed files
with
496 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,12 @@ def _encode_nested_dict(key, data, fmt="%s[%s]"): | |
return d | ||
|
||
|
||
def _json_encode_date_callback(value): | ||
if isinstance(value, datetime.datetime): | ||
return _encode_datetime(value) | ||
return value | ||
|
||
|
||
def _api_encode(data): | ||
for key, value in six.iteritems(data): | ||
key = util.utf8(key) | ||
|
@@ -115,16 +121,28 @@ def format_app_info(cls, info): | |
str += " (%s)" % (info["url"],) | ||
return str | ||
|
||
def request(self, method, url, params=None, headers=None): | ||
def request(self, method, url, params=None, headers=None, api_mode=None): | ||
rbody, rcode, rheaders, my_api_key = self.request_raw( | ||
method.lower(), url, params, headers, is_streaming=False | ||
method.lower(), | ||
url, | ||
params, | ||
headers, | ||
is_streaming=False, | ||
api_mode=api_mode, | ||
) | ||
resp = self.interpret_response(rbody, rcode, rheaders) | ||
return resp, my_api_key | ||
|
||
def request_stream(self, method, url, params=None, headers=None): | ||
def request_stream( | ||
self, method, url, params=None, headers=None, api_mode=None | ||
): | ||
stream, rcode, rheaders, my_api_key = self.request_raw( | ||
method.lower(), url, params, headers, is_streaming=True | ||
method.lower(), | ||
url, | ||
params, | ||
headers, | ||
is_streaming=True, | ||
api_mode=api_mode, | ||
) | ||
resp = self.interpret_streaming_response(stream, rcode, rheaders) | ||
return resp, my_api_key | ||
|
@@ -238,7 +256,7 @@ def specific_oauth_error(self, rbody, rcode, resp, rheaders, error_code): | |
|
||
return None | ||
|
||
def request_headers(self, api_key, method): | ||
def request_headers(self, api_key, method, api_mode): | ||
user_agent = "Stripe/v1 PythonBindings/%s" % (version.VERSION,) | ||
if stripe.app_info: | ||
user_agent += " " + self.format_app_info(stripe.app_info) | ||
|
@@ -272,8 +290,11 @@ def request_headers(self, api_key, method): | |
headers["Stripe-Account"] = self.stripe_account | ||
|
||
if method == "post": | ||
headers["Content-Type"] = "application/x-www-form-urlencoded" | ||
headers.setdefault("Idempotency-Key", str(uuid.uuid4())) | ||
if api_mode == "preview": | ||
headers["Content-Type"] = "application/json" | ||
else: | ||
headers["Content-Type"] = "application/x-www-form-urlencoded" | ||
|
||
if self.api_version is not None: | ||
headers["Stripe-Version"] = self.api_version | ||
|
@@ -287,6 +308,7 @@ def request_raw( | |
params=None, | ||
supplied_headers=None, | ||
is_streaming=False, | ||
api_mode=None, | ||
): | ||
""" | ||
Mechanism for issuing an API call | ||
|
@@ -317,6 +339,13 @@ def request_raw( | |
# makes these parameter strings easier to read. | ||
encoded_params = encoded_params.replace("%5B", "[").replace("%5D", "]") | ||
|
||
if api_mode == "preview": | ||
encoded_body = json.dumps( | ||
params or {}, default=_json_encode_date_callback | ||
) | ||
else: | ||
encoded_body = encoded_params | ||
|
||
if method == "get" or method == "delete": | ||
if params: | ||
abs_url = _build_api_url(abs_url, encoded_params) | ||
|
@@ -334,15 +363,15 @@ def request_raw( | |
"Content-Type" | ||
] = "multipart/form-data; boundary=%s" % (generator.boundary,) | ||
else: | ||
post_data = encoded_params | ||
post_data = encoded_body | ||
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) | ||
headers = self.request_headers(my_api_key, method, api_mode) | ||
if supplied_headers is not None: | ||
for key, value in six.iteritems(supplied_headers): | ||
headers[key] = value | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,4 @@ | |
|
||
class _ApiVersion: | ||
CURRENT = "2022-11-15" | ||
PREVIEW = "20230509T165653" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from stripe import raw_request | ||
|
||
|
||
class Preview(object): | ||
def _get_default_opts(self, params): | ||
if "api_mode" not in params: | ||
params["api_mode"] = "preview" | ||
return params | ||
|
||
def post(self, url, **params): | ||
return raw_request("post", url, **self._get_default_opts(params)) | ||
|
||
def get(self, url, **params): | ||
return raw_request("get", url, **self._get_default_opts(params)) | ||
|
||
def delete(self, url, **params): | ||
return raw_request("delete", url, **self._get_default_opts(params)) | ||
|
||
|
||
preview = Preview() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
from stripe import api_requestor, util | ||
from stripe.api_version import _ApiVersion | ||
|
||
|
||
def _raw_request(method_, url_, **params): | ||
params = None if params is None else params.copy() | ||
api_key = util.read_special_variable(params, "api_key", None) | ||
idempotency_key = util.read_special_variable( | ||
params, "idempotency_key", None | ||
) | ||
stripe_version = util.read_special_variable(params, "stripe_version", None) | ||
stripe_account = util.read_special_variable(params, "stripe_account", None) | ||
api_mode = util.read_special_variable(params, "api_mode", None) | ||
stripe_context = util.read_special_variable(params, "stripe_context", None) | ||
headers = util.read_special_variable(params, "headers", None) | ||
|
||
if api_mode == "preview": | ||
stripe_version = stripe_version or _ApiVersion.PREVIEW | ||
|
||
requestor = api_requestor.APIRequestor( | ||
key=api_key, | ||
api_version=stripe_version, | ||
account=stripe_account, | ||
) | ||
|
||
if idempotency_key is not None: | ||
headers = {} if headers is None else headers.copy() | ||
headers.update(util.populate_headers(idempotency_key)) | ||
|
||
# stripe-context goes *here* and not in api_requestor. Properties | ||
# go on api_requestor when you want them to persist onto requests | ||
# made when you call instance methods on APIResources that come from | ||
# the first request. No need for that here, as we aren't deserializing APIResources | ||
if stripe_context is not None: | ||
headers = {} if headers is None else headers.copy() | ||
headers.update({"Stripe-Context": stripe_context}) | ||
|
||
response, _ = requestor.request(method_, url_, params, headers, api_mode) | ||
return response | ||
|
||
|
||
def _deserialize( | ||
resp, api_key=None, stripe_version=None, stripe_account=None, params=None | ||
): | ||
return util.convert_to_stripe_object( | ||
resp, api_key, stripe_version, stripe_account, params | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.