aboutsummaryrefslogtreecommitdiffstats
path: root/examples/pygments_api/views.py
blob: e22705d96899858ca3ae304977424b687750e968 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
from django.conf import settings

from djangorestframework.resource import Resource
from djangorestframework.response import Response, status
from djangorestframework.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 uuid
import operator

# We need somewhere to store the code that we highlight
HIGHLIGHTED_CODE_DIR = os.path.join(settings.MEDIA_ROOT, 'pygments')
MAX_FILES = 20

def remove_oldest_files(dir, max_files):
    """Remove the oldest files in a directory 'dir', leaving at most 'max_files' remaining.
    We use this to limit the number of resources in the sandbox."""
    filepaths = [os.path.join(dir, file) for file in os.listdir(dir)]
    ctime_sorted_paths = [item[0] for item in sorted([(path, os.path.getctime(path)) for path in filepaths],
                                                     key=operator.itemgetter(1), reverse=True)]
    [os.remove(path) for path in ctime_sorted_paths[max_files:]]


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 highlighted code snippets, and to list all the existing code snippets."""
    form = PygmentsForm
    allowed_methods = anon_allowed_methods = ('GET', 'POST',)

    def get(self, request, auth):
        """Return a list of all currently existing snippets."""
        unique_ids = sorted(os.listdir(HIGHLIGHTED_CODE_DIR))
        return [self.reverse(PygmentsInstance, unique_id) for unique_id in unique_ids]

    def post(self, request, auth, content):
        """Create a new highlighed snippet and return it's location.
        For the purposes of the sandbox example, also ensure we delete the oldest snippets if we have > MAX_FILES."""
        unique_id = str(uuid.uuid1())
        pathname = os.path.join(HIGHLIGHTED_CODE_DIR, unique_id)

        lexer = get_lexer_by_name(content['lexer'])
        linenos = 'table' if content['linenos'] else False
        options = {'title': content['title']} if content['title'] else {}
        formatter = HtmlFormatter(style=content['style'], linenos=linenos, full=True, **options)
        
        with open(pathname, 'w') as outfile:
            highlight(content['code'], lexer, formatter, outfile)
        
        remove_oldest_files(HIGHLIGHTED_CODE_DIR, MAX_FILES)

        return Response(status.HTTP_201_CREATED, 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 the emitters.DocumentingHTMLEmitter class."""
    allowed_methods = anon_allowed_methods = ('GET',)
    emitters = (HTMLEmitter,)

    def get(self, request, auth, unique_id):
        """Return the highlighted snippet."""
        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()

    def delete(self, request, auth, unique_id):
        """Delete the highlighted snippet."""
        pathname = os.path.join(HIGHLIGHTED_CODE_DIR, unique_id)
        if not os.path.exists(pathname):
            return Resource(status.HTTP_404_NOT_FOUND)
        return os.remove(pathname)