aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/pygments_api/__init__.py0
-rw-r--r--examples/pygments_api/forms.py71
-rw-r--r--examples/pygments_api/urls.py6
-rw-r--r--examples/pygments_api/views.py64
-rw-r--r--examples/settings.py3
-rw-r--r--examples/urls.py6
6 files changed, 149 insertions, 1 deletions
diff --git a/examples/pygments_api/__init__.py b/examples/pygments_api/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/examples/pygments_api/__init__.py
diff --git a/examples/pygments_api/forms.py b/examples/pygments_api/forms.py
new file mode 100644
index 00000000..66446c5b
--- /dev/null
+++ b/examples/pygments_api/forms.py
@@ -0,0 +1,71 @@
+from django import forms
+
+from pygments.lexers import get_all_lexers
+from pygments.styles import get_all_styles
+
+import httplib2 as httplib
+
+
+LEXER_CHOICES = sorted([(item[1][0], item[0]) for item in get_all_lexers()])
+STYLE_CHOICES = sorted((item, item) for item in list(get_all_styles()))
+
+
+class PygmentsForm(forms.Form):
+ """A simple form with some of the most important pygments settings.
+ The code to be highlighted can be specified either in a text field, or by URL.
+ We do some additional form validation to ensure clients see helpful error responses."""
+
+ code_url = forms.URLField(required=False, label='Code URL',
+ help_text='eg. https://bitbucket.org/tomchristie/flywheel/raw/cc266285d879/flywheel/resource.py')
+ code_text = forms.CharField(widget=forms.Textarea, required=False, label='Code Text',
+ help_text='Either supply a URL for the code to be highlighted or copy and paste the code text here.')
+ title = forms.CharField(required=False, help_text='(Optional)')
+ linenos = forms.BooleanField(label='Show Line Numbers', required=False)
+ lexer = forms.ChoiceField(choices=LEXER_CHOICES, initial='python')
+ style = forms.ChoiceField(choices=STYLE_CHOICES, initial='friendly')
+
+
+ def clean_code_url(self):
+ """Custom field validation.
+ Ensure that code URLs really are valid, and return the content they point to in the cleaned_data,
+ rather than returning the URL itself."""
+ cleaned_data = self.cleaned_data
+ url = cleaned_data.get('code_url')
+ if not url:
+ return ''
+
+ try:
+ http = httplib.Http('.cache')
+ resp, content = http.request(url)
+ except:
+ raise forms.ValidationError('The URL supplied cannot be reached')
+
+ if int(resp.status/100) != 2:
+ raise forms.ValidationError('The URL supplied does not return successfully')
+ if not content:
+ raise forms.ValidationError('The URL supplied returns no content')
+
+ return content
+
+
+ def clean(self):
+ """Custom form validation.
+ Ensure that only one of code_url and code_text is set, and return the content of whichever is set in 'code'."""
+ cleaned_data = self.cleaned_data
+ code_url = cleaned_data.get('code_url')
+ code_text = cleaned_data.get('code_text')
+
+ if not code_url and not code_text:
+ raise forms.ValidationError('Either the URL or the code text must be supplied')
+ if code_url and code_text:
+ raise forms.ValidationError('You may not specify both the URL and the code text')
+
+ if code_url:
+ cleaned_data['code'] = code_url
+ del cleaned_data['code_url']
+ else:
+ cleaned_data['code'] = code_text
+ del cleaned_data['code_text']
+
+ return cleaned_data
+
diff --git a/examples/pygments_api/urls.py b/examples/pygments_api/urls.py
new file mode 100644
index 00000000..39bcf668
--- /dev/null
+++ b/examples/pygments_api/urls.py
@@ -0,0 +1,6 @@
+from django.conf.urls.defaults import patterns
+
+urlpatterns = patterns('pygments_api.views',
+ (r'^$', 'PygmentsRoot'),
+ (r'^([a-zA-Z0-9]+)/$', 'PygmentsInstance'),
+)
diff --git a/examples/pygments_api/views.py b/examples/pygments_api/views.py
new file mode 100644
index 00000000..01f1b4b6
--- /dev/null
+++ b/examples/pygments_api/views.py
@@ -0,0 +1,64 @@
+from django.conf import settings
+
+from flywheel.resource import Resource
+from flywheel.response import Response, status
+from flywheel.emitters import BaseEmitter
+
+from pygments.formatters import HtmlFormatter
+from pygments.lexers import get_lexer_by_name
+from pygments import highlight
+
+from forms import PygmentsForm
+
+import os
+import hashlib
+
+# We need somewhere to store the code that we highlight
+HIGHLIGHTED_CODE_DIR = os.path.join(settings.MEDIA_ROOT, 'pygments')
+
+
+class HTMLEmitter(BaseEmitter):
+ """Basic emitter which just returns the content without any further serialization."""
+ media_type = 'text/html'
+
+
+class PygmentsRoot(Resource):
+ """This example demonstrates a simple RESTful Web API aound the awesome pygments library.
+ This top level resource is used to create """
+ form = PygmentsForm
+ allowed_methods = anon_allowed_methods = ('POST',)
+
+ def post(self, request, auth, content):
+ # Generate a unique id by hashing the input
+ input_str = ''.join(['%s%s' % (key, content[key]) for key in sorted(content.keys())])
+ hash = hashlib.md5()
+ hash.update(input_str)
+ unique_id = hash.hexdigest()
+ pathname = os.path.join(HIGHLIGHTED_CODE_DIR, unique_id)
+
+ if not os.path.exists(pathname):
+ # We only need to generate the file if it doesn't already exist.
+ title = content['title'] if content['title'] else None
+ linenos = 'table' if content['linenos'] else False
+ lexer = get_lexer_by_name(content['lexer'])
+ formatter = HtmlFormatter(style=content['style'], linenos=linenos, full=True, title=title)
+
+ with open(pathname, 'w') as outfile:
+ highlight(content['code'], lexer, formatter, outfile)
+
+ return Response(status.HTTP_303_SEE_OTHER, headers={'Location': self.reverse(PygmentsInstance, unique_id)})
+
+
+class PygmentsInstance(Resource):
+ """Simply return the stored highlighted HTML file with the correct mime type.
+ This Resource only emits HTML and uses a standard HTML emitter rather than FlyWheel's DocumentingHTMLEmitter class."""
+ allowed_methods = anon_allowed_methods = ('GET',)
+ emitters = (HTMLEmitter,)
+
+ def get(self, request, auth, unique_id):
+ pathname = os.path.join(HIGHLIGHTED_CODE_DIR, unique_id)
+ if not os.path.exists(pathname):
+ return Resource(status.HTTP_404_NOT_FOUND)
+ return open(pathname, 'r').read()
+
+
diff --git a/examples/settings.py b/examples/settings.py
index d1635104..f85e75f1 100644
--- a/examples/settings.py
+++ b/examples/settings.py
@@ -92,5 +92,6 @@ INSTALLED_APPS = (
'django.contrib.admin',
'flywheel',
'blogpost',
- 'objectstore'
+ 'objectstore',
+ 'pygments_api'
)
diff --git a/examples/urls.py b/examples/urls.py
index ebf2c9a3..62001016 100644
--- a/examples/urls.py
+++ b/examples/urls.py
@@ -4,9 +4,15 @@ from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
+<<<<<<< local
+ (r'^blog-post-api/', include('blogpost.urls')),
+ (r'^object-store-api/', include('objectstore.urls')),
+ (r'^pygments-api/', include('pygments_api.urls')),
+=======
(r'pygments-example/', include('pygmentsapi.urls')),
(r'^blog-post-example/', include('blogpost.urls')),
(r'^object-store-example/', include('objectstore.urls')),
+>>>>>>> other
(r'^admin/doc/', include('django.contrib.admindocs.urls')),
(r'^admin/', include(admin.site.urls)),
)