Switch to django-appconf.

This makes it much easier to view the list of settings,
and avoids repeated calls to ``getattr(settings, 'FOO', default)``
that lead to inconsistent default values.
This commit is contained in:
Raphaël Barrois 2014-03-12 14:18:17 +01:00
parent 0469d425ab
commit 63b6380a83
10 changed files with 167 additions and 114 deletions

38
dpaste/conf.py Normal file
View file

@ -0,0 +1,38 @@
"""Default settings for dpaste."""
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
import appconf
from . import enums
class DPasteConf(appconf.AppConf):
class Meta:
prefix = 'dpaste'
BASE_URL = 'https://dpaste.de'
# Expiry
EXPIRE_CHOICES = (
(enums.EXPIRE_ONETIME, _(u'One Time Snippet')),
(enums.EXPIRE_ONE_HOUR, _(u'In one hour')),
(enums.EXPIRE_ONE_WEEK, _(u'In one week')),
(enums.EXPIRE_ONE_MONTH, _(u'In one month')),
# ('never', _(u'Never')),
)
EXPIRE_DEFAULT = enums.EXPIRE_ONE_MONTH
# Lexer
LEXER_DEFAULT = 'python'
LEXER_LIST = enums.DEFAULT_LEXER_LIST
LEXER_WORDWRAP = ('text', 'rst')
# Snippets
SLUG_LENGTH = 4
SLUG_CHOICES = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ1234567890'
MAX_CONTENT_LENGTH = 250 * 1024 * 1024
# Users
MAX_SNIPPETS_PER_USER = 15
ONETIME_LIMIT = 2

95
dpaste/enums.py Normal file
View file

@ -0,0 +1,95 @@
EXPIRE_ONETIME = 'onetime'
EXPIRE_ONE_HOUR = 3600
EXPIRE_ONE_WEEK = 3600 * 24 * 7
EXPIRE_ONE_MONTH = 3600 * 24 * 30
# Get a list of all lexer, and then remove all lexer which have '-' or '+'
# or 'with' in the name. Those are too specific and never used. This produces a
# tuple list of [(lexer, Lexer Display Name) ...] lexers.
# >>> from pygments.lexers import get_all_lexers
# >>> ALL_LEXER = set([(i[1][0], i[0]) for i in get_all_lexers()])
# >>> LEXER_LIST = [l for l in ALL_LEXER if not (
# >>> '-' in l[0]
# >>> or '+' in l[0]
# >>> or '+' in l[1]
# >>> or 'with' in l[1].lower()
# >>> or ' ' in l[1]
# >>> or l[0] in IGNORE_LEXER
# >>> )]
# >>> LEXER_LIST = sorted(LEXER_LIST)
# The list of lexers. Its not worth to autogenerate this. See above how to
# retrieve this.
DEFAULT_LEXER_LIST = (
('text', 'Text'),
('text', '----------'),
('abap', 'ABAP'),
('apacheconf', 'ApacheConf'),
('applescript', 'AppleScript'),
('as', 'ActionScript'),
('bash', 'Bash'),
('bbcode', 'BBCode'),
('c', 'C'),
('clojure', 'Clojure'),
('cobol', 'COBOL'),
('css', 'CSS'),
('cuda', 'CUDA'),
('dart', 'Dart'),
('delphi', 'Delphi'),
('diff', 'Diff'),
('django', 'Django'),
('erlang', 'Erlang'),
('fortran', 'Fortran'),
('go', 'Go'),
('groovy', 'Groovy'),
('haml', 'Haml'),
('haskell', 'Haskell'),
('html', 'HTML'),
('http', 'HTTP'),
('ini', 'INI'),
('irc', 'IRC'),
('java', 'Java'),
('js', 'JavaScript'),
('json', 'JSON'),
('lua', 'Lua'),
('make', 'Makefile'),
('mako', 'Mako'),
('mason', 'Mason'),
('matlab', 'Matlab'),
('modula2', 'Modula'),
('monkey', 'Monkey'),
('mysql', 'MySQL'),
('numpy', 'NumPy'),
('ocaml', 'OCaml'),
('perl', 'Perl'),
('php', 'PHP'),
('postscript', 'PostScript'),
('powershell', 'PowerShell'),
('prolog', 'Prolog'),
('properties', 'Properties'),
('puppet', 'Puppet'),
('python', 'Python'),
('rb', 'Ruby'),
('rst', 'reStructuredText'),
('rust', 'Rust'),
('sass', 'Sass'),
('scala', 'Scala'),
('scheme', 'Scheme'),
('scilab', 'Scilab'),
('scss', 'SCSS'),
('smalltalk', 'Smalltalk'),
('smarty', 'Smarty'),
('sql', 'SQL'),
('tcl', 'Tcl'),
('tcsh', 'Tcsh'),
('tex', 'TeX'),
('text', 'Text'),
('vb.net', 'VB.net'),
('vim', 'VimL'),
('xml', 'XML'),
('xquery', 'XQuery'),
('xslt', 'XSLT'),
('yaml', 'YAML'),
)

View file

@ -1,27 +1,18 @@
import datetime import datetime
from django import forms from django import forms
from django.conf import settings
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from dpaste.conf import settings
from dpaste.models import Snippet from dpaste.models import Snippet
from dpaste.highlight import LEXER_LIST, LEXER_DEFAULT, LEXER_KEYS from dpaste.highlight import LEXER_LIST, LEXER_DEFAULT, LEXER_KEYS
EXPIRE_CHOICES = getattr(settings, 'DPASTE_EXPIRE_CHOICES', (
('onetime', _(u'One Time Snippet')),
(3600, _(u'In one hour')),
(3600 * 24 * 7, _(u'In one week')),
(3600 * 24 * 30, _(u'In one month')),
# ('never', _(u'Never')),
))
EXPIRE_DEFAULT = getattr(settings, 'DPASTE_EXPIRE_DEFAULT', EXPIRE_CHOICES[3][0])
MAX_CONTENT_LENGTH = getattr(settings, 'DPASTE_MAX_CONTENT_LENGTH', 250*1024*1024)
class SnippetForm(forms.ModelForm): class SnippetForm(forms.ModelForm):
content = forms.CharField( content = forms.CharField(
label=_('Content'), label=_('Content'),
widget=forms.Textarea(attrs={'placeholder': _('Awesome code goes here...')}), widget=forms.Textarea(attrs={'placeholder': _('Awesome code goes here...')}),
max_length=MAX_CONTENT_LENGTH, max_length=settings.DPASTE_MAX_CONTENT_LENGTH,
) )
lexer = forms.ChoiceField( lexer = forms.ChoiceField(
@ -32,8 +23,8 @@ class SnippetForm(forms.ModelForm):
expires = forms.ChoiceField( expires = forms.ChoiceField(
label=_(u'Expires'), label=_(u'Expires'),
choices=EXPIRE_CHOICES, choices=settings.DPASTE_EXPIRE_CHOICES,
initial=EXPIRE_DEFAULT, initial=settings.DPASTE_EXPIRE_DEFAULT,
) )
# Honeypot field # Honeypot field
@ -91,8 +82,6 @@ class SnippetForm(forms.ModelForm):
return expires return expires
def save(self, parent=None, *args, **kwargs): def save(self, parent=None, *args, **kwargs):
MAX_SNIPPETS_PER_USER = getattr(settings, 'DPASTE_MAX_SNIPPETS_PER_USER', 15)
# Set parent snippet # Set parent snippet
if parent: if parent:
self.instance.parent = parent self.instance.parent = parent
@ -111,7 +100,7 @@ class SnippetForm(forms.ModelForm):
# Add the snippet to the user session list # Add the snippet to the user session list
if self.request.session.get('snippet_list', False): if self.request.session.get('snippet_list', False):
if len(self.request.session['snippet_list']) >= MAX_SNIPPETS_PER_USER: if len(self.request.session['snippet_list']) >= settings.DPASTE_MAX_SNIPPETS_PER_USER:
self.request.session['snippet_list'].pop(0) self.request.session['snippet_list'].pop(0)
self.request.session['snippet_list'] += [self.instance.pk] self.request.session['snippet_list'] += [self.instance.pk]
else: else:

View file

@ -1,7 +1,8 @@
from pygments import highlight from pygments import highlight
from pygments.lexers import * from pygments.lexers import *
from pygments.formatters import HtmlFormatter from pygments.formatters import HtmlFormatter
from django.conf import settings
from dpaste.conf import settings
""" """
# Get a list of all lexer, and then remove all lexer which have '-' or '+' # Get a list of all lexer, and then remove all lexer which have '-' or '+'
@ -22,85 +23,15 @@ LEXER_LIST = sorted(LEXER_LIST)
# The list of lexers. Its not worth to autogenerate this. See above how to # The list of lexers. Its not worth to autogenerate this. See above how to
# retrieve this. # retrieve this.
LEXER_LIST = getattr(settings, 'DPASTE_LEXER_LIST', ( LEXER_LIST = settings.DPASTE_LEXER_LIST
('text', 'Text'),
('text', '----------'),
('abap', 'ABAP'),
('apacheconf', 'ApacheConf'),
('applescript', 'AppleScript'),
('as', 'ActionScript'),
('bash', 'Bash'),
('bbcode', 'BBCode'),
('c', 'C'),
('clojure', 'Clojure'),
('cobol', 'COBOL'),
('css', 'CSS'),
('cuda', 'CUDA'),
('dart', 'Dart'),
('delphi', 'Delphi'),
('diff', 'Diff'),
('django', 'Django'),
('erlang', 'Erlang'),
('fortran', 'Fortran'),
('go', 'Go'),
('groovy', 'Groovy'),
('haml', 'Haml'),
('haskell', 'Haskell'),
('html', 'HTML'),
('http', 'HTTP'),
('ini', 'INI'),
('irc', 'IRC'),
('java', 'Java'),
('js', 'JavaScript'),
('json', 'JSON'),
('lua', 'Lua'),
('make', 'Makefile'),
('mako', 'Mako'),
('mason', 'Mason'),
('matlab', 'Matlab'),
('modula2', 'Modula'),
('monkey', 'Monkey'),
('mysql', 'MySQL'),
('numpy', 'NumPy'),
('ocaml', 'OCaml'),
('perl', 'Perl'),
('php', 'PHP'),
('postscript', 'PostScript'),
('powershell', 'PowerShell'),
('prolog', 'Prolog'),
('properties', 'Properties'),
('puppet', 'Puppet'),
('python', 'Python'),
('rb', 'Ruby'),
('rst', 'reStructuredText'),
('rust', 'Rust'),
('sass', 'Sass'),
('scala', 'Scala'),
('scheme', 'Scheme'),
('scilab', 'Scilab'),
('scss', 'SCSS'),
('smalltalk', 'Smalltalk'),
('smarty', 'Smarty'),
('sql', 'SQL'),
('tcl', 'Tcl'),
('tcsh', 'Tcsh'),
('tex', 'TeX'),
('text', 'Text'),
('vb.net', 'VB.net'),
('vim', 'VimL'),
('xml', 'XML'),
('xquery', 'XQuery'),
('xslt', 'XSLT'),
('yaml', 'YAML'),
))
LEXER_KEYS = dict(LEXER_LIST).keys() LEXER_KEYS = dict(LEXER_LIST).keys()
# The default lexer is python # The default lexer is python
LEXER_DEFAULT = getattr(settings, 'DPASTE_LEXER_DEFAULT', 'python') LEXER_DEFAULT = settings.DPASTE_LEXER_DEFAULT
# Lexers which have wordwrap enabled by default # Lexers which have wordwrap enabled by default
LEXER_WORDWRAP = getattr(settings, 'DPASTE_LEXER_WORDWRAP', ('text', 'rst')) LEXER_WORDWRAP = settings.DPASTE_LEXER_WORDWRAP
class NakedHtmlFormatter(HtmlFormatter): class NakedHtmlFormatter(HtmlFormatter):

View file

@ -2,20 +2,15 @@ from random import SystemRandom
from django.db import models from django.db import models
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.conf import settings
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
import mptt import mptt
from dpaste.conf import settings
from dpaste.highlight import LEXER_DEFAULT from dpaste.highlight import LEXER_DEFAULT
R = SystemRandom() R = SystemRandom()
L = getattr(settings, 'DPASTE_SLUG_LENGTH', 4)
T = getattr(settings, 'DPASTE_SLUG_CHOICES',
'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ1234567890')
ONETIME_LIMIT = getattr(settings, 'DPASTE_ONETIME_LIMIT', 2) def generate_secret_id(length=settings.DPASTE_SLUG_LENGTH, alphabet=settings.DPASTE_SLUG_CHOICES):
def generate_secret_id(length=L, alphabet=T):
return ''.join([R.choice(alphabet) for i in range(length)]) return ''.join([R.choice(alphabet) for i in range(length)])
class Snippet(models.Model): class Snippet(models.Model):
@ -48,7 +43,7 @@ class Snippet(models.Model):
@property @property
def remaining_views(self): def remaining_views(self):
if self.expire_type == self.EXPIRE_ONETIME: if self.expire_type == self.EXPIRE_ONETIME:
remaining = ONETIME_LIMIT - self.view_count remaining = settings.DPASTE_ONETIME_LIMIT - self.view_count
return remaining > 0 and remaining or 0 return remaining > 0 and remaining or 0
return None return None

View file

@ -8,9 +8,9 @@ from django.test.client import Client
from django.test import TestCase from django.test import TestCase
from django.test.utils import override_settings from django.test.utils import override_settings
from dpaste.conf import settings
from ..models import Snippet from ..models import Snippet
from ..forms import EXPIRE_DEFAULT
from ..highlight import LEXER_DEFAULT
class SnippetTestCase(TestCase): class SnippetTestCase(TestCase):
@ -22,8 +22,8 @@ class SnippetTestCase(TestCase):
def valid_form_data(self): def valid_form_data(self):
return { return {
'content': u"Hello Wörld.\n\tGood Bye", 'content': u"Hello Wörld.\n\tGood Bye",
'lexer': LEXER_DEFAULT, 'lexer': settings.DPASTE_LEXER_DEFAULT,
'expires': EXPIRE_DEFAULT, 'expires': settings.DPASTE_EXPIRE_DEFAULT,
} }

View file

@ -1,3 +1,5 @@
from __future__ import absolute_import
from django.conf.urls import url, patterns, include from django.conf.urls import url, patterns, include
urlpatterns = patterns( urlpatterns = patterns(

View file

@ -1,7 +1,10 @@
from django.conf.urls import url, patterns from __future__ import absolute_import
from django.conf import settings
L = getattr(settings, 'DPASTE_SLUG_LENGTH', 4) from django.conf.urls import url, patterns
from dpaste.conf import settings
L = settings.DPASTE_SLUG_LENGTH
urlpatterns = patterns('dpaste.views', urlpatterns = patterns('dpaste.views',
url(r'^about/$', 'about', name='dpaste_about'), url(r'^about/$', 'about', name='dpaste_about'),

View file

@ -7,7 +7,6 @@ from django.shortcuts import (render_to_response, get_object_or_404)
from django.template.context import RequestContext from django.template.context import RequestContext
from django.http import (Http404, HttpResponseRedirect, HttpResponseBadRequest, from django.http import (Http404, HttpResponseRedirect, HttpResponseBadRequest,
HttpResponse) HttpResponse)
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
@ -16,8 +15,9 @@ from django.views.defaults import (page_not_found as django_page_not_found,
server_error as django_server_error) server_error as django_server_error)
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
from dpaste.conf import settings
from dpaste.forms import SnippetForm from dpaste.forms import SnippetForm
from dpaste.models import Snippet, ONETIME_LIMIT from dpaste.models import Snippet
from dpaste.highlight import LEXER_WORDWRAP, LEXER_LIST from dpaste.highlight import LEXER_WORDWRAP, LEXER_LIST
from dpaste.highlight import LEXER_DEFAULT, LEXER_KEYS from dpaste.highlight import LEXER_DEFAULT, LEXER_KEYS
@ -60,7 +60,7 @@ def snippet_details(request, snippet_id, template_name='dpaste/snippet_details.h
# One time snippet get deleted if the view count matches our limit # One time snippet get deleted if the view count matches our limit
if snippet.expire_type == Snippet.EXPIRE_ONETIME \ if snippet.expire_type == Snippet.EXPIRE_ONETIME \
and snippet.view_count >= ONETIME_LIMIT: and snippet.view_count >= settings.DPASTE_ONETIME_LIMIT:
snippet.delete() snippet.delete()
raise Http404() raise Http404()
@ -145,7 +145,7 @@ def snippet_history(request, template_name='dpaste/snippet_list.html'):
return HttpResponseRedirect(reverse('snippet_history')) return HttpResponseRedirect(reverse('snippet_history'))
template_context = { template_context = {
'snippets_max': getattr(settings, 'DPASTE_MAX_SNIPPETS_PER_USER', 10), 'snippets_max': settings.DPASTE_MAX_SNIPPETS_PER_USER,
'snippet_list': snippet_list, 'snippet_list': snippet_list,
} }
@ -259,21 +259,20 @@ def about(request, template_name='dpaste/about.html'):
def _format_default(s): def _format_default(s):
"""The default response is the snippet URL wrapped in quotes.""" """The default response is the snippet URL wrapped in quotes."""
return u'"%s%s"' % (BASE_URL, s.get_absolute_url()) return u'"%s%s"' % (settings.DPASTE_BASE_URL, s.get_absolute_url())
def _format_url(s): def _format_url(s):
"""The `url` format returns the snippet URL, no quotes, but a linebreak after.""" """The `url` format returns the snippet URL, no quotes, but a linebreak after."""
return u'%s%s\n' % (BASE_URL, s.get_absolute_url()) return u'%s%s\n' % (settings.DPASTE_BASE_URL, s.get_absolute_url())
def _format_json(s): def _format_json(s):
"""The `json` format export.""" """The `json` format export."""
return json.dumps({ return json.dumps({
'url': u'%s%s' % (BASE_URL, s.get_absolute_url()), 'url': u'%s%s' % (settings.DPASTE_BASE_URL, s.get_absolute_url()),
'content': s.content, 'content': s.content,
'lexer': s.lexer, 'lexer': s.lexer,
}) })
BASE_URL = getattr(settings, 'DPASTE_BASE_URL', 'https://dpaste.de')
FORMAT_MAPPING = { FORMAT_MAPPING = {
'default': _format_default, 'default': _format_default,
@ -297,7 +296,7 @@ def snippet_api(request):
s = Snippet.objects.create( s = Snippet.objects.create(
content=content, content=content,
lexer=lexer, lexer=lexer,
expires=datetime.datetime.now()+datetime.timedelta(seconds=60*60*24*30) expires=datetime.datetime.now() + datetime.timedelta(seconds=60*60*24*30)
) )
s.save() s.save()

View file

@ -9,6 +9,7 @@ django==1.6.1
django-mptt==0.6.0 django-mptt==0.6.0
pygments==1.6 pygments==1.6
requests==2.0.0 requests==2.0.0
django-appconf==0.6
# Testing # Testing
python-coveralls==2.4.0 python-coveralls==2.4.0