diff options
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/pygments_api/__init__.py | 0 | ||||
| -rw-r--r-- | examples/pygments_api/forms.py | 71 | ||||
| -rw-r--r-- | examples/pygments_api/urls.py | 6 | ||||
| -rw-r--r-- | examples/pygments_api/views.py | 64 | ||||
| -rw-r--r-- | examples/settings.py | 3 | ||||
| -rw-r--r-- | examples/urls.py | 6 | 
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)),  ) | 
