2011-02-19 13:26:27 +03:00
|
|
|
from __future__ import with_statement # for python 2.5
|
2011-01-26 11:58:09 +03:00
|
|
|
from django.conf import settings
|
2011-02-19 13:26:27 +03:00
|
|
|
from django.core.urlresolvers import reverse
|
2011-01-26 11:58:09 +03:00
|
|
|
|
2011-01-30 21:30:39 +03:00
|
|
|
from djangorestframework.resource import Resource
|
2011-02-19 16:54:55 +03:00
|
|
|
from djangorestframework.response import Response
|
2011-01-30 21:30:39 +03:00
|
|
|
from djangorestframework.emitters import BaseEmitter
|
2011-02-19 16:54:55 +03:00
|
|
|
from djangorestframework import status
|
2011-01-26 11:58:09 +03:00
|
|
|
|
|
|
|
from pygments.formatters import HtmlFormatter
|
|
|
|
from pygments.lexers import get_lexer_by_name
|
|
|
|
from pygments import highlight
|
|
|
|
|
|
|
|
from forms import PygmentsForm
|
|
|
|
|
|
|
|
import os
|
2011-01-30 14:00:20 +03:00
|
|
|
import uuid
|
|
|
|
import operator
|
2011-01-26 11:58:09 +03:00
|
|
|
|
|
|
|
# We need somewhere to store the code that we highlight
|
|
|
|
HIGHLIGHTED_CODE_DIR = os.path.join(settings.MEDIA_ROOT, 'pygments')
|
2011-03-23 01:48:59 +03:00
|
|
|
MAX_FILES = 10
|
2011-01-30 14:00:20 +03:00
|
|
|
|
2011-03-09 12:39:45 +03:00
|
|
|
def list_dir_sorted_by_ctime(dir):
|
|
|
|
"""Return a list of files sorted by creation time"""
|
2011-03-23 01:48:59 +03:00
|
|
|
filepaths = [os.path.join(dir, file) for file in os.listdir(dir) if not file.startswith('.')]
|
2011-03-09 12:39:45 +03:00
|
|
|
return [item[0] for item in sorted([(path, os.path.getctime(path)) for path in filepaths],
|
2011-04-27 16:28:48 +04:00
|
|
|
key=operator.itemgetter(1), reverse=False)]
|
2011-01-30 14:00:20 +03:00
|
|
|
def remove_oldest_files(dir, max_files):
|
2011-01-30 19:51:06 +03:00
|
|
|
"""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."""
|
2011-03-09 12:39:45 +03:00
|
|
|
[os.remove(path) for path in list_dir_sorted_by_ctime(dir)[max_files:]]
|
2011-01-26 11:58:09 +03:00
|
|
|
|
|
|
|
|
|
|
|
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.
|
2011-01-30 14:00:20 +03:00
|
|
|
This top level resource is used to create highlighted code snippets, and to list all the existing code snippets."""
|
2011-01-26 11:58:09 +03:00
|
|
|
form = PygmentsForm
|
2011-01-30 14:00:20 +03:00
|
|
|
allowed_methods = anon_allowed_methods = ('GET', 'POST',)
|
|
|
|
|
|
|
|
def get(self, request, auth):
|
|
|
|
"""Return a list of all currently existing snippets."""
|
2011-03-09 12:39:45 +03:00
|
|
|
unique_ids = [os.path.split(f)[1] for f in list_dir_sorted_by_ctime(HIGHLIGHTED_CODE_DIR)]
|
2011-02-19 13:26:27 +03:00
|
|
|
return [reverse('pygments-instance', args=[unique_id]) for unique_id in unique_ids]
|
2011-01-26 11:58:09 +03:00
|
|
|
|
|
|
|
def post(self, request, auth, content):
|
2011-01-30 14:00:20 +03:00
|
|
|
"""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())
|
2011-01-26 11:58:09 +03:00
|
|
|
pathname = os.path.join(HIGHLIGHTED_CODE_DIR, unique_id)
|
|
|
|
|
2011-01-30 14:00:20 +03:00
|
|
|
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)
|
|
|
|
|
2011-02-19 13:26:27 +03:00
|
|
|
return Response(status.HTTP_201_CREATED, headers={'Location': reverse('pygments-instance', args=[unique_id])})
|
2011-01-26 11:58:09 +03:00
|
|
|
|
|
|
|
|
|
|
|
class PygmentsInstance(Resource):
|
|
|
|
"""Simply return the stored highlighted HTML file with the correct mime type.
|
2011-01-30 14:00:20 +03:00
|
|
|
This Resource only emits HTML and uses a standard HTML emitter rather than the emitters.DocumentingHTMLEmitter class."""
|
2011-01-26 11:58:09 +03:00
|
|
|
allowed_methods = anon_allowed_methods = ('GET',)
|
|
|
|
emitters = (HTMLEmitter,)
|
|
|
|
|
|
|
|
def get(self, request, auth, unique_id):
|
2011-01-30 14:00:20 +03:00
|
|
|
"""Return the highlighted snippet."""
|
2011-01-26 11:58:09 +03:00
|
|
|
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()
|
|
|
|
|
2011-01-30 19:51:06 +03:00
|
|
|
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)
|
2011-01-26 11:58:09 +03:00
|
|
|
|