Skip to content

Commit cfac62f

Browse files
committed
Merge pull request #13 from coagulant/py3k
Python 3 support
2 parents 3e1ce5e + 1df4227 commit cfac62f

File tree

7 files changed

+115
-97
lines changed

7 files changed

+115
-97
lines changed

.travis.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
language: python
2+
python:
3+
- 2.6
4+
- 2.7
5+
- 3.2
6+
- 3.3
7+
script: python embedly/tests.py
8+
install:
9+
- python setup.py -q install

embedly/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
from client import Embedly
1+
from __future__ import absolute_import
2+
from .client import Embedly
23

34
__version__ = '0.4.3'

embedly/client.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,22 @@
44
55
The embedly object that interacts with the service
66
"""
7+
from __future__ import absolute_import
78
import re
8-
import urllib
99
import httplib2
10-
10+
import json
1111
try:
12-
import json
12+
from urllib import quote, urlencode
1313
except ImportError:
14-
import simplejson as json
14+
# py3k
15+
from urllib.parse import quote, urlencode
16+
1517

16-
from models import Url
18+
from .models import Url
1719

1820
USER_AGENT = 'Mozilla/5.0 (compatible; embedly-python/0.3;)'
1921

22+
2023
class Embedly(object):
2124
"""
2225
Client
@@ -97,43 +100,43 @@ def _get(self, version, method, url_or_urls, **kwargs):
97100

98101
# Throw an error early for too many URLs
99102
if multi and len(url_or_urls) > 20:
100-
raise ValueError('Embedly accepts only 20 urls at a time. Url ' \
101-
'Count:%s' % len(url_or_urls))
103+
raise ValueError('Embedly accepts only 20 urls at a time. Url '
104+
'Count:%s' % len(url_or_urls))
102105

103106
query = ''
104107

105108
key = kwargs.get('key', self.key)
106109

107110
#make sure that a key was set on the client or passed in.
108111
if not key:
109-
raise ValueError('Requires a key. None given: %s' % (key))
112+
raise ValueError('Requires a key. None given: %s' % key)
110113

111114
kwargs['key'] = key
112115

113-
query += urllib.urlencode(kwargs)
116+
query += urlencode(kwargs)
114117

115118
if multi:
116-
query += '&urls=%s&' % ','.join([urllib.quote(url) for url in url_or_urls])
119+
query += '&urls=%s&' % ','.join([quote(url) for url in url_or_urls])
117120
else:
118-
query += '&url=%s' % urllib.quote(url_or_urls)
121+
query += '&url=%s' % quote(url_or_urls)
119122

120123
url = 'http://api.embed.ly/%s/%s?%s' % (version, method, query)
121124

122125
http = httplib2.Http(timeout=self.timeout)
123126

124-
headers = {'User-Agent' : self.user_agent}
127+
headers = {'User-Agent': self.user_agent}
125128

126129
resp, content = http.request(url, headers=headers)
127130

128131
if resp['status'] == '200':
129-
data = json.loads(content)
132+
data = json.loads(content.decode('utf-8'))
130133

131134
if kwargs.get('raw', False):
132135
data['raw'] = content
133136
else:
134-
data = {'type' : 'error',
135-
'error' : True,
136-
'error_code' : int(resp['status'])}
137+
data = {'type': 'error',
138+
'error': True,
139+
'error_code': int(resp['status'])}
137140

138141
if multi:
139142
return map(lambda url, data: Url(data, method, url),

embedly/models.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
44
Creates a sudo model class that makes it easy to access attributes
55
"""
6+
from __future__ import unicode_literals
67
class AttrDict(object):
78
"""
89
UserDict is a pain in the ass. Let's just make our own.
@@ -30,11 +31,8 @@ def __getattr__(self, name):
3031
return object.__getattr__(self, name)
3132
try:
3233
return self.data[name]
33-
except KeyError, e:
34+
except KeyError as e:
3435
return None
35-
raise AttributeError(
36-
"%s instance has no attribute '%s'" % (self.__class__.__name__,
37-
name))
3836

3937
def __setattr__(self, name, value):
4038
if name in ['data', 'method']:
@@ -55,6 +53,7 @@ def items(self): return self.data.items()
5553
def dict(self):
5654
return self.data
5755

56+
5857
class Url(AttrDict):
5958

6059
def __init__(self, data=None, method=None, original_url=None):
@@ -68,7 +67,7 @@ def __str__(self):
6867
return self.__unicode__().encode("utf-8")
6968

7069
def __unicode__(self):
71-
r = u'<%s ' % self.method.title()
70+
r = '<%s ' % self.method.title()
7271

7372
if self.original_url:
7473
r += self.original_url

embedly/tests.py

Lines changed: 74 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,139 +1,138 @@
1-
2-
import os
1+
from __future__ import unicode_literals
32
import unittest
43

54
from embedly.client import Embedly
65
from embedly.models import Url
76

7+
88
class EmbedlyTestCase(unittest.TestCase):
99

1010
def __init__(self, *args, **kwargs):
11-
self.key = 'internal' # os.environ['EMBEDLY_API_KEY']
11+
self.key = 'internal'
1212

1313
if not self.key:
14-
raise ValueError('Set envirnomental varible EMBEDLY_API_KEY '+\
15-
'before running these tests like so: $ export '+\
14+
raise ValueError('Set envirnomental varible EMBEDLY_API_KEY ' +
15+
'before running these tests like so: $ export ' +
1616
'EMBEDLY_API_KEY=key')
1717

1818
super(EmbedlyTestCase, self).__init__(*args, **kwargs)
1919

2020
def test_model(self):
2121
data = {
22-
u'provider_url': u'http://www.google.com/',
23-
u'safe': True,
24-
u'description': u'Google',
25-
u'original_url': u'http://google.com/',
26-
u'url': u'http://www.google.com/',
27-
u'type': u'html',
28-
u'object': {},
29-
u'provider_display': u'www.google.com',
30-
u'author_name': None,
31-
u'favicon_url': u'http://www.google.com/favicon.ico',
32-
u'place': {},
33-
u'author_url': None,
34-
u'images': [
35-
{u'url': u'http://www.google.com/intl/en_ALL/images/srpr/logo1w.png',
36-
u'width': 275,
37-
u'height': 95}],
38-
u'title': u'Google',
39-
u'provider_name': u'Google',
40-
u'cache_age': 86400,
41-
u'embeds': []
22+
'provider_url': 'http://www.google.com/',
23+
'safe': True,
24+
'description': 'Google',
25+
'original_url': 'http://google.com/',
26+
'url': 'http://www.google.com/',
27+
'type': 'html',
28+
'object': {},
29+
'provider_display': 'www.google.com',
30+
'author_name': None,
31+
'favicon_url': 'http://www.google.com/favicon.ico',
32+
'place': {},
33+
'author_url': None,
34+
'images': [
35+
{'url': 'http://www.google.com/intl/en_ALL/images/srpr/logo1w.png',
36+
'width': 275,
37+
'height': 95}],
38+
'title': 'Google',
39+
'provider_name': 'Google',
40+
'cache_age': 86400,
41+
'embeds': []
4242
}
4343

4444
obj = Url(data, 'preview', 'http://google.com/')
4545

46-
self.assert_(len(obj) is 17)
47-
self.assert_(len(obj.values()) is 17)
48-
self.assert_(len(obj.keys()) is 17)
49-
self.assert_(len(obj.items()) is 17)
46+
self.assertTrue(len(obj) is 17)
47+
self.assertTrue(len(obj.values()) is 17)
48+
self.assertTrue(len(obj.keys()) is 17)
49+
self.assertTrue(len(obj.items()) is 17)
5050

51-
self.assert_('type' in obj.keys())
52-
self.assert_('html' in obj.values())
51+
self.assertTrue('type' in obj.keys())
52+
self.assertTrue('html' in obj.values())
5353

5454
#Get the object
55-
self.assert_(obj.type == 'html')
56-
self.assert_(obj['type'] == 'html')
57-
self.assert_(obj.get('type') == 'html')
55+
self.assertTrue(obj.type == 'html')
56+
self.assertTrue(obj['type'] == 'html')
57+
self.assertTrue(obj.get('type') == 'html')
5858

5959
#nope
60-
self.assert_(obj.nothing is None)
60+
self.assertTrue(obj.nothing is None)
6161

6262
obj.nothing = 'something'
63-
self.assert_(obj.nothing == 'something')
63+
self.assertTrue(obj.nothing == 'something')
6464

6565
obj['nothing'] = 'maybe'
66-
self.assert_(obj['nothing'] == 'maybe')
66+
self.assertTrue(obj['nothing'] == 'maybe')
6767

6868
del obj['nothing']
69-
self.assert_(obj.nothing is None)
69+
self.assertTrue(obj.nothing is None)
7070

7171
#Deep Get attrs
72-
self.assert_(obj.images[0].width is 275)
73-
self.assert_(obj.images[0].nothing is None)
74-
self.assert_(obj.object.type is None)
72+
self.assertTrue(obj.images[0].width is 275)
73+
self.assertTrue(obj.images[0].nothing is None)
74+
self.assertTrue(obj.object.type is None)
7575

7676
def test_provider(self):
7777
http = Embedly(self.key)
7878

7979
obj = http.oembed('http://www.scribd.com/doc/13994900/Easter')
80-
self.assert_(obj.provider_url == 'http://www.scribd.com/')
80+
self.assertTrue(obj.provider_url == 'http://www.scribd.com/')
8181

8282
obj = http.oembed('http://www.scribd.com/doc/28452730/Easter-Cards')
83-
self.assert_(obj.provider_url == 'http://www.scribd.com/')
83+
self.assertTrue(obj.provider_url == 'http://www.scribd.com/')
8484

8585
obj = http.oembed('http://www.youtube.com/watch?v=Zk7dDekYej0')
86-
self.assert_(obj.provider_url == 'http://www.youtube.com/')
86+
self.assertTrue(obj.provider_url == 'http://www.youtube.com/')
8787

8888
obj = http.oembed('http://yfrog.com/h22eu4j')
89-
self.assert_(obj.provider_url == 'http://yfrog.com')
89+
self.assertTrue(obj.provider_url == 'http://yfrog.com')
9090

9191
def test_providers(self):
9292
http = Embedly(self.key)
9393

94-
objs = http.oembed(['http://www.scribd.com/doc/13994900/Easter',
95-
'http://www.scribd.com/doc/28452730/Easter-Cards'])
96-
self.assert_(objs[0].provider_url == 'http://www.scribd.com/')
97-
self.assert_(objs[1].provider_url == 'http://www.scribd.com/')
94+
objs = list(http.oembed(['http://www.scribd.com/doc/13994900/Easter',
95+
'http://www.scribd.com/doc/28452730/Easter-Cards']))
96+
self.assertTrue(objs[0].provider_url == 'http://www.scribd.com/')
97+
self.assertTrue(objs[1].provider_url == 'http://www.scribd.com/')
9898

99-
objs = http.oembed(['http://www.youtube.com/watch?v=Zk7dDekYej0',
100-
'http://yfrog.com/h22eu4'])
101-
self.assert_(objs[0].provider_url == 'http://www.youtube.com/')
102-
self.assert_(objs[1].provider_url == 'http://yfrog.com')
99+
objs = list(http.oembed(['http://www.youtube.com/watch?v=Zk7dDekYej0',
100+
'http://yfrog.com/h22eu4']))
101+
self.assertTrue(objs[0].provider_url == 'http://www.youtube.com/')
102+
self.assertTrue(objs[1].provider_url == 'http://yfrog.com')
103103

104104
def test_error(self):
105105
http = Embedly(self.key)
106106

107107
obj = http.oembed('http://www.embedly.com/this/is/a/bad/url')
108-
self.assert_(obj.error is True, obj.dict)
108+
self.assertTrue(obj.error is True, obj.dict)
109109
obj = http.oembed('http://blog.embed.ly/lsbsdlfldsf/asdfkljlas/klajsdlfkasdf')
110-
self.assert_(obj.error is True, obj.dict)
110+
self.assertTrue(obj.error is True, obj.dict)
111111
obj = http.oembed('http://twitpic/nothing/to/see/here')
112-
self.assert_(obj.error is True, obj.dict)
112+
self.assertTrue(obj.error is True, obj.dict)
113113

114114
def test_multi_errors(self):
115115
http = Embedly(self.key)
116116

117-
objs = http.oembed(['http://www.embedly.com/this/is/a/bad/url',
118-
'http://blog.embed.ly/alsd/slsdlf/asdlfj'])
119-
self.assert_(objs[0].type == 'error', objs[0].dict)
120-
self.assert_(objs[1].type == 'error', objs[1].dict)
117+
objs = list(http.oembed(['http://www.embedly.com/this/is/a/bad/url',
118+
'http://blog.embed.ly/alsd/slsdlf/asdlfj']))
119+
self.assertTrue(objs[0].type == 'error', objs[0].dict)
120+
self.assertTrue(objs[1].type == 'error', objs[1].dict)
121121

122-
objs = http.oembed(['http://blog.embed.ly/lsbsdlfldsf/asdf/kl',
123-
'http://twitpic.com/nothing/to/see/here'])
124-
self.assert_(objs[0].type == 'error',objs[0].dict)
125-
self.assert_(objs[1].type == 'error',objs[1].dict)
122+
objs = list(http.oembed(['http://blog.embed.ly/lsbsdlfldsf/asdf/kl',
123+
'http://twitpic.com/nothing/to/see/here']))
124+
self.assertTrue(objs[0].type == 'error',objs[0].dict)
125+
self.assertTrue(objs[1].type == 'error',objs[1].dict)
126126

127-
objs = http.oembed(['http://blog.embed.ly/lsbsdlfldsf/asdf/kl',
128-
'http://yfrog.com/h22eu4j'])
129-
self.assert_(objs[0].type == 'error',objs[0].dict)
130-
self.assert_(objs[1].type == 'photo',objs[1].dict)
131-
132-
objs = http.oembed(['http://yfrog.com/h22eu4j',
133-
'http://www.scribd.com/asdf/asdf/asdfasdf'])
134-
self.assert_(objs[0].type == 'photo',objs[0].dict)
135-
self.assert_(objs[1].type == 'error',objs[1].dict)
127+
objs = list(http.oembed(['http://blog.embed.ly/lsbsdlfldsf/asdf/kl',
128+
'http://yfrog.com/h22eu4j']))
129+
self.assertTrue(objs[0].type == 'error',objs[0].dict)
130+
self.assertTrue(objs[1].type == 'photo',objs[1].dict)
136131

132+
objs = list(http.oembed(['http://yfrog.com/h22eu4j',
133+
'http://www.scribd.com/asdf/asdf/asdfasdf']))
134+
self.assertTrue(objs[0].type == 'photo',objs[0].dict)
135+
self.assertTrue(objs[1].type == 'error',objs[1].dict)
137136

138137
def test_too_many_urls(self):
139138
http = Embedly(self.key)
@@ -142,8 +141,9 @@ def test_too_many_urls(self):
142141
try:
143142
http.oembed(urls)
144143
self.fail('too many urls, should have thrown an error')
145-
except Exception, e:
144+
except Exception as e:
146145
self.assertTrue(type(e), ValueError)
147146

147+
148148
if __name__ == '__main__':
149149
unittest.main()

setup.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@
3838
'License :: OSI Approved :: BSD License',
3939
'Operating System :: OS Independent',
4040
'Programming Language :: Python',
41-
'Programming Language :: Python :: 2.5',
4241
'Programming Language :: Python :: 2.6',
4342
'Programming Language :: Python :: 2.7',
43+
'Programming Language :: Python :: 3.1',
44+
'Programming Language :: Python :: 3.2',
45+
'Programming Language :: Python :: 3.3',
4446
),
4547
**extra
4648
)

tox.ini

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[tox]
2+
envlist = py26,py27,py31,py32,py33
3+
[testenv]
4+
commands=python embedly/tests.py

0 commit comments

Comments
 (0)