Skip to content

Commit

Permalink
Merge pull request #477 from stripe/ob-file-resource
Browse files Browse the repository at this point in the history
Handle `file` objects like `file_upload`
  • Loading branch information
ob-stripe authored Sep 24, 2018
2 parents 4dd5a16 + 94d6331 commit 2226f47
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ cache:
env:
global:
# If changing this number, please also change it in `tests/conftest.py`.
- STRIPE_MOCK_VERSION=0.30.0
- STRIPE_MOCK_VERSION=0.32.0

before_install:
# Unpack and start stripe-mock so that the test suite can talk to it
Expand Down
2 changes: 1 addition & 1 deletion stripe/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
client_id = None
api_base = 'https://api.stripe.com'
connect_api_base = 'https://connect.stripe.com'
upload_api_base = 'https://uploads.stripe.com'
upload_api_base = 'https://files.stripe.com'
api_version = None
verify_ssl_certs = True
proxy = None
Expand Down
3 changes: 2 additions & 1 deletion stripe/api_resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
from stripe.api_resources.ephemeral_key import EphemeralKey
from stripe.api_resources.event import Event
from stripe.api_resources.exchange_rate import ExchangeRate
from stripe.api_resources.file import File
from stripe.api_resources.file import FileUpload
from stripe.api_resources.file_link import FileLink
from stripe.api_resources.file_upload import FileUpload
from stripe.api_resources.invoice import Invoice
from stripe.api_resources.invoice_item import InvoiceItem
from stripe.api_resources.invoice_line_item import InvoiceLineItem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
from stripe.api_resources.abstract import ListableAPIResource


class FileUpload(ListableAPIResource):
OBJECT_NAME = 'file_upload'

@classmethod
def api_base(cls):
return stripe.upload_api_base
class File(ListableAPIResource):
# This resource can have two different object names. In latter API
# versions, only `file` is used, but since stripe-python may be used with
# any API version, we need to support deserializing the older
# `file_upload` object into the same class.
OBJECT_NAME = 'file'
OBJECT_NAME_ALT = 'file_upload'

@classmethod
def class_url(cls):
Expand All @@ -20,7 +21,7 @@ def class_url(cls):
def create(cls, api_key=None, api_version=None, stripe_account=None,
**params):
requestor = api_requestor.APIRequestor(
api_key, api_base=cls.api_base(), api_version=api_version,
api_key, api_base=stripe.upload_api_base, api_version=api_version,
account=stripe_account)
url = cls.class_url()
supplied_headers = {
Expand All @@ -30,3 +31,7 @@ def create(cls, api_key=None, api_version=None, stripe_account=None,
'post', url, params=params, headers=supplied_headers)
return util.convert_to_stripe_object(response, api_key, api_version,
stripe_account)


# For backwards compatibility, the `File` class is aliased to `FileUpload`.
FileUpload = File
3 changes: 2 additions & 1 deletion stripe/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,9 @@ def load_object_classes():
api_resources.EphemeralKey.OBJECT_NAME: api_resources.EphemeralKey,
api_resources.Event.OBJECT_NAME: api_resources.Event,
api_resources.ExchangeRate.OBJECT_NAME: api_resources.ExchangeRate,
api_resources.File.OBJECT_NAME: api_resources.File,
api_resources.File.OBJECT_NAME_ALT: api_resources.File,
api_resources.FileLink.OBJECT_NAME: api_resources.FileLink,
api_resources.FileUpload.OBJECT_NAME: api_resources.FileUpload,
api_resources.Invoice.OBJECT_NAME: api_resources.Invoice,
api_resources.InvoiceItem.OBJECT_NAME: api_resources.InvoiceItem,
api_resources.InvoiceLineItem.OBJECT_NAME:
Expand Down
2 changes: 1 addition & 1 deletion tests/api_resources/issuing/test_dispute.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class TestDispute(object):
def test_is_creatable(self, request_mock):
resource = stripe.issuing.Dispute.create(
reason='fraudulent',
transaction='ipi_123'
disputed_transaction='ipi_123'
)
request_mock.assert_requested(
'post',
Expand Down
67 changes: 67 additions & 0 deletions tests/api_resources/test_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from __future__ import absolute_import, division, print_function

import tempfile

import pytest

import stripe


TEST_RESOURCE_ID = 'file_123'


class TestFile(object):
@pytest.fixture(scope='function')
def setup_upload_api_base(self):
stripe.upload_api_base = stripe.api_base
stripe.api_base = None
yield
stripe.api_base = stripe.upload_api_base
stripe.upload_api_base = 'https://files.stripe.com'

def test_is_listable(self, request_mock):
resources = stripe.File.list()
request_mock.assert_requested(
'get',
'/v1/files'
)
assert isinstance(resources.data, list)
assert isinstance(resources.data[0], stripe.File)

def test_is_retrievable(self, request_mock):
resource = stripe.File.retrieve(TEST_RESOURCE_ID)
request_mock.assert_requested(
'get',
'/v1/files/%s' % TEST_RESOURCE_ID
)
assert isinstance(resource, stripe.File)

def test_is_creatable(self, setup_upload_api_base, request_mock):
stripe.multipart_data_generator.MultipartDataGenerator\
._initialize_boundary = lambda self: 1234567890
test_file = tempfile.TemporaryFile()
resource = stripe.File.create(
purpose='dispute_evidence',
file=test_file
)
request_mock.assert_api_base(stripe.upload_api_base)
request_mock.assert_requested(
'post',
'/v1/files',
headers={
'Content-Type': 'multipart/form-data; boundary=1234567890',
}
)
assert isinstance(resource, stripe.File)

def test_deserializes_from_file(self):
obj = stripe.util.convert_to_stripe_object({
'object': 'file',
})
assert isinstance(obj, stripe.File)

def test_deserializes_from_file_upload(self):
obj = stripe.util.convert_to_stripe_object({
'object': 'file_upload',
})
assert isinstance(obj, stripe.File)
25 changes: 24 additions & 1 deletion tests/api_resources/test_file_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,23 @@

import tempfile

import pytest

import stripe


TEST_RESOURCE_ID = 'file_123'


class TestFileUpload(object):
@pytest.fixture(scope='function')
def setup_upload_api_base(self):
stripe.upload_api_base = stripe.api_base
stripe.api_base = None
yield
stripe.api_base = stripe.upload_api_base
stripe.upload_api_base = 'https://files.stripe.com'

def test_is_listable(self, request_mock):
resources = stripe.FileUpload.list()
request_mock.assert_requested(
Expand All @@ -26,14 +36,15 @@ def test_is_retrievable(self, request_mock):
)
assert isinstance(resource, stripe.FileUpload)

def test_is_creatable(self, request_mock):
def test_is_creatable(self, setup_upload_api_base, request_mock):
stripe.multipart_data_generator.MultipartDataGenerator\
._initialize_boundary = lambda self: 1234567890
test_file = tempfile.TemporaryFile()
resource = stripe.FileUpload.create(
purpose='dispute_evidence',
file=test_file
)
request_mock.assert_api_base(stripe.upload_api_base)
request_mock.assert_requested(
'post',
'/v1/files',
Expand All @@ -42,3 +53,15 @@ def test_is_creatable(self, request_mock):
}
)
assert isinstance(resource, stripe.FileUpload)

def test_deserializes_from_file(self):
obj = stripe.util.convert_to_stripe_object({
'object': 'file',
})
assert isinstance(obj, stripe.FileUpload)

def test_deserializes_from_file_upload(self):
obj = stripe.util.convert_to_stripe_object({
'object': 'file_upload',
})
assert isinstance(obj, stripe.FileUpload)
5 changes: 1 addition & 4 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from tests.request_mock import RequestMock


MOCK_MINIMUM_VERSION = '0.30.0'
MOCK_MINIMUM_VERSION = '0.32.0'
MOCK_PORT = os.environ.get('STRIPE_MOCK_PORT', 12111)


Expand Down Expand Up @@ -43,21 +43,18 @@ def setup_stripe():
'api_key': stripe.api_key,
'client_id': stripe.client_id,
'default_http_client': stripe.default_http_client,
'upload_api_base': stripe.upload_api_base,
}
http_client = stripe.http_client.new_default_http_client()
stripe.api_base = 'http://localhost:%s' % MOCK_PORT
stripe.api_key = 'sk_test_123'
stripe.client_id = 'ca_123'
stripe.default_http_client = http_client
stripe.upload_api_base = 'http://localhost:%s' % MOCK_PORT
yield
http_client.close()
stripe.api_base = orig_attrs['api_base']
stripe.api_key = orig_attrs['api_key']
stripe.client_id = orig_attrs['client_id']
stripe.default_http_client = orig_attrs['default_http_client']
stripe.upload_api_base = orig_attrs['upload_api_base']


@pytest.fixture
Expand Down
19 changes: 19 additions & 0 deletions tests/request_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,25 @@ def stub_request(self, method, url, rbody={}, rcode=200, rheaders={}):
self._stub_request_handler.register(method, url, rbody, rcode,
rheaders)

def assert_api_base(self, expected_api_base):
# Note that this method only checks that an API base was provided
# as a keyword argument in APIRequestor's constructor, not as a
# positional argument.

if 'api_base' not in self.constructor_patcher.call_args[1]:
msg = ("Expected APIRequestor to have been constructed with "
"api_base='%s'. No API base was provided." %
expected_api_base)
raise AssertionError(msg)

actual_api_base = \
self.constructor_patcher.call_args[1]['api_base']
if actual_api_base != expected_api_base:
msg = ("Expected APIRequestor to have been constructed with "
"api_base='%s'. Constructed with api_base='%s' "
"instead." % (expected_api_base, actual_api_base))
raise AssertionError(msg)

def assert_api_version(self, expected_api_version):
# Note that this method only checks that an API version was provided
# as a keyword argument in APIRequestor's constructor, not as a
Expand Down

0 comments on commit 2226f47

Please sign in to comment.