GithubHelp home page GithubHelp logo

balanced-python's Introduction

Balanced

Online Marketplace Payments

Build Status Latest Version Downloads Supported Python versions License

v1.x requires Balanced API 1.1. Use v0.x for Balanced API 1.0.

Installation

pip install balanced

Usage

View Balanced's online tutorial and documentation at https://www.balancedpayments.com/docs/overview?language=python

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Write your code and unit tests
  4. Ensure all tests still pass (nosetests)
  5. PEP8 your code
  6. Commit your changes (git commit -am 'Add some feature')
  7. Push to the branch (git push origin my-new-feature)
  8. Create new pull request

Documentation scenarios

Each scenario lives in the scenarios directory and is comprised of the following:

  • definition.mako - Method definition
  • request.mako - Scenario code
  • executable.py - Processed request.mako. Can be executed directly in Python. Generated by render_scenarios.py.
  • python.mako - Documentation template to be consumed by balanced-docs. Generated by - render_scenarios.py.

balanced-python's People

Contributors

areski avatar chadwhitacre avatar fangpenlin avatar icook avatar jrus avatar julianpistorius avatar mahmoudimus avatar matthewfl avatar mjallday avatar msherry avatar pnegahdar avatar remear avatar rloomba avatar rofrankel avatar rserna2010 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

balanced-python's Issues

balanced-python on Windows?

I am not sure how to set it up!

c:\Python27\Scripts>easy_install.exe balanced
Searching for balanced
Reading http://pypi.python.org/simple/balanced/
Reading https://balancedpayments.com/
Reading https://github.com/mahmoudimus
Best match: balanced 0.8.19
Downloading http://pypi.python.org/packages/source/b/balanced/balanced-0.8.19.t
r.gz#md5=6bc6c7ca483fbdcc34e35d7da32e9734
Processing balanced-0.8.19.tar.gz
Running balanced-0.8.19\setup.py -q bdist_egg --dist-dir c:\users\admini~1\appd
ta\local\temp\easy_install-ga4fqs\balanced-0.8.19\egg-dist-tmp-o8zpfm
error: c:\users\admini~1\appdata\local\temp\easy_install-ga4fqs\balanced-0.8.19
README.rst: No such file or directory

c:\Python27\Scripts>

I notice that README is a symlink to README.rst, maybe this is the problem?

Write a test for sideloading

Given the payload

{
    "debits": [
        {
            "amount": 5000, 
            "appears_on_statement_as": "BAL*Statement text", 
            "created_at": "2014-02-27T20:03:06.176697Z", 
            "currency": "USD", 
            "description": "Some descriptive text for the debit in the dashboard", 
            "failure_reason": null, 
            "failure_reason_code": null, 
            "href": "/debits/WD1l5vYA21ZP24LMQMqHizea", 
            "id": "WD1l5vYA21ZP24LMQMqHizea", 
            "links": {
                "customer": null, 
                "dispute": null, 
                "order": null, 
                "source": "CC1diaA1Lunr4RlelwKQ8C4v"
            }, 
            "meta": {}, 
            "status": "succeeded", 
            "transaction_number": "W347-910-8642", 
            "updated_at": "2014-02-27T20:03:07.629780Z"
        }
    ], 
    "foos": [
        {
        }
    ], 
    "links": {
        "debits.customer": "/customers/{debits.customer}", 
        "debits.dispute": "/disputes/{debits.dispute}", 
        "debits.events": "/debits/{debits.id}/events", 
        "debits.order": "/orders/{debits.order}", 
        "debits.refunds": "/debits/{debits.id}/refunds", 
        "debits.source": "/resources/{debits.source}"
    }
}

Make sure that this client library does not choke and return the wrong object.

Debit class has no `self.refunds_uri`

Been looking at this class:

class Debit(Resource):
    """
    A Debit represents a transfer of funds from a buyer's Account to your
    Marketplace's escrow account.

    A Debit may be created directly, or it will be created as a side-effect
    of capturing a Hold. If you create a Debit directly it will implicitly
    create the associated Hold if the funding source supports this.

    If no Hold is specified, the Debit will by default be created using the
    most recently added funding source associated with the Account. You
    cannot change the funding source between creating a Hold and capturing
    it.
    """
    __metaclass__ = resource_base(collection='debits')

    def refund(self, amount=None, description=None, meta=None):
        """
        Refunds this Debit. If no amount is specified it will refund the entire
        amount of the Debit, you may create many Refunds up to the sum total
        of the original Debit's amount.

        :rtype: Refund
        """
        meta = meta or {}
        return Refund(
            uri=self.refunds_uri,
            debit_uri=self.uri,
            amount=amount,
            description=description,
            meta=meta,
        ).save()

But when you try to use this, you get
AttributeError: 'Debit' object has no attribute 'refunds_uri'

I tried changing self.refunds_uri to self.uri but then I got:
HTTPError: Method Not Allowed: 405: Your request id is OHM2f81d254500c11e...redacted....

Unable to add buyer w/o card URI

I was trying to add a buyer without a card URI as I was wanting to write my program in steps instead of doing 2 things at once.

client = balanced.Marketplace.my_marketplace.create_buyer(email, None)

This returns an issue saying that None is not a valid card URI.

client = balanced.Marketplace.my_marketplace.create_buyer(email, {})

This returns saying that "{}" needs to be a URI

client = balanced.Marketplace.my_marketplace.create_buyer(email, "")

Same as using None.

The fix for this is to do the following:

client = balanced.Account(uri=balanced.Marketplace.my_marketplace.accounts_uri,email_address=email).save()

Perhaps there can be an easier fix for this, though?

Iterator is broken

ipdb> balanced.BankAccount.query.total
14
ipdb> len([x for x in balanced.BankAccount.query])
10
ipdb> balanced.__version__
'0.9.1'

Filtering debits with on_behalf_of_uri does not work

I run:

balanced.Debit.query.filter(**{'on_behalf_of_uri': profile.balanced_account_uri}).all()

and receive a following Exception:

Bad Request: 400: /v1/customers/CU44MWOCekwfDwUyY0PkzAam does not resolve to a valid customer Your request id is OHM019556dc7ca211e3aec5026ba7c1aba6.

Another similar issue but it is with another package and it does not solve my problem: balanced/balanced-api#413

Do I miss anything?
I appreciate any help.

Resource query all to a empty list bug

Just spotted a bug, when you query to a resource which has no records in result, like this

balanced.Credit.query.all()

an error will be raised:

Traceback (most recent call last):
  File "\env\lib\site-packages\unittest2\case.py", line 340, in run
    testMethod()
  File "\tests\test_suite.py", line 354, in test_empty_list
    balanced.Credit.query.all()
  File "\env\lib\site-packages\wac-0.22-py2.7.egg\wac.py", line 776, in all
    return list(self)
  File "\env\lib\site-packages\wac-0.22-py2.7.egg\wac.py", line 801, in __iter__
    for v in page.items:
  File "\balanced\resources.py", line 128, in items
    return self.event_callbacks
AttributeError: 'JSONSchemaPage' object has no attribute 'event_callbacks'

This is caused by no corresponding item key name in the result

{
  "meta": {
    "last": "/credits?limit=25&offset=0",
    "next": null,
    "href": "/credits?limit=25&offset=0",
    "limit": 25,
    "offset": 0,
    "previous": null,
    "total": 0,
    "first": "/credits?limit=25&offset=0"
  },
  "links": {}
}

Is this an expected behavior of API service? Or it should at least have a key to an empty list in the result?

balanced-python does not run on Windows

Running python examples.py crashes with the following error:

C:\tmp\balanced-python\examples>python examples.py
create our new api key
Traceback (most recent call last):
  File "examples.py", line 17, in <module>
    api_key = balanced.APIKey().save()
  File "c:\tmp\balanced-python\balanced\resources.py", line 264, in save
    resource = method(uri, data=instance_attributes)
  File "c:\tmp\balanced-python\balanced\http_client.py", line 103, in make_absolute_url
    return http_op(client, url, **kwargs)
  File "c:\tmp\balanced-python\balanced\http_client.py", line 132, in post
    resp = self.interface.post(uri, data=data, **kwargs)
  File "build\bdist.win-amd64\egg\requests\sessions.py", line 259, in post
  File "build\bdist.win-amd64\egg\requests\sessions.py", line 209, in request
  File "build\bdist.win-amd64\egg\requests\models.py", line 607, in send
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='api.balancedpayments.com%5Cv1%5Capi_keys', port=443): Max retries exceeded with url: /

support requests 1.2.x

The requirements.txt for balanced-python currently pegs requests at 1.1.0. The current version of requests is 1.2.3. Balanced-python breaks under 1.2.3 because apparently response hooks now have to take *_kwargs where they didn't before (the docs appear not to reflect this change). This manifests in the tests and the fix is simple (add *_kwargs to the signature for wrapper in balanced.http_client.wrap_response_for_status).

Multithreaded use of the library

balanced.configure() must be called for every thread since the configuration inherits from threading.Local. This is not mentioned anywhere in the documentation, and causes issues in development - when using the interpreter or test scripts everything will work, but on an actual multi-threaded web server, things will start breaking for what can seem to be no reason at all.

Card.associate_to_customer(customer) fails

When I call: MYCARD.associate_to_customer(customer)
It fails to save when adding new attribute 'links' to Card object as indicated in resources.py:

class FundingInstrument(Resource):
...
    def associate_to_customer(self, customer):
        try:
            self.links
        except AttributeError:
            self.links = {}
        self.links['customer'] = utils.extract_href_from_object(customer)
        self.save()

In fact, at the end of saving process, MYCARD got a new attribute called 'customer_href' instead of 'links' that I expected. Next, I fetch MYCARD again to see its response, but neither 'links' nor 'customer_href' is on MYCARD. However, the number of cards associated with the customer increases by one.

I'd appreciate any help.
Thanks!

Identity map is not properly mapped in the Python client

If I delete a card from a Customer:

customer.cards[0].delete()

and the customer only has 1 card, any further operation on the customer object will issue a PUT on the actual customer object, however, the source_uri which might reference the deleted card will throw a 409 since that card will have been deleted.

Here's an executable snippet:

card = balanced.Card.find('/v1/marketplaces/:marketplace_id/cards/:card_id')
customer = balanced.Customer().save()
customer.add_card(card.uri)
assert len(customer.cards) == 1
assert customer.cards[0].uri == card.uri
assert customer.source_uri == card.uri
customer.cards[0].delete()
assert len(customer.cards) == 0
customer.source_uri # this still exists, it should be None!

indexing into account.cards not working as expected

Over on Gittip, I'm seeing behavior like this:

(Pdb) self._account.cards.total
18
(Pdb) self._account.cards[13]
Card(...)
(Pdb) self._account.cards[14]
*** IndexError: list index out of range
(Pdb) self._account.cards[-1]
*** IndexError: list index out of range
(Pdb) 

Large collections generate RuntimeError

Bam,

/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/balanced/resources.pyc in __iter__(self)                                                                                               [102/1962]
    131     def __iter__(self):
    132         if self.next_page is not None:
--> 133             for resource in itertools.chain(self.items, self.next_page):
    134                 yield resource
    135         else:

/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/balanced/resources.pyc in __iter__(self)
    131     def __iter__(self):
    132         if self.next_page is not None:
--> 133             for resource in itertools.chain(self.items, self.next_page):
    134                 yield resource
    135         else:

/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/balanced/resources.pyc in __iter__(self)
    131     def __iter__(self):
    132         if self.next_page is not None:
--> 133             for resource in itertools.chain(self.items, self.next_page):
    134                 yield resource
    135         else:

/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/balanced/resources.pyc in __iter__(self)
    131     def __iter__(self):
    132         if self.next_page is not None:
--> 133             for resource in itertools.chain(self.items, self.next_page):
    134                 yield resource
    135         else:

/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/balanced/resources.pyc in __iter__(self)
    131     def __iter__(self):
    132         if self.next_page is not None:
--> 133             for resource in itertools.chain(self.items, self.next_page):
    134                 yield resource
    135         else:

/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/balanced/resources.pyc in __iter__(self)
    130 
    131     def __iter__(self):
--> 132         if self.next_page is not None:
    133             for resource in itertools.chain(self.items, self.next_page):
    134                 yield resource

/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/balanced/resources.pyc in next_page(self)
    211     @property
    212     def next_page(self):
--> 213         if 'next_uri' in self._lazy_loaded:
    214             uri = self._lazy_loaded['next_uri']
    215             return self._fetch(uri)

/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/balanced/utils.pyc in __get__(self, obj, type)
    188         value = obj.__dict__.get(self.__name__, _missing)
    189        
    189         if value is _missing:                                                                                                                                                                 --> 190             value = self.func(obj)
    191             obj.__dict__[self.__name__] = value
    192         return value

/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/balanced/resources.pyc in _lazy_loaded(self)
    177     def _lazy_loaded(self):
    178         page = self._fetch(self.uri)
--> 179         response = Resource.http_client.get(page.uri)
    180         return response.deserialized
    181 

/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/balanced/http_client.pyc in make_absolute_url(client, url, **kwargs)
    124         _before_request(client, http_op, url, kwargs)
    125 
--> 126         return http_op(client, url, **kwargs)
    127 
    128     return make_absolute_url

/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/balanced/http_client.pyc in get(self, uri, **kwargs)
    146     def get(self, uri, **kwargs):
    147         kwargs = self.serialize(kwargs.copy())
--> 148         resp = self.interface.get(uri, **kwargs)
    149         resp.deserialized = self.deserialize(resp)
    150         return resp

/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/requests/sessions.pyc in get(self, url, **kwargs)
    308 
    309         kwargs.setdefault('allow_redirects', True)
--> 310         return self.request('GET', url, **kwargs)
    311 
    312     def options(self, url, **kwargs):

/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/requests/sessions.pyc in request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream
, verify, cert)
    277 
    278         # Send the request.

--> 279         resp = self.send(prep, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies)
    280 
    281         # Persist cookies.


/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/requests/sessions.pyc in send(self, request, **kwargs)
    372         """Send a given PreparedRequest."""
    373         adapter = self.get_adapter(url=request.url)
--> 374         r = adapter.send(request, **kwargs)
    375         return r
    376 

/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/requests/adapters.pyc in send(self, request, stream, timeout, verify, cert, proxies)
    217                 raise Timeout('Request timed out.')
    218 
--> 219         r = self.build_response(request, resp)
    220 
    221         if not stream:

/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/requests/adapters.pyc in build_response(self, req, resp)
     85 
     86     def build_response(self, req, resp):
---> 87         response = Response()
     88 
     89         # Fallback to None if there's no status_code, for whatever reason.


/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/requests/models.pyc in __init__(self)
    455 
    456         #: A CookieJar of Cookies the server sent back.

--> 457         self.cookies = cookiejar_from_dict({})
    458 
    459     def __repr__(self):

/home/deploy/.virtualenvs/justice/lib/python2.7/site-packages/requests/cookies.pyc in cookiejar_from_dict(cookie_dict, cookiejar)
    366     """
    367     if cookiejar is None:
--> 368         cookiejar = RequestsCookieJar()
    369 
    370     if cookie_dict is not None:

/usr/local/lib/python2.7/cookielib.pyc in __init__(self, policy)
   1220         self._policy = policy
   1221 
-> 1222         self._cookies_lock = _threading.RLock()
   1223         self._cookies = {}
   1224 

/usr/local/lib/python2.7/threading.pyc in RLock(*args, **kwargs)
     99 
    100 def RLock(*args, **kwargs):
--> 101     return _RLock(*args, **kwargs)
    102 
    103 class _RLock(_Verbose):

/usr/local/lib/python2.7/threading.pyc in __init__(self, verbose)
    104 
    105     def __init__(self, verbose=None):
--> 106         _Verbose.__init__(self, verbose)
    107         self.__block = _allocate_lock()
    108         self.__owner = None

RuntimeError: maximum recursion depth exceeded while calling a Python object

update to newest version of requests

The requests library has gone through big changes since the April 2012 version the balanced python client requires: http://pypi.python.org/pypi/requests#history

It had some backwards incompatible changes w/ the big refactor/rewrite 1.0 release, but that's now 2 months ago, so it might be stable enough to rely on by now. Might take a bit of reworking of our code, I don’t know how hard it would be.

Also worth investigating is version 0.14.2 of Requests from the end of October, the last version before the big refactor.

When trying to run on google app engine, the python client currently fails, because requests can't find a list of certificate authority keys, and therefore raises an exception. It’s possible to work around this by leaving the same requests version and modifying the balanced python client. But it also might fix things to just use a newer version of the library. I haven’t done much testing of it.

Does not work with python <= 2.6

>>> balanced.Card(card_number='4111111111111111', expiration_month=12, expiration_year=2020).save()
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "/usr/local/lib/python2.6/dist-packages/balanced/resources.py", line 356, in the_init
     self.uri = uri_discovery(self)
   File "/usr/local/lib/python2.6/dist-packages/balanced/resources.py", line 265, in uri_discovery
     resource.RESOURCE['collection']
 ValueError: zero length field name in format

Deleted bank accounts returned via INDEX operations

In [3]: balanced.configure('441ba950ea6411e2950a026ba7cac9da')

In [4]: balanced.BankAccount.query.all()
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-4-93cf3ced395f> in <module>()
----> 1 balanced.BankAccount.query.all()

/Users/marshall/.virtualenvs/tmp/lib/python2.7/site-packages/balanced/resources.pyc in all(self)
    162 
    163     def all(self):
--> 164         return list(self)
    165 
    166     def one(self):

/Users/marshall/.virtualenvs/tmp/lib/python2.7/site-packages/balanced/resources.pyc in __iter__(self)
    133     def __iter__(self):
    134         if self.next_page is not None:
--> 135             for resource in itertools.chain(self.items, self.next_page):
    136                 yield resource
    137         else:

/Users/marshall/.virtualenvs/tmp/lib/python2.7/site-packages/balanced/resources.pyc in items(self)
    190     def items(self):
    191         for item in self._lazy_loaded['items']:
--> 192             _resource = _RESOURCES.from_uri(item['uri'])
    193             yield _resource(**item)
    194 

KeyError: 'uri'

Saving a card with no changes invalidates the card

import balanced

key = balanced.APIKey().save()
balanced.configure(key.secret)
balanced.Marketplace().save()

card = balanced.Marketplace.my_marketplace.create_card(
    name='John Stewart',
    card_number='5105105105105100',
    expiration_month='12',
    expiration_year='2020',
    security_code='123',
).save()

buyer = balanced.Marketplace.my_marketplace.create_buyer('[email protected]', card_uri=card.uri)

Results in

HTTPError: Conflict: 409: Card has been invalidated. Your request id is OHM5f1366d2f7bf11e187e4026ba7d31e6f. 

BankAccount object '.bank_account_verification' returns a Resource instead of BankAccountVerification object

Pretty self-explanatory:

(Pdb) type(ba)
<class 'balanced.resources.BankAccount'>
(Pdb) ba.bank_account_verification_href
'/verifications/BZ6Wlrqn6kqANUl3HJxsyPdJ'
(Pdb) ba.bank_account_verification
Resource(verification_status='pending', created_at='2014-03-10T23:01:19.050446Z', attempts_remaining=3, updated_at='2014-03-10T23:01:19.419339Z', deposit_status='succeeded', attempts=0, href='/verifications/BZ6Wlrqn6kqANUl3HJxsyPdJ', meta={}, bank_account_href='/bank_accounts/BA31VS8QfKfs66zycQpCtQaY', id='BZ6Wlrqn6kqANUl3HJxsyPdJ')

I'd expect to receive a BankAccountVerification object instead. As a workaround I am doing this:

balanced.BankAccountVerification.fetch(ba.bank_account_verification_href)

Indexing is broked

ipdb> buyer_account.cards.count()
3
ipdb> card = buyer_account.cards[-1]
*** IndexError: list index out of range

also

ipdb> len(buyer_account.cards)
*** TypeError: object of type 'Page' has no len()

Make balanced-python compatible with python 3

Hi all,

I recently started looking into developing a django website using python 3.3, but when looking at django-balanced, I found it isn't compatible with python 3, in part because balanced-python isn't compatible. I'm opening this issue to help gauge interest in updating balanced-python to python 3.

Error messages not descriptive

In [7]: debit = balanced.Debit(source=card_uri, amount=100).save()                                                  
---------------------------------------------------------------------------
HTTPError                                 Traceback (most recent call last)
<ipython-input-7-2ae239434505> in <module>()
----> 1 debit = balanced.Debit(source=card_uri, amount=100).save()

/Users/marshall/code/balanced/balanced-python/balanced/resources.pyc in save(self)
    157         )
    158 
--> 159         resp = method(href, data=attrs)
    160 
    161         instance = self.__class__(**resp.data)

/Users/marshall/.virtualenvs/balanced-python/lib/python2.7/site-packages/wac.py in post(self, uri, data, **kwargs)
    452         kwargs.setdefault('headers', {})
    453         kwargs['headers']['Content-Type'] = mime_type
--> 454         return self._op(self.interface.post, uri, data=data, **kwargs)
    455 
    456     def put(self, uri, data=None, **kwargs):

/Users/marshall/.virtualenvs/balanced-python/lib/python2.7/site-packages/wac.py in _op(self, f, uri, **kwargs)
    510                 handle_redirect(response)
    511         except requests.HTTPError as ex:
--> 512             handle_error(ex)
    513 
    514         response.data = None

/Users/marshall/.virtualenvs/balanced-python/lib/python2.7/site-packages/wac.py in handle_error(ex)
    487                 raise Redirection(ex)
    488             ex = self.config.error_cls(ex)
--> 489             raise ex
    490 
    491         kwargs.setdefault('headers', {})

HTTPError: 400 Client Error: BAD REQUEST

I want "HTTPError: 400 Client Error: BAD REQUEST - Some descriptive error message here"

BankAccount bank_account_verification field

Hello,

The bank_account_verification field seems to be of the wrong type:

In [2]: ba = balanced.BankAccount.fetch('/bank_accounts/BA372SBS9pJDmYAAr0tGcSfS')

In [3]: type(ba.bank_account_verification)
Out[3]: balanced.resources.JSONSchemaCollection

In [4]: type(ba.bank_account_verifications)
Out[4]: balanced.resources.JSONSchemaCollection

Am I missing something here? I'd expect bank_account_verification to be the latest one (or None if not present).

Thanks!

Better filtering of already-existing cards

Right now you're not able to filter balanced.Marketplace.cards by last_four, and instead need to do something like this:

    def search_cc(self, cc):
        if not isinstance(cc, str):
            print "%d is not a string.  Converting." % (cc)
            cc = str(cc)
            print "cc =", cc

        if len(cc) > 4:
            cc = cc[-4:]
            print "Fetched last 4:", cc
        elif len(cc) < 4:
            print "Invalid length for CC"
            return False

        try:
            cards = list(balanced.Marketplace.query.one().cards)

            for card in cards:
                if card.last_four == cc:
                    return card
        except:
            pass

        return None

While ultimately it comes down to the last 8 non-whitespace lines, it'd be a lot more efficient to be able to just do something like this:

def cc_exists(last_four):
    try:
        return balanced.Marketplace.query.filter(last_four=last_four)
    except:
        return None

Use type information to infer object type

Currently the python client uses meta classes and URLs to specify the type of object.

The API now returns type information (see _type param below) on all resources when they are returned. Using this instead allows us to break away from inspecting the URL to see the type of object that something is and gives us more flexibility in naming conventions.

$ curl https://api.balancedpayments.com/v1/api_keys -X POST
{
  "_type": "api_key", 
  "created_at": "2013-05-06T21:37:38.888923Z", 
  "uri": "/v1/api_keys/AK1m8dgKozaJwrv1BaYBesYn", 
  "_uris": {}, 
  "meta": {}, 
  "id": "AK1m8dgKozaJwrv1BaYBesYn"
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.