Skip to content

Add config options to python client#5

Merged
oritheorca merged 9 commits intomasterfrom
grace/options
Oct 10, 2016
Merged

Add config options to python client#5
oritheorca merged 9 commits intomasterfrom
grace/options

Conversation

@oritheorca
Copy link
Copy Markdown
Contributor

@oritheorca oritheorca commented Sep 27, 2016

Description

Add hostname, secure, port, timeout options

Test Plan

  • Updated unit tests to include configs
  • Tested against api.usebutton, staging, SimpleHTTPServer

Copy link
Copy Markdown
Contributor

@griffinmyers griffinmyers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks fantastic, @gckwan! I've requested a few cosmetic changes and the move to urlparse... after which I think we'll be ready to ship!

Because the API is backwards compatible, we'll also want to bump the package minor version and add a note to the CHANGELOG

Comment thread README.rst

.. code:: python

client = Client("sk-XXX", {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you include from pybutton import Client? I'm trying to keep all code snippets atomically copy+pasteable

Comment thread README.rst Outdated
'hostname': 'api.testsite.com',
'port': 80,
'secure': False,
'timeout': 5
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe 'timeout': 5 # seconds just to make sure people copy+pasting know the units... It's fairly common that timeouts are expressed in ms.

Comment thread pybutton/client.py Outdated
https://app.usebutton.com/settings/organization.

config (dict): Configuration options for the client. Options include:
timeout: The time in ms for network requests to abort. Defaults to None.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: match ordering of README

Comment thread pybutton/client.py Outdated
'''

def __init__(self, api_key):
def __init__(self, api_key, config={}):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Python function (and bound method) definitions hold the memory for any default parameters. This means if you somehow mutate a default parameter argument (and believe me it happens) you'll be mutating the default for all following invocations. The "pythonic" move here is to default to None:

def __init__(self, api_key, config=None):

    if config is None:
        config = {}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weird! good to know, thanks.

Comment thread pybutton/client.py Outdated

self.orders = Orders(api_key, config)

def _config_with_defaults(self, config):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this method doesn't actually need to be bound to self, we can just have this as a function in the file.

Comment thread pybutton/resources/resource.py Outdated

def _request_url(self, path):
protocol = 'https://' if self.config['secure'] else 'http://'
return '{0}{1}:{2}{3}'.format(protocol, self.config['hostname'], self.config['port'], path)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think at this point it makes sense to get some help from the python stdlib:

import urlparse

# 'http://api.usebutton.com/12/12'
urlparse.urlunsplit(('http', 'api.usebutton.com', '/12/12', '', ''))

# also 'http://api.usebutton.com/12/12'
urlparse.urlunsplit(('http', 'api.usebutton.com', '12/12', '', ''))

def __init__(self, api_key):
def __init__(self, api_key, config):
self.api_key = api_key
self.config = config
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

even though you're going to end up repeating it a lot, I think a docstring here explaining config makes sense (especially given all the keys are required at this point)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally. Added config to the docstring above.

Comment thread README.rst Outdated
# {'status': open, 'btn_ref': None, 'line_items': [], ...}

Configuration
---------
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: extra -'s

@oritheorca
Copy link
Copy Markdown
Contributor Author

@griffinmyers Ping! No rush, but ready for another look whenever you have free time.

@griffinmyers
Copy link
Copy Markdown
Contributor

👋 @gckwan cool! will take a look today!

Copy link
Copy Markdown
Contributor

@griffinmyers griffinmyers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple style nits, specifically please run the linter flake8. I saw a couple violations. You can get your own copy with pip install flake8.

Upshot: I tested locally and everything looks great functionality wise!

Comment thread CHANGELOG.md Outdated
@@ -1,2 +1,5 @@
1.0.2 August 11, 2016
- Initial Release
1.1.0 September 28, 2016
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: changelog should be sorted reverse chronological order

Comment thread pybutton/client.py Outdated
'hostname': config.get('hostname', 'api.usebutton.com'),
'port': config.get('port', defaultPort)
}
def _config_with_defaults(config):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: because this isn't a private method to anything we can drop the _ prefix on the function name.

Comment thread pybutton/client.py Outdated
'secure': secure,
'timeout': config.get('timeout'),
'hostname': config.get('hostname', 'api.usebutton.com'),
'port': config.get('port', defaultPort)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: as weird as it may seem, the python community seems to prefer trailing commas for multi-line dict/list elements. config.get('port', defaultPort),

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually like trailing commas, myself! No need to add/remove commas when reordering values/adding new lines.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The airbnb styleguide is pro-trailing commas too: https://github.com/airbnb/javascript#commas--dangling

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still need to add trailing commas! I've seen some in README / tests we should make sure get them as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Derp, got too focused on the flake8 output. Adding them now.

Comment thread pybutton/resources/resource.py Outdated
protocol = 'https://' if self.config['secure'] else 'http://'
return '{0}{1}:{2}{3}'.format(protocol, self.config['hostname'], self.config['port'], path)
protocol = 'https' if self.config['secure'] else 'http'
return urlparse.urlunsplit((protocol, '{0}:{1}'.format(self.config['hostname'], self.config['port']), path, '', ''))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I try go give best effort to keeping under 80 columns. This could easily be split up with 1 argument per line or maybe by allocating the hostname/port string ahead of the #urlunsplit call

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix!

@oritheorca
Copy link
Copy Markdown
Contributor Author

flake8 should pass now :)

Comment thread pybutton/request.py Outdated
raise ButtonClientError('Invalid response: {0}'.format(response))

__all__ = [Request, urlopen, HTTPError, request]
def request_url(secure, hostname, port, path):
Copy link
Copy Markdown
Contributor

@griffinmyers griffinmyers Oct 4, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because this is the exact same implementation as the one on line 117, we can simply import each urlunsplit in the if/else and the define request_url and __all__ at the bottom of the file, once. Also, would you mind adding a Args/Returns to the docstring on this because it's used external to this file?

Copy link
Copy Markdown
Contributor

@griffinmyers griffinmyers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 LGTM!

@griffinmyers
Copy link
Copy Markdown
Contributor

Looks awesome! When you merge, please select the Squash and merge option. Then we can publish!

@oritheorca oritheorca merged commit f86c72a into master Oct 10, 2016
@griffinmyers griffinmyers deleted the grace/options branch January 5, 2017 23:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants