Skip to content

Commit ad8afa4

Browse files
author
floguy
committed
Added docstrings and inline documentation, and some standard open source files.
git-svn-id: https://django-oembed.googlecode.com/svn/trunk@9 4c08321d-174e-0410-8f1d-477679e35061
1 parent 94f92ac commit ad8afa4

File tree

6 files changed

+98
-22
lines changed

6 files changed

+98
-22
lines changed

CONTRIBUTORS.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Eric Florenzano <[email protected]>

INSTALL.txt

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
Thanks for downloading django-oembed!
2+
3+
To install it, first use subversion to check out the source code:
4+
5+
svn checkout http://django-oembed.googlecode.com/svn/trunk/ django-oembed
6+
7+
Now, link the included ``oembed`` directory to your pythonpath. On Debian
8+
variants, it would look something like this.
9+
10+
sudo ln -s `pwd`/django-oembed/oembed /usr/lib/python2.5/site-packages/
11+
12+
To use it with a Django installation, first place 'oembed' in the INSTALLED_APPS
13+
tuple of your settings.py file like so:
14+
15+
INSTALLED_APPS = (
16+
# ...
17+
'oembed',
18+
)
19+
20+
Then syncdb, and here is sample usage in a template.
21+
22+
{% load oembed_tags %}
23+
{% oembed %}
24+
{% for link in links %}{{ link.href }}{% endfor %}
25+
{% endoembed %}
26+
27+
In the previous example, any link.href would be replaced with an OEmbed-fetched
28+
embed.
29+
30+
The templatetag takes one optional second argument, which you can figure out by
31+
looking at this usage:
32+
33+
{% oembed 320x240 %}
34+
35+
Note that this application requires Python 2.3 or later, and Django later than
36+
0.96. You can obtain Python from http://www.python.org/ and Django from
37+
http://www.djangoproject.com/.

README.txt

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=======================
2+
django-oembed
3+
=======================
4+
5+
This is a collection of tools for Django to allow for replacing links in text
6+
with OEmbed. This application also provides utilities to make this process not
7+
prohibitively expensive CPU-wise.
8+
9+
For installation instructions, read INSTALL.txt.
10+
11+
Visit the google code page at http://django-oembed.googlecode.com/

oembed/core.py

+39-18
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,28 @@
1111
from django.utils import simplejson
1212
from django.conf import settings
1313
from django.utils.safestring import mark_safe
14-
#from django.utils.html import conditional_escape
1514
from oembed.models import ProviderRule, StoredOEmbed
1615
from django.template.loader import render_to_string
1716

18-
conditional_escape = lambda x: x
19-
2017
END_OVERRIDES = (')', ',', '.', '>', ']', ';')
2118
MAX_WIDTH = getattr(settings, "OEMBED_MAX_WIDTH", 320)
2219
MAX_HEIGHT = getattr(settings, "OEMBED_MAX_HEIGHT", 240)
2320
FORMAT = getattr(settings, "OEMBED_FORMAT", "json")
2421

25-
def fetch(url, user_agent="django-oembed"):
26-
request = urllib2.Request(url)
27-
request.add_header('User-Agent', user_agent)
28-
request.add_header('Accept-Encoding', 'gzip')
29-
opener = urllib2.build_opener()
30-
f = opener.open(request)
31-
result = f.read()
32-
if f.headers.get('content-encoding', '') == 'gzip':
33-
result = gzip.GzipFile(fileobj=StringIO(result)).read()
34-
f.close()
35-
return result
22+
def fetch(url, user_agent="django-oembed/0.1"):
23+
"""
24+
Fetches from a URL, respecting GZip encoding, etc.
25+
"""
26+
request = urllib2.Request(url)
27+
request.add_header('User-Agent', user_agent)
28+
request.add_header('Accept-Encoding', 'gzip')
29+
opener = urllib2.build_opener()
30+
f = opener.open(request)
31+
result = f.read()
32+
if f.headers.get('content-encoding', '') == 'gzip':
33+
result = gzip.GzipFile(fileobj=StringIO(result)).read()
34+
f.close()
35+
return result
3636

3737
def re_parts(regex_list, text):
3838
"""
@@ -83,6 +83,17 @@ def match_compare(x, y):
8383
yield (-1, last_bit)
8484

8585
def replace(text, max_width=MAX_WIDTH, max_height=MAX_HEIGHT):
86+
"""
87+
Scans a block of text, replacing anything matched by a ``ProviderRule``
88+
pattern with an OEmbed html snippet, if possible.
89+
90+
Templates should be stored at oembed/{format}.html, so for example:
91+
92+
oembed/video.html
93+
94+
These templates are passed a context variable, ``response``, which is a
95+
dictionary representation of the response.
96+
"""
8697
rules = list(ProviderRule.objects.all())
8798
patterns = [re.compile(r.regex) for r in rules] # Compiled patterns from the rules
8899
parts = [] # The parts that we will assemble into the final return value.
@@ -91,10 +102,10 @@ def replace(text, max_width=MAX_WIDTH, max_height=MAX_HEIGHT):
91102
urls = set() # A set of URLs to try to lookup from the database.
92103
stored = {} # A mapping of URLs to StoredOEmbed objects.
93104
index = 0
94-
# First let's pass through the text, populating our data structures.
105+
# First we pass through the text, populating our data structures.
95106
for i, part in re_parts(patterns, text):
96107
if i == -1:
97-
parts.append(conditional_escape(part))
108+
parts.append(part)
98109
index += 1
99110
else:
100111
to_append = ""
@@ -110,19 +121,28 @@ def replace(text, max_width=MAX_WIDTH, max_height=MAX_HEIGHT):
110121
if to_append:
111122
parts.append(to_append)
112123
index += 1
124+
# Now we fetch a list of all stored patterns, and put it in a dictionary
125+
# mapping the URL to to the stored model instance.
113126
for stored_embed in StoredOEmbed.objects.filter(match__in=urls, max_width=max_width, max_height = max_height):
114127
stored[stored_embed.match] = stored_embed
128+
# Now we're going to do the actual replacement of URL to embed.
115129
for i, id_to_replace in enumerate(indices):
116130
rule = rules[indices_rules[i]]
117131
part = parts[id_to_replace]
118132
try:
133+
# Try to grab the stored model instance from our dictionary, and
134+
# use the stored HTML fragment as a replacement.
119135
parts[id_to_replace] = stored[part].html
120136
except KeyError:
121137
try:
138+
# Build the URL based on the properties defined in the OEmbed spec.
122139
url = u"%s?url=%s&maxwidth=%s&maxheight=%s&format=%s" % (
123140
rule.endpoint, part, max_width, max_height, FORMAT
124141
)
142+
# Fetch the link and parse the JSON.
125143
resp = simplejson.loads(fetch(url))
144+
# Depending on the embed type, grab the associated template and
145+
# pass it the parsed JSON response as context.
126146
replacement = render_to_string('oembed/%s.html' % resp['type'], {'response': resp})
127147
if replacement:
128148
stored_embed = StoredOEmbed.objects.create(
@@ -136,7 +156,8 @@ def replace(text, max_width=MAX_WIDTH, max_height=MAX_HEIGHT):
136156
else:
137157
raise ValueError
138158
except ValueError:
139-
parts[id_to_replace] = conditional_escape(part)
159+
parts[id_to_replace] = part
140160
except KeyError:
141-
parts[id_to_replace] = conditional_escape(part)
161+
parts[id_to_replace] = part
162+
# Combine the list into one string and return it.
142163
return mark_safe(u''.join(parts))

oembed/models.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,4 @@ class StoredOEmbed(models.Model):
3030
date_added = models.DateTimeField(default=datetime.datetime.now)
3131

3232
def __unicode__(self):
33-
return self.match
34-
35-
class Admin:
36-
pass
33+
return self.match

oembed/templatetags/oembed_tags.py

+9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@
44
register = template.Library()
55

66
def oembed(parser, token):
7+
"""
8+
A node which parses everything between its two nodes, and replaces any links
9+
with OEmbed-provided objects, if possible.
10+
11+
Supports one optional argument, which is the maximum width and height,
12+
specified like so:
13+
14+
{% oembed 640x480 %}http://www.viddler.com/explore/SYSTM/videos/49/{% endoembed %}
15+
"""
716
args = token.contents.split()
817
if len(args) > 2:
918
raise template.TemplateSyntaxError("Oembed tag takes only one (option" \

0 commit comments

Comments
 (0)