Skip to content

Commit

Permalink
more setuptools packaging
Browse files Browse the repository at this point in the history
* move webutil to oauth_dropins.webutil. it's a bit presumptuous to put it at the top level when it's named so broadly.
* switch gdata-python-client from submodule to pip dependency. (i've submitted my two bug fix patches as google/gdata-python-client#27.)
* move appengine_config.py to oauth_dropins, except for vender/virtualenv setup
* update README
  • Loading branch information
snarfed committed Jun 15, 2015
1 parent d13f9f6 commit c936b72
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 133 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/build/
/dist/
/.eggs/
/*.egg-info
Expand Down
5 changes: 1 addition & 4 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
[submodule "gdata-python-client"]
path = gdata-python-client
url = [email protected]:snarfed/gdata-python-client.git
[submodule "webutil"]
path = webutil
path = oauth_dropins/webutil
url = [email protected]:snarfed/webutil.git
60 changes: 38 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,42 @@ Tumblr, Twitter, and WordPress.com.
This repo also provides an example demo app, deployed at
http://oauth-dropins.appspot.com/.

Some dependencies are included as git submodules; others are installed with
`pip` in a
Depends on the
[App Engine Python SDK](https://developers.google.com/appengine/downloads). All
other dependencies are handled by pip and enumerated in
[requirements.txt](https://github.com/snarfed/oauth-dropins/blob/master/requirements.txt).
We recommend that you install with pip in a
[`virtualenv`](http://docs.python-guide.org/en/latest/dev/virtualenvs/).
([App Engine details.](https://cloud.google.com/appengine/docs/python/tools/libraries27#vendoring))
To get set up:

```shell
git submodule init
git submodule update
virtualenv local
source local/bin/activate
pip install -r requirements.txt
```

Then add this line to the `appengine_config.py` file in your project's root
directory:

```py
from oauth_dropins.appengine_config import *
```
If you clone the repo directly or want to contribute, see
[Development](#development) for setup instructions.

This software is released into the public domain. See LICENSE for details.

Related work:

* [Python Social Auth](http://psa.matiasaguirre.net/)


Quick start
---

Here's a full example of using the Facebook drop-in.

1. Install oauth-dropins into a virtualenv somewhere your App Engine project's
directory, e.g. `local/`:

```shell
source local/bin/activate
pip install oauth-dropins
```

1. Add this to the `appengine_config.py` file in your project's root directory
([background](https://cloud.google.com/appengine/docs/python/tools/libraries27#vendoring)):

```py
from google.appengine.ext import vendor
vendor.add('local')
from oauth_dropins.appengine_config import *
```

1. Put your [Facebook application](https://developers.facebook.com/apps)'s ID
and secret in two plain text files in your app's root directory,
`facebook_app_id` and `facebook_app_secret`. (If you use git, you'll probably
Expand Down Expand Up @@ -211,7 +214,16 @@ least one of them, but not all.

Development
---
Run the unit tests with `python setup.py test`.
To get started:

```shell
git submodule init
git submodule update
virtualenv local
source local/bin/activate
pip install -r requirements.txt
python setup.py test
```

Most dependencies are clean, but we've made patches to some that we haven't
(yet) tried to push upstream. If we ever switch submodule repos for those
Expand All @@ -224,6 +236,10 @@ To convert README.md to README.rst:

`pandoc --from=markdown --to=rst --output=README.rst README.md`

Related work:

* [Python Social Auth](http://psa.matiasaguirre.net/)

TODO:

* Google+ and Blogger need some love:
Expand Down
96 changes: 3 additions & 93 deletions appengine_config.py
Original file line number Diff line number Diff line change
@@ -1,97 +1,7 @@
"""App Engine settings.
from oauth_dropins.appengine_config import *

Reads app keys and secrets into constants from these files:
disqus_client_id
disqus_client_secret
dropbox_app_key
dropbox_app_secret
facebook_app_id
facebook_app_secret
facebook_app_id_local
facebook_app_secret_local
flickr_app_key
flickr_app_secret
google_client_id
google_client_secret
instagram_client_id
instagram_client_secret
instagram_client_id_local
instagram_client_secret_local
twitter_app_key
twitter_app_secret
tumblr_app_key
tumblr_app_secret
wordpress_client_id
wordpress_client_secret
wordpress_client_id_local
wordpress_client_secret_local
"""

import os
import sys

# Load packages in lib/
# Load packages from virtualenv
# https://cloud.google.com/appengine/docs/python/tools/libraries27#vendoring
from google.appengine.ext import vendor
vendor.add('local')

from webutil.appengine_config import *

# default timeout. the G+ and Instagram APIs use httplib2, which honors this.
import socket
socket.setdefaulttimeout(HTTP_TIMEOUT)
# monkey-patch socket.getdefaulttimeout() because it often gets reset, e.g. by
# socket.setblocking() and maybe other operations.
# http://stackoverflow.com/a/8465202/186123
socket.getdefaulttimeout = lambda: HTTP_TIMEOUT

# Add submodule directories to sys.path so they can be imported.
#
# I used to use symlinks and munge sys.modules, but both of those ended up in
# duplicate instances of modules, which caused problems. Background in
# https://github.com/snarfed/bridgy/issues/31
for path in (
'gdata-python-client/src',
):
path = os.path.join(os.path.dirname(__file__), path)
if path not in sys.path:
sys.path.append(path)


def read(filename):
"""Returns the contents of filename, or None if it doesn't exist."""
if os.path.exists(filename):
with open(filename) as f:
return f.read().strip()

MOCKFACEBOOK = False

if DEBUG:
FACEBOOK_APP_ID = read('facebook_app_id_local')
FACEBOOK_APP_SECRET = read('facebook_app_secret_local')
INSTAGRAM_CLIENT_ID = read('instagram_client_id_local')
INSTAGRAM_CLIENT_SECRET = read('instagram_client_secret_local')
WORDPRESS_CLIENT_ID = read('wordpress.com_client_id_local')
WORDPRESS_CLIENT_SECRET = read('wordpress.com_client_secret_local')
DISQUS_CLIENT_ID = read('disqus_client_id_local')
DISQUS_CLIENT_SECRET = read('disqus_client_secret_local')
else:
FACEBOOK_APP_ID = read('facebook_app_id')
FACEBOOK_APP_SECRET = read('facebook_app_secret')
INSTAGRAM_CLIENT_ID = read('instagram_client_id')
INSTAGRAM_CLIENT_SECRET = read('instagram_client_secret')
WORDPRESS_CLIENT_ID = read('wordpress.com_client_id')
WORDPRESS_CLIENT_SECRET = read('wordpress.com_client_secret')
DISQUS_CLIENT_ID = read('disqus_client_id')
DISQUS_CLIENT_SECRET = read('disqus_client_secret')

DROPBOX_APP_KEY = read('dropbox_app_key')
DROPBOX_APP_SECRET = read('dropbox_app_secret')
FLICKR_APP_KEY = read('flickr_app_key')
FLICKR_APP_SECRET = read('flickr_app_secret')
GOOGLE_CLIENT_ID = read('google_client_id')
GOOGLE_CLIENT_SECRET = read('google_client_secret')
TUMBLR_APP_KEY = read('tumblr_app_key')
TUMBLR_APP_SECRET = read('tumblr_app_secret')
TWITTER_APP_KEY = read('twitter_app_key')
TWITTER_APP_SECRET = read('twitter_app_secret')
1 change: 0 additions & 1 deletion gdata-python-client
Submodule gdata-python-client deleted from fabb62
78 changes: 78 additions & 0 deletions oauth_dropins/appengine_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"""App Engine settings.
Reads app keys and secrets into constants from these files:
disqus_client_id
disqus_client_secret
dropbox_app_key
dropbox_app_secret
facebook_app_id
facebook_app_secret
facebook_app_id_local
facebook_app_secret_local
flickr_app_key
flickr_app_secret
google_client_id
google_client_secret
instagram_client_id
instagram_client_secret
instagram_client_id_local
instagram_client_secret_local
twitter_app_key
twitter_app_secret
tumblr_app_key
tumblr_app_secret
wordpress_client_id
wordpress_client_secret
wordpress_client_id_local
wordpress_client_secret_local
"""

import os

from webutil.appengine_config import *

# default timeout. the G+ and Instagram APIs use httplib2, which honors this.
import socket
socket.setdefaulttimeout(HTTP_TIMEOUT)
# monkey-patch socket.getdefaulttimeout() because it often gets reset, e.g. by
# socket.setblocking() and maybe other operations.
# http://stackoverflow.com/a/8465202/186123
socket.getdefaulttimeout = lambda: HTTP_TIMEOUT


def read(filename):
"""Returns the contents of filename, or None if it doesn't exist."""
if os.path.exists(filename):
with open(filename) as f:
return f.read().strip()

if DEBUG:
FACEBOOK_APP_ID = read('facebook_app_id_local')
FACEBOOK_APP_SECRET = read('facebook_app_secret_local')
INSTAGRAM_CLIENT_ID = read('instagram_client_id_local')
INSTAGRAM_CLIENT_SECRET = read('instagram_client_secret_local')
WORDPRESS_CLIENT_ID = read('wordpress.com_client_id_local')
WORDPRESS_CLIENT_SECRET = read('wordpress.com_client_secret_local')
DISQUS_CLIENT_ID = read('disqus_client_id_local')
DISQUS_CLIENT_SECRET = read('disqus_client_secret_local')
else:
FACEBOOK_APP_ID = read('facebook_app_id')
FACEBOOK_APP_SECRET = read('facebook_app_secret')
INSTAGRAM_CLIENT_ID = read('instagram_client_id')
INSTAGRAM_CLIENT_SECRET = read('instagram_client_secret')
WORDPRESS_CLIENT_ID = read('wordpress.com_client_id')
WORDPRESS_CLIENT_SECRET = read('wordpress.com_client_secret')
DISQUS_CLIENT_ID = read('disqus_client_id')
DISQUS_CLIENT_SECRET = read('disqus_client_secret')

DROPBOX_APP_KEY = read('dropbox_app_key')
DROPBOX_APP_SECRET = read('dropbox_app_secret')
FLICKR_APP_KEY = read('flickr_app_key')
FLICKR_APP_SECRET = read('flickr_app_secret')
GOOGLE_CLIENT_ID = read('google_client_id')
GOOGLE_CLIENT_SECRET = read('google_client_secret')
TUMBLR_APP_KEY = read('tumblr_app_key')
TUMBLR_APP_SECRET = read('tumblr_app_secret')
TWITTER_APP_KEY = read('twitter_app_key')
TWITTER_APP_SECRET = read('twitter_app_secret')
4 changes: 2 additions & 2 deletions oauth_dropins/test/test_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
from webob import exc

from oauth_dropins import handlers
from webutil import util
from webutil import testutil
from oauth_dropins.webutil import util
from oauth_dropins.webutil import testutil


class HandlersTest(testutil.HandlerTest):
Expand Down
15 changes: 4 additions & 11 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,15 @@
Based on https://github.com/pypa/sampleproject/blob/master/setup.py
"""
import unittest

from setuptools import setup


class TestLoader(unittest.TestLoader):
def loadTestsFromNames(self, names, _=None):
return self.discover(names[0])
from setuptools import setup, find_packages


setup(name='oauth-dropins',
version='1.0',
description='Drop-in App Engine OAuth client handlers for many popular sites.',
long_description=open('README.rst').read(),
url='https://github.com/snarfed/oauth-dropins',
packages=['oauth_dropins', 'webutil'],
packages=find_packages(),
author='Ryan Barrett',
author_email='[email protected]',
license='Public domain',
Expand All @@ -36,6 +29,7 @@ def loadTestsFromNames(self, names, _=None):
],
keywords='oauth appengine',
install_requires=[
'gdata',
'google-api-python-client',
'httplib2',
'oauthlib',
Expand All @@ -44,6 +38,5 @@ def loadTestsFromNames(self, names, _=None):
'requests-oauthlib',
'tweepy',
],
test_loader='setup:TestLoader',
test_suite='.',
test_suite='oauth_dropins',
)

4 comments on commit c936b72

@snarfed
Copy link
Owner Author

Choose a reason for hiding this comment

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

hey @kylewm, you've done more pypi packaging than me before (read: any :P). i think i have a decent rough draft in the current repo right now. mind skimming it and see what you think? tia!

@snarfed
Copy link
Owner Author

Choose a reason for hiding this comment

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

(btw, it currently needs snarfed/webutil#2 for the tests to run. not sure what the actually right fix is yet. meh.)

@kylewm
Copy link
Contributor

@kylewm kylewm commented on c936b72 Jun 16, 2015

Choose a reason for hiding this comment

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

Fun!

This looks pretty good. You may want to exclude test classes in the find_packages call (I think find_packages(exclude="test")).

Also when you read in README.rst, you can use this if you'd like

import codecs
def readme():
    with codecs.open(
            os.path.join(os.path.dirname(__file__), 'README.rst'),
            encoding='utf-8') as f:
        return f.read()

https://github.com/kylewm/brevity/blob/master/setup.py#L8

The codecs thing is necessary if the environment variable LANG=C and the readme file contains unicode. The path, I don't exactly remember why I needed to add it, something about virtualenvs I think.

@snarfed
Copy link
Owner Author

Choose a reason for hiding this comment

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

thanks for looking! both great ideas, i'll definitely add them.

Please sign in to comment.