Braintree Python library

Overview

Braintree Python library

The Braintree Python library provides integration access to the Braintree Gateway.

TLS 1.2 required

The Payment Card Industry (PCI) Council has mandated that early versions of TLS be retired from service. All organizations that handle credit card information are required to comply with this standard. As part of this obligation, Braintree has updated its services to require TLS 1.2 for all HTTPS connections. Braintrees require HTTP/1.1 for all connections. Please see our technical documentation for more information.

Dependencies

The Braintree Python SDK is tested against Python versions 3.5.3 and 3.8.0.

The Python core development community has released End-of-Life branches for Python versions 2.7 - 3.4, and are no longer receiving security updates. As a result, Braintree no longer supports these versions of Python.

Versions

Braintree employs a deprecation policy for our SDKs. For more information on the statuses of an SDK check our developer docs.

Major version number Status Released Deprecated Unsupported
4.x.x Active March 2020 TBA TBA
3.x.x Inactive June 2014 March 2022 March 2023

Documentation

Updating from an Inactive, Deprecated, or Unsupported version of this SDK? Check our Migration Guide for tips.

Quick Start Example

import braintree

gateway = braintree.BraintreeGateway(
    braintree.Configuration(
        environment=braintree.Environment.Sandbox
        merchant_id="your_merchant_id",
        public_key="your_public_key",
        private_key="your_private_key",
    )
)

result = gateway.transaction.sale({
    "amount": "1000.00",
    "payment_method_nonce": nonce_from_the_client,
    "options": {
        "submit_for_settlement": True
    }
})

if result.is_success:
    print("success!: " + result.transaction.id)
elif result.transaction:
    print("Error processing transaction:")
    print("  code: " + result.transaction.processor_response_code)
    print("  text: " + result.transaction.processor_response_text)
else:
    for error in result.errors.deep_errors:
        print("attribute: " + error.attribute)
        print("  code: " + error.code)
        print("  message: " + error.message)

Developing

  1. Create a virtualenv called venv:

    virtualenv venv
    
  2. Start the virtualenv:

    source venv/bin/activate
    
  3. Install dependencies:

    pip3 install -r dev_requirements.txt
    

Developing (Docker)

The Makefile and Dockerfile will build an image containing the dependencies and drop you to a terminal where you can run tests.

make

Testing

Our friends at Venmo have an open source library designed to simplify testing of applications using this library.

If you wish to run the tests, make sure you are set up for development (see instructions above). The unit specs can be run by anyone on any system, but the integration specs are meant to be run against a local development server of our gateway code. These integration specs are not meant for public consumption and will likely fail if run on your system. To run unit tests use rake (rake test:unit) or nose (nosetests tests/unit).

License

See the LICENSE file for more info.

Comments
  • setup.py improvements and universal wheels

    setup.py improvements and universal wheels

    Re-re-hash of the rejected #74 and #75.

    Includes these changes:

    • Add a link from PyPI direct to the Github repository, so people can find the changelog. It's really annoying when upgrading to have to resort to Google-sleuthing to find the changelog to see if there are any breaking changes.
    • Prefer to use setuptools rather than distutils, because the future is now. setuptools is installed in nearly every Python environment these days because pip always includes it. It supports deployment of universal wheels. By falling back to distutils when it can't be imported, we still support source installations in legacy environments.
    • Include releasing as a universal wheel to speed up users' installs. See #75 for instructions.
    opened by adamchainz 15
  • Unable to JSON Serialize Result

    Unable to JSON Serialize Result

    General information

    • SDK/Library version: 3.46.0
    • Language, language version, and OS: Python 2.7.0 | MacOS

    Issue description

    Hello, I'm having trouble JSON serializing the result object that is returned when calling gateway.subscription.create. I've tried using json.dumps and it just tells me the object cannot be serialized. I'm sure this is something I'm doing wrong, but I don't really know where else to go.

    Thank you.

    opened by selected-pixel-jameson 11
  • TypeError: cannot make memory view because object does not have the buffer interface

    TypeError: cannot make memory view because object does not have the buffer interface

    This error happens when running braintree.Customer.create({'email': email}) where email is the user's email address.

    Traceback (most recent call last):
      File "/opt/wakatime/current/venv/local/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
        response = self.full_dispatch_request()
      File "/opt/wakatime/current/venv/local/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
        rv = self.handle_user_exception(e)
      File "/opt/wakatime/current/venv/local/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
        reraise(exc_type, exc_value, tb)
      File "/opt/wakatime/current/venv/local/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
        rv = self.dispatch_request()
      File "/opt/wakatime/current/venv/local/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
        return self.view_functions[rule.endpoint](**req.view_args)
      File "/opt/wakatime/current/venv/local/lib/python2.7/site-packages/flask_login.py", line 792, in decorated_view
        return func(*args, **kwargs)
      File "/opt/wakatime/current/app/api_v1.py", line 295, in post_users_current_payment_method
        app.current_user.update_payment_method(processor_type, **form.data)
      File "/opt/wakatime/current/app/models.py", line 924, in update_payment_method
        self.processor.update_payment_method(kwargs['token'])
      File "/opt/wakatime/current/app/models.py", line 3435, in update_payment_method
        'customer_id': self.customer.id,
      File "/opt/wakatime/current/app/models.py", line 3319, in customer
        self._customer = PaymentProcessor.get_customer(self.user, self.type)[0]
      File "/opt/wakatime/current/app/models.py", line 3294, in get_customer
        'email': user.email,
      File "/opt/wakatime/current/venv/local/lib/python2.7/site-packages/braintree/customer.py", line 102, in create
        return Configuration.gateway().customer.create(params)
      File "/opt/wakatime/current/venv/local/lib/python2.7/site-packages/braintree/customer_gateway.py", line 26, in create
        return self._post("/customers", {"customer": params})
      File "/opt/wakatime/current/venv/local/lib/python2.7/site-packages/braintree/customer_gateway.py", line 88, in _post
        response = self.config.http().post(self.config.base_merchant_path() + url, params)
      File "/opt/wakatime/current/venv/local/lib/python2.7/site-packages/braintree/util/http.py", line 49, in post
        return self.__http_do("POST", path, params)
      File "/opt/wakatime/current/venv/local/lib/python2.7/site-packages/braintree/util/http.py", line 72, in __http_do
        raise e
    TypeError: cannot make memory view because object does not have the buffer interface
    
    opened by alanhamlett 11
  • Remove pycurl

    Remove pycurl

    looked like pycurl was only being used to validate the SSL cert which can be done with a simple backport from 3.0, which I included in this path.

    by removing pycurl as a dependency it makes the library much more accessible especially in cases where the target deploy can't build pycurl as it depends on the curl development headers to be able to compile which are not always available on different hosts.

    thanks, Patrick Altman Eldarion, Inc.

    opened by paltman 11
  • braintree calls raise NoCertificate when setdefaulttimeout() has been used.

    braintree calls raise NoCertificate when setdefaulttimeout() has been used.

    I'm currently seeing this problem with Customer.create(), but it probably applies to all braintree API calls which contact the server. These calls are failing, raising a spurious NoCertificate exception with this message: "peer did not return certificate"

    This appears to be caused by a known bug in m2crypto: https://bugzilla.osafoundation.org/show_bug.cgi?id=2341 http://bytes.com/topic/python/answers/586302-wierd-m2crypto-bug-phony-peer-did-not-return-certificate-error

    Our application calls socket.setdefaulttimeout() to make it gracefully handle cases when third-party libraries contact unresponsive servers. This is still pretty common in the python world, since per-connection timeout support was only recently added to urllib2 and many libraries have not yet started using that feature. That means we can't reasonably stop using socket.setdefaulttimeout(). Unfortunately, it causes braintree calls to fail.

    So, as long as the braintree library depends on m2crypto for its https support, it seems we are stuck with either an incompatibility or (if we were to disable socket timeouts to work around the bug) a reliability problem.

    Perhaps it would make sense for the braintree python library to use pycurl instead of m2crypto, or better yet, expose a pluggable http/https fetcher API? (The latter would be especially nice when we migrate to App Engine. Of course, such a plugin API should support caller-specified timeouts. :)

    opened by foresto 9
  • Transparent Redirect field name brackets make integration difficult

    Transparent Redirect field name brackets make integration difficult

    This issue is not python-specific, but since I don't see a general Braintree tracker, I'm writing it up here.

    The bracket characters in Transparent Redirect field names make Braintree integration rather a pain. Aside from looking confusingly similar to first-class subscripting syntax in various programming languages, I have seen two specific problems so far:

    1. They are incompatible with web form construction/validation libraries that use native-language variables to represent form fields. (For example, the WTForms python library.) Since brackets are not allowed in most languages' variable names, creating a Braintree form in a project that uses such libraries requires either laboriously writing form-processing code by hand, or else jumping through hoops to make the libraries work with reduced functionality.
    2. They do not conform to the HTML ID and NAME requirements, and therefore produce invalid HTML when used in templating systems that generate <input id=""> and <label for=""> tags from field names.

    There are workarounds for these problems, of course, but they make for overly-complicated special-case code, wasted time, and frustrated programmers.

    Would you folks consider supporting an alternative syntax for embedding structure in your field names? Separating sub-fields with double-underscores ought to work nicely. For example, instead of writing credit_card[options][make_default] one might write credit_card__options__make_default, which would be no longer than the former syntax and would also work as a variable/id name in every language that comes to mind.

    opened by foresto 9
  • Support Python 3.6 and 3.7

    Support Python 3.6 and 3.7

    General information

    • SDK/Library version: current master (591f322b5bbc)
    • Environment: n/a
    • Language, language version, and OS: Python 3.6/3.7 on any OS

    Issue description

    According to the README.md and setup.py files, the latest supported version of Python 3.5. Version 3.6 was released almost two years ago. Please test & support with the latest official release.

    opened by sybrenstuvel 8
  • TypeError: cannot concatenate 'str' and 'NoneType' objects

    TypeError: cannot concatenate 'str' and 'NoneType' objects

    When I do subscription.find(user.subscription_id), I get this error if user.subscription_id==None. I can of course change my code to:

    if user.subscription_id:
        subscription.find(user.subscription_id)
    

    so no real issue here :)

    The "offending" code is here: https://github.com/braintree/braintree_python/blob/master/braintree/subscription_gateway.py#L38

    And there's possibly a similar issue here (though it might be wise not to repr(nonce), I'm not sure): https://github.com/braintree/braintree_python/blob/master/braintree/credit_card_gateway.py#L58

    Suggesting those should be, respectively,

    • raise NotFoundError("subscription with id " + repr(subscription_id) + " not found")
    • raise NotFoundError("payment method with nonce " + repr(nonce) + " locked, consumed or not found")

    Tests:

    For test_subscription.py:

        @raises(NotFoundError)
        def test_finding_none_raises_not_found_exception(self):
            Subscription.find(None)
    

    For test_credit_card.py:

        @raises(NotFoundError)
        def test_from_nonce_as_none_raises_not_found_exception(self):
            CreditCard.from_nonce(None)
    
    opened by sharifyounes 6
  • SSLError (just started, this was working yesterday)

    SSLError (just started, this was working yesterday)

    Here is a traceback, I use braintree in my django app.

    Internal Server Error: /my-django-url/ Traceback (most recent call last): File "/Users/myuser/Projects/my_env/lib/python2.7/site-packages/django/core/handlers/exception.py", line 39, in inner response = get_response(request) File "/Users/myuser/Projects/my_env/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response response = self.process_exception_by_middleware(e, request) File "/Users/myuser/Projects/my_env/lib/python2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/Users/myuser/Projects/my_env/my_project/my_app/views.py", line 56, in my_function bt_authorization = braintree.ClientToken.generate() File "/Users/myuser/Projects/my_env/lib/python2.7/site-packages/braintree/client_token.py", line 16, in generate return gateway.generate(params) File "/Users/myuser/Projects/my_env/lib/python2.7/site-packages/braintree/client_token_gateway.py", line 24, in generate response = self.config.http().post(self.config.base_merchant_path() + "/client_token", params) File "/Users/myuser/Projects/my_env/lib/python2.7/site-packages/braintree/util/http.py", line 52, in post return self.__http_do("POST", path, params) File "/Users/myuser/Projects/my_env/lib/python2.7/site-packages/braintree/util/http.py", line 70, in __http_do status, response_body = http_strategy.http_do(http_verb, full_path, self.__headers(), request_body) File "/Users/myuser/Projects/my_env/lib/python2.7/site-packages/braintree/util/http.py", line 91, in http_do timeout=self.config.timeout File "/Users/myuser/Projects/my_env/lib/python2.7/site-packages/requests/api.py", line 110, in post return request('post', url, data=data, json=json, **kwargs) File "/Users/myuser/Projects/my_env/lib/python2.7/site-packages/requests/api.py", line 56, in request return session.request(method=method, url=url, **kwargs) File "/Users/myuser/Projects/my_env/lib/python2.7/site-packages/requests/sessions.py", line 488, in request resp = self.send(prep, **send_kwargs) File "/Users/myuser/Projects/my_env/lib/python2.7/site-packages/requests/sessions.py", line 609, in send r = adapter.send(request, **kwargs) File "/Users/myuser/Projects/my_env/lib/python2.7/site-packages/requests/adapters.py", line 497, in send raise SSLError(e, request=request) SSLError: [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:590)

    So, I'm not sure if this is a requests issue or how braintree is using requests. Pretty odd though!

    opened by teewuane 6
  • AttributeError: 'unicode' object has no attribute 'items'

    AttributeError: 'unicode' object has no attribute 'items'

    This line misses Python2 unicode strings, eventually causing an AttributeError exception.

    Traceback (most recent call last):
      File "/opt/wakatime/current/venv/local/lib/python2.7/site-packages/braintree/subscription.py", line 150, in update
        return Configuration.gateway().subscription.update(subscription_id, params)
      File "/opt/wakatime/current/venv/local/lib/python2.7/site-packages/braintree/subscription_gateway.py", line 59, in update
        Resource.verify_keys(params, Subscription.update_signature())
      File "/opt/wakatime/current/venv/local/lib/python2.7/site-packages/braintree/resource.py", line 9, in verify_keys
        params_keys = Resource.__flattened_params_keys(params)
      File "/opt/wakatime/current/venv/local/lib/python2.7/site-packages/braintree/resource.py", line 27, in __flattened_params_keys
        keys += Resource.__flattened_params_keys(val, full_key)
      File "/opt/wakatime/current/venv/local/lib/python2.7/site-packages/braintree/resource.py", line 30, in __flattened_params_keys
        keys += Resource.__flattened_params_keys(item, full_key)
      File "/opt/wakatime/current/venv/local/lib/python2.7/site-packages/braintree/resource.py", line 24, in __flattened_params_keys
        for key, val in params.items():
    AttributeError: 'unicode' object has no attribute 'items'
    

    Should be basestring instead of str, or even better use six.string_types for Python 3 compatibility.

    opened by alanhamlett 6
  • Unable to use braintree_python on Google App Engine

    Unable to use braintree_python on Google App Engine

    AI responses are gzip-encoded, but the python library (probably the requests library) treats them as ASCII.

    File "xtras/braintree/customer.py", line 126, in find
        return Configuration.gateway().customer.find(customer_id)
      File "xtras/braintree/customer_gateway.py", line 36, in find
        response = self.config.http().get("/customers/" + customer_id)
      File "xtras/braintree/util/http.py", line 57, in get
        return self.__http_do("GET", path)
      File "xtras/braintree/util/http.py", line 82, in __http_do
        return XmlUtil.dict_from_xml(response_body)
      File "xtras/braintree/util/xml_util.py", line 11, in dict_from_xml
        return Parser(xml).parse()
      File "xtras/braintree/util/parser.py", line 15, in __init__
        self.doc = minidom.parseString("><".join(re.split(">\s+<", xml)).strip())
      File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xml/dom/minidom.py", line 1928, in parseString
        return expatbuilder.parseString(string)
      File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xml/dom/expatbuilder.py", line 940, in parseString
        return builder.parseString(string)
      File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xml/dom/expatbuilder.py", line 223, in parseString
        parser.Parse(string, True)
    UnicodeEncodeError: 'ascii' codec can't encode character u'\ufffd' in position 0: ordinal not in range(128)
    

    Modifying http_do() in util/http.py to unzip the content, makes the library work again, but this is probably a fragile way to fix this. (unzip() is just a wrapper to unzip raw data, nothing special.)

       def http_do(self, http_verb, path, headers, request_body):
            response = self.__request_function(http_verb)(
                self.environment.base_url + path,
                headers=headers,
                data=request_body,
                verify=self.environment.ssl_certificate,
                timeout=self.config.timeout
            )
            if response.headers['content-encoding']=='gzip':
                return [response.status_code, unzip(response.content)]
            else:
                return [response.status_code, response.text]
    
    opened by vrypan 6
  • strings with special regex characters are causing a DeprecationWarning

    strings with special regex characters are causing a DeprecationWarning

    General information

    • SDK/Library version: 4.9.0 (I also checked the latest code and it's still an issue)
    • Environment: doesn't matter, I think
    • Language, language version, and OS: Python 3.8

    Issue description

    According to https://docs.python.org/3/library/re.html, some of the regex strings might lead to syntax errors in future python versions:

    Regular expressions use the backslash character ('') to indicate special forms or to allow special characters to be used without invoking their special meaning. This collides with Python’s usage of the same character for the same purpose in string literals; for example, to match a literal backslash, one might have to write '\\' as the pattern string, because the regular expression must be \, and each backslash must be expressed as \ inside a regular Python string literal. Also, please note that any invalid escape sequences in Python’s usage of the backslash in string literals now generate a DeprecationWarning and in the future this will become a SyntaxError. This behaviour will happen even if it is a valid escape sequence for a regular expression.

    For example:

    virtualenv/lib/python3.8/site-packages/braintree/util/parser.py:13: DeprecationWarning: invalid escape sequence \s
    self.doc = minidom.parseString("><".join(re.split(">\s+<", xml)).strip())
    

    I think the solution is just to convert all regex strings to the raw r"..." format. But I'm not sure on backwards compatibility on that...

    next-major-version triaged 
    opened by zormit 3
  • Remove universal wheel, python 2 is unsupported

    Remove universal wheel, python 2 is unsupported

    Issue description

    This library doesn't seem to support python 2 but is still producing a universal wheel, setup.cfg can just be removed since that is the only entry.

    https://github.com/braintree/braintree_python/blob/9b58e54eee72a7682bf341e4c9a8a404199e7c3c/setup.cfg

    triaged 
    opened by gopackgo90 2
  • Print transactions in JSON format

    Print transactions in JSON format

    We are writing a connector to write JSON files of transactions that we search in the past day. Version 3.57.1

    import braintree
    from braintree import Environment, BraintreeGateway, Configuration, TransactionSearch
    
    gateway = braintree.BraintreeGateway(braintree.Configuration(environment=braintree.Environment.Sandbox,merchant_id="XXXXXX",public_key="XXXXX",private_key="XXXXXX"))
    results=gateway.transaction.search(TransactionSearch.created_at.between("2021-05-05T09:03:00.000Z", "2021-05-05T10:03:00Z"))
    
    for i in results.items:
        print(i)
    

    Returns :

    <Transaction {id: '9r6g66mr', additional_processor_response: None, amount: Decimal('1.00'), authorization_adjustments: [], authorization_expires_at: datetime.datetime(2021, 5, 12, 9, 14, 34), avs_error_response_code: None, avs_postal_code_response_code: 'M', avs_street_address_response_code: 'I', channel: None, created_at: datetime.datetime(2021, 5, 5, 9, 14, 33), credit_card_details: <CreditCard {token: '3qddmkg', bin: '401288', last_4: '1881', card_type: 'Visa', expiration_month: '12', expiration_year: '2022', customer_location: 'US', cardholder_name: None, image_url: 'https://assets.braintreegateway.com/payment_method_logo/visa.png?environment=sandbox', prepaid: 'No', healthcare: 'Unknown', debit: 'Unknown', durbin_regulated: 'Unknown', commercial: 'Unknown', payroll: 'Unknown', issuing_bank: 'Unknown', country_of_issuance: 'Unknown', product_id: 'Unknown', global_id: 'cGF5bWVudG1ldGhvZF9jY18zcWRkbWtn', account_type: None, unique_number_identifier: 'f2425aa6f4215f1be772e5144f480c70', venmo_sdk: False} at 4482418672>, currency_iso_code: 'AUD', cvv_response_code: 'M', discount_amount: None, disputes: [], escrow_status: None, gateway_rejection_reason: None, master_merchant_account_id: None, merchant_account_id: 'belongmobileverificationAUD', network_response_code: 'XX', network_response_text: 'sample network response text', network_transaction_id: '020210505091434', order_id: None, payment_instrument_type: 'credit_card', plan_id: None, processor_authorization_code: 'W95P6L', processor_response_code: '1000', processor_response_text: 'Approved', processor_settlement_response_code: '', processor_settlement_response_text: '', purchase_order_number: None, recurring: False, refund_id: None, refunded_transaction_id: None, service_fee_amount: None, settlement_batch_id: None, shipping_amount: None, ships_from_postal_code: None, status: 'authorization_expired', status_history: [<StatusEvent {timestamp: datetime.datetime(2021, 5, 5, 9, 14, 34), status: 'authorized', amount: Decimal('1.00'), user: 'System-User-Sandbox', transaction_source: 'api'} at 4482418896>, <StatusEvent {timestamp: datetime.datetime(2021, 5, 12, 9, 47, 31), status: 'authorization_expired', amount: Decimal('1.00'), transaction_source: 'recurring'} at 4482418952>], sub_merchant_account_id: None, subscription_id: None, tax_amount: None, tax_exempt: False, type: 'sale', updated_at: datetime.datetime(2021, 5, 12, 9, 47, 31), voice_referral_number: None} at 4482418560>
    

    Is there a way to format it as JSON? I tried emulating the __repr__ method but it is still printing bjects like StatuEvent as <StatusEvent ..... at 1214132321>

    Here is what I tried:

    detail_list = i._setattrs
    details = ", ".join("\"%s\": %r" % (attr, getattr(i, attr)) for attr in detail_list if (hasattr(i, attr) and getattr(i, attr) is not None))
    json_data="{%s}"%(details)
    

    Thank you

    triaged 
    opened by mailtobash 3
  • gateway.transaction.find raises a TypeError when initialised with client_id and secret

    gateway.transaction.find raises a TypeError when initialised with client_id and secret

    General information

    • SDK/Library version: 4.6.0
    • Environment: Sandbox
    • Language, language version, and OS: Python 3.9.1 on a python:alpine docker container

    Issue description

    When I try and gateway.transaction.find a transaction using a gateway that was initialised with a client_id and secret, I receive a TypeError "can only concatenate str (not "NoneType") to str".

    Had a look, this happens because the BraintreeGateway.merchant_id is not set if you initialise it using a client_id and secret.

    Steps to reproduce:

    # gateway using my credentials
    gateway = braintree.BraintreeGateway(
        client_id=os.getenv('BT_CID'), 
        client_secret=os.getenv('BT_SECRET')
    )
    
    result = gateway.transaction.sale({
        "amount": '1.00',
        "payment_method_nonce": 'fake-valid-nonce',
        "options": {
            "submit_for_settlement": True
        }
    })
    
    transaction = result.transaction
    
    result = gateway.transaction.find(transaction.id)
    

    Traceback:

    Traceback (most recent call last):
      File "/test.py", line 89, in <module>
        result = my_gateway.transaction.sale({
      File "/usr/local/lib/python3.9/site-packages/braintree/transaction_gateway.py", line 84, in sale
        return self.create(params)
      File "/usr/local/lib/python3.9/site-packages/braintree/transaction_gateway.py", line 31, in create
        return self._post("/transactions", {"transaction": params})
      File "/usr/local/lib/python3.9/site-packages/braintree/transaction_gateway.py", line 168, in _post
        response = self.config.http().post(self.config.base_merchant_path() + url, params)
      File "/usr/local/lib/python3.9/site-packages/braintree/configuration.py", line 113, in base_merchant_path
        return "/merchants/" + self.merchant_id
    TypeError: can only concatenate str (not "NoneType") to str
    
    triaged 
    opened by jvn145 2
  • Test disbursement objects throw AttributeError for is_credit() and is_debit()

    Test disbursement objects throw AttributeError for is_credit() and is_debit()

    General information

    • SDK/Library version: 3.59.0
    • Environment: Local testing
    • Language, language version, and OS: Python 3.8.6 (python:3.8-buster Docker image)

    Issue description

    Test disbursement webhook notifications are missing the disbursement_type attribute, causing the is_credit() and is_debit() methods to throw AttributeErrors:

    >>> webhook_notification = self.gateway.webhook_testing.sample_notification(
    >>>   braintree.WebhookNotification.Kind.Disbursement,
    >>>   "test_disbursement_id",
    >>> )
    >>> webhook_notification.disbursement.is_credit()                                                                     
    Traceback (most recent call last):                                                               
      File "<pudb command line>", line 1, in <module>                                                
      File "/usr/local/lib/python3.8/site-packages/braintree/disbursement.py", line 27, in is_credit 
        return self.disbursement_type == Disbursement.Type.Credit                                    
    AttributeError: 'Disbursement' object has no attribute 'disbursement_type'                       
    
    triaged 
    opened by bcdickinson 3
alpaca-trade-api-python is a python library for the Alpaca Commission Free Trading API.

alpaca-trade-api-python is a python library for the Alpaca Commission Free Trading API. It allows rapid trading algo development easily, with support for both REST and streaming data interfaces

Alpaca 1.5k Jan 9, 2023
🐍 The official Python client library for Google's discovery based APIs.

Google API Client This is the Python client library for Google's discovery based APIs. To get started, please see the docs folder. These client librar

Google APIs 6.2k Jan 8, 2023
Python bindings for ArrayFire: A general purpose GPU library.

ArrayFire Python Bindings ArrayFire is a high performance library for parallel computing with an easy-to-use API. It enables users to write scientific

ArrayFire 402 Dec 20, 2022
Balanced API library in python.

Balanced Online Marketplace Payments v1.x requires Balanced API 1.1. Use v0.x for Balanced API 1.0. Installation pip install balanced Usage View Bala

Balanced 70 Oct 4, 2022
python library to the bitly api

bitly API python library Installation pip install bitly_api Run tests Your username is the lowercase name shown when you login to bitly, your access

Bitly 245 Aug 14, 2022
A Python library for the Buildkite API

PyBuildkite A Python library and client for the Buildkite API. Usage To get the package, execute: pip install pybuildkite Then set up an instance of

Peter Yasi 29 Nov 30, 2022
Unofficial Coinbase Python Library

Unofficial Coinbase Python Library Python Library for the Coinbase API for use with three legged oAuth2 and classic API key usage Version 0.3.0 Requir

George Sibble 104 Dec 1, 2022
A Python library for the Discourse API

pydiscourse A Python library for working with Discourse. This is a fork of the original Tindie version. It was forked to include fixes, additional fun

Ben Lopatin 72 Oct 14, 2022
A Python library for the Docker Engine API

Docker SDK for Python A Python library for the Docker Engine API. It lets you do anything the docker command does, but from within Python apps – run c

Docker 6.1k Jan 3, 2023
A Python Library to interface with Flickr REST API, OAuth & JSON Responses

Python-Flickr Python-Flickr is A Python library to interface with Flickr REST API & OAuth Features Photo Uploading Retrieve user information Common Fl

Mike Helmick 40 Sep 25, 2021
Unofficial GoPro API Library for Python - connect to GoPro via WiFi.

GoPro API for Python Unofficial GoPro API Library for Python - connect to GoPro cameras via WiFi. Compatibility: HERO3 HERO3+ HERO4 (including HERO Se

Konrad Iturbe 1.3k Jan 1, 2023
A Python library wrapping the iFixit (Dozuki) API.

A Python library wrapping the iFixit API. Status Working, but incomplete. Fully tested and documented. Hacking I highly recommend using virtualenv: [$

James Pearson Hughes 13 May 24, 2021
:snake: A simple library to fetch data from the iTunes Store API made for Python >= 3.5

itunespy itunespy is a simple library to fetch data from the iTunes Store API made for Python 3.5 and beyond. Important: Since version 1.6 itunespy no

Fran González 56 Dec 22, 2022
Python JIRA Library is the easiest way to automate JIRA. Support for py27 was dropped on 2019-10-14, do not raise bugs related to it.

Jira Python Library This library eases the use of the Jira REST API from Python and it has been used in production for years. As this is an open-sourc

PyContribs 1.7k Jan 6, 2023
The official Python client library for the Kite Connect trading APIs

The Kite Connect API Python client - v3 The official Python client for communicating with the Kite Connect API. Kite Connect is a set of REST-like API

Zerodha Technology 756 Jan 6, 2023
A Python Library to interface with LinkedIn API, OAuth and JSON responses

#Overview Here's another library based on the LinkedIn API, OAuth and JSON responses. Hope this documentation explains everything you need to get star

Mike Helmick 69 Dec 11, 2022
A Python library for PagerDuty.

Pygerduty Python Library for PagerDuty's REST API and Events API. This library was originally written to support v1 and is currently being updated to

Dropbox 164 Dec 20, 2022
PyMed is a Python library that provides access to PubMed.

IMPORTANT NOTE: I don't have time to maintain this library (as some of you might have noticed). The PubMed API is a little chaotic, without a clear do

Gijs Wobben 143 Dec 21, 2022
The Official Twilio SendGrid Led, Community Driven Python API Library

The default branch name for this repository has been changed to main as of 07/27/2020. This library allows you to quickly and easily use the SendGrid

Twilio SendGrid 1.4k Jan 7, 2023