Initial commit after move to linode

This commit is contained in:
Martin Mahner 2011-05-30 01:03:04 +02:00
commit a2e4e83c20
65 changed files with 3333 additions and 0 deletions

7
.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
*~
*.pyc
docs/_build/*
uploads
pastebin/conf/local/*.py
dev.db
pastebin.egg-info

308
.pylintrc Normal file
View file

@ -0,0 +1,308 @@
# lint Python modules using external checkers.
#
# This is the main checker controlling the other ones and the reports
# generation. It is itself both a raw checker and an astng checker in order
# to:
# * handle message activation / deactivation at the module level
# * handle some basic but necessary stats'data (number of classes, methods...)
#
[MASTER]
# Specify a configuration file.
#rcfile=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=
# Profiled execution.
profile=no
# Add <file or directory> to the black list. It should be a base name, not a
# path. You may set this option multiple times.
ignore=conf
ignore=migrations
# Pickle collected data for later comparisons.
persistent=yes
# Set the cache size for astng objects.
cache-size=500
# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=
[MESSAGES CONTROL]
# Enable only checker(s) with the given id(s). This option conflicts with the
# disable-checker option
#enable-checker=
# Enable all checker(s) except those with the given id(s). This option
# conflicts with the enable-checker option
#disable-checker=
# Enable all messages in the listed categories (IRCWEF).
#enable-msg-cat=
# Disable all messages in the listed categories (IRCWEF).
disable-msg-cat=I
# Enable the message(s) with the given id(s).
#enable-msg=
# Disable the message(s) with the given id(s).
disable=W0704,W0201,W0142,W0232,R0903,C0301
[REPORTS]
# Set the output format. Available formats are text, parseable, colorized, msvs
# (visual studio) and html
output-format=text
# Include message's id in output
include-ids=yes
# Put messages in a separate file for each module / package specified on the
# command line instead of printing them on stdout. Reports (if any) will be
# written in a file name "pylint_global.[txt|html]".
files-output=no
# Tells wether to display a full report or only the messages
reports=yes
# Python expression which should return a note less than 10 (10 is the highest
# note). You have access to the variables errors warning, statement which
# respectivly contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation report
# (R0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
# Add a comment according to your evaluation note. This is used by the global
# evaluation report (R0004).
comment=no
# Enable the report(s) with the given id(s).
#enable-report=
# Disable the report(s) with the given id(s).
#disable-report=
# checks for :
# * doc strings
# * modules / classes / functions / methods / arguments / variables name
# * number of arguments, local variables, branchs, returns and statements in
# functions, methods
# * required module attributes
# * dangerous default values as arguments
# * redefinition of function / method / class
# * uses of the global statement
#
[BASIC]
# Required attributes for module, separated by a comma
required-attributes=
# Regular expression which should only match functions or classes name which do
# not require a docstring
no-docstring-rgx=__.*__|get_absolute_url
# Regular expression which should only match correct module names
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Regular expression which should only match correct module level names
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Regular expression which should only match correct class names
class-rgx=[A-Z_][a-zA-Z0-9]+$
# Regular expression which should only match correct function names
function-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct method names
method-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct instance attribute names
attr-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct argument names
argument-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct variable names
variable-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}$)
# Regular expression which should only match correct list comprehension /
# generator expression variable names
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
# Good variable names which should always be accepted, separated by a comma
good-names=i,j,k,v,qs,urlpatterns,register,p,a,t,r,u,x,f,e,setUp,tearDown
# Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata
# List of builtins function names that should not be used, separated by a comma
bad-functions=map,filter,apply,input
# try to find bugs in the code using type inference
#
[TYPECHECK]
# Tells wether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# List of classes names for which member attributes should not be checked
# (useful for classes with attributes dynamicaly set).
ignored-classes=SQLObject
# When zope mode is activated, add a predefined set of Zope acquired attributes
# to generated-members.
zope=no
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E0201 when accessed.
generated-members=objects,DoesNotExist,id,pk,_default_manager,_meta
# checks for
# * unused variables / imports
# * undefined variables
# * redefinition of variable from builtins or from an outer scope
# * use of variable before assigment
#
[VARIABLES]
# Tells wether we should check for unused import in __init__ files.
init-import=no
# A regular expression matching names used for dummy variables (i.e. not used).
dummy-variables-rgx=_|dummy
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
additional-builtins=
# checks for :
# * methods without self as first argument
# * overridden methods signature
# * access only to existant members via self
# * attributes not defined in the __init__ method
# * supported interfaces implementation
# * unreachable code
#
[CLASSES]
# List of interface methods to ignore, separated by a comma. This is used for
# instance to not check methods defines in Zope's Interface base class.
ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,__new__,setUp
# checks for sign of poor/misdesign:
# * number of methods, attributes, local variables...
# * size, complexity of functions, methods
#
[DESIGN]
# Maximum number of arguments for function / method
max-args=5
# Maximum number of locals for function / method body
max-locals=15
# Maximum number of return / yield for function / method body
max-returns=6
# Maximum number of branch for function / method body
max-branchs=12
# Maximum number of statements in function / method body
max-statements=50
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of attributes for a class (see R0902).
max-attributes=7
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
# checks for
# * external modules dependencies
# * relative / wildcard imports
# * cyclic imports
# * uses of deprecated modules
#
[IMPORTS]
# Deprecated modules which should not be used, separated by a comma
deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report R0402 must not be disabled)
import-graph=
# Create a graph of external dependencies in the given file (report R0402 must
# not be disabled)
ext-import-graph=
# Create a graph of internal dependencies in the given file (report R0402 must
# not be disabled)
int-import-graph=
# checks for :
# * unauthorized constructions
# * strict indentation
# * line length
# * use of <> instead of !=
#
[FORMAT]
# Maximum number of characters on a single line.
max-line-length=88
# Maximum number of lines in a module
max-module-lines=1000
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# checks for:
# * warning notes in the code like FIXME, XXX
# * PEP 263: source code with non ascii character but no encoding declaration
#
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,XXX,TODO
# checks for similarities and duplicated code. This computation may be
# memory / CPU intensive, so you should disable it if you experiments some
# problems.
#
[SIMILARITIES]
# Minimum lines number of a similarity.
min-similarity-lines=4
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes

4
README Normal file
View file

@ -0,0 +1,4 @@
Developer documentation is available in Sphinx format in the docs directory.
Initial installation instructions (including how to build the documentation as
HTML) can be found in docs/install.rst.

88
docs/Makefile Normal file
View file

@ -0,0 +1,88 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf _build/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
@echo
@echo "Build finished. The HTML pages are in _build/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) _build/dirhtml
@echo
@echo "Build finished. The HTML pages are in _build/dirhtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in _build/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in _build/qthelp, like this:"
@echo "# qcollectiongenerator _build/qthelp/pastebin.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile _build/qthelp/pastebin.qhc"
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex
@echo
@echo "Build finished; the LaTeX files are in _build/latex."
@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
"run these through (pdf)latex."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes
@echo
@echo "The overview file is in _build/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in _build/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in _build/doctest/output.txt."

195
docs/conf.py Normal file
View file

@ -0,0 +1,195 @@
# -*- coding: utf-8 -*-
#
# pastebin documentation build configuration file, created by
# sphinx-quickstart on Wed Aug 19 10:27:46 2009.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
import datetime
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.append(os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'pastebin'
copyright = u'%d, Martin Mahner' % datetime.date.today().year
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '1.0'
# The full version, including alpha/beta/rc tags.
release = '1.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of documents that shouldn't be included in the build.
#unused_docs = []
# List of directories, relative to source directory, that shouldn't be searched
# for source files.
exclude_trees = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_use_modindex = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = ''
# Output file base name for HTML help builder.
htmlhelp_basename = 'pastebindoc'
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'pastebin.tex', u'pastebin Documentation',
u'Martin Mahner', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_use_modindex = True

18
docs/deployment.rst Normal file
View file

@ -0,0 +1,18 @@
Deployment
==========
Staging/Development
-------------------
`Fabric <http://pypi.python.org/pypi/Fabric>`_ is used to allow developers to
easily push changes to a previously setup development/staging environment.
To get started, run the following command from within your virtual
environment::
pip install fabric==0.9.3
fab --fabfile src/pastebin/fabfile.py -l
This will install Fabric and provide a list of available commands.
When run from src/pastebin, you can just run ``fab [command]`` (i.e. without
the ``-fabfile`` flag).

18
docs/index.rst Normal file
View file

@ -0,0 +1,18 @@
Welcome to pastebin's documentation!
=====================================
Contents:
.. toctree::
:maxdepth: 2
install
deployment
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

57
docs/install.rst Normal file
View file

@ -0,0 +1,57 @@
==================
Installation
==================
Pre-Requisites
===============
* `setuptools <http://pypi.python.org/pypi/setuptools>`_
* `virtualenv <http://pypi.python.org/pypi/virtualenv>`_
To install all of these system dependencies on a Debian-based system, run::
sudo apt-get install python-setuptools
sudo easy_install virtualenv
Creating the Virtual Environment
================================
First, create a clean base environment using virtualenv::
virtualenv pastebin
cd pastebin
source bin/activate
Installing the Project
======================
Install the requirements and the project source::
cd path/to/your/pastebin/repository
pip install -r requirements.pip
pip install -e .
Configuring a Local Environment
===============================
If you're just checking the project out locally, you can copy some example
configuration files to get started quickly::
cp pastebin/conf/local/example/* pastebin/conf/local
manage.py syncdb --migrate
Building Documentation
======================
Documentation is available in ``docs`` and can be built into a number of
formats using `Sphinx <http://pypi.python.org/pypi/Sphinx>`_. To get started::
pip install Sphinx
cd docs
make html
This creates the documentation in HTML format at ``docs/_build/html``.

92
fabfile.py vendored Normal file
View file

@ -0,0 +1,92 @@
from fabric.api import env, local, run, require, cd
from fabric.operations import _prefix_commands, _prefix_env_vars
env.disable_known_hosts = True # always fails for me without this
env.hosts = ['pastebin.dev.lincolnloop.com']
env.root = '/opt/webapps/pastebin'
env.proj_root = env.root + '/src/pastebin'
env.proj_repo = 'git@github.com:myuser/myrepo.git'
env.pip_file = env.proj_root + '/requirements.pip'
def deploy():
"""Update source, update pip requirements, syncdb, restart server"""
update()
update_reqs()
syncdb()
restart()
def switch(branch):
"""Switch the repo branch which the server is using"""
with cd(env.proj_root):
ve_run('git checkout %s' % branch)
restart()
def version():
"""Show last commit to repo on server"""
with cd(env.proj_root):
sshagent_run('git log -1')
def restart():
"""Restart Apache process"""
run('touch %s/etc/apache/django.wsgi' % env.root)
def update_reqs():
"""Update pip requirements"""
ve_run('yes w | pip install -r %s' % env.pip_file)
def update():
"""Updates project source"""
with cd(env.proj_root):
sshagent_run('git pull')
def syncdb():
"""Run syncdb (along with any pending south migrations)"""
ve_run('manage.py syncdb --migrate')
def clone():
"""Clone the repository for the first time"""
with cd('%s/src' % env.root):
sshagent_run('git clone %s' % env.proj_repo)
ve_run('pip install -e %s' % env.proj_root)
with cd('%s/pastebin/conf/local' % env.proj_root):
run('ln -s ../dev/__init__.py')
run('ln -s ../dev/settings.py')
def ve_run(cmd):
"""
Helper function.
Runs a command using the virtualenv environment
"""
require('root')
return sshagent_run('source %s/bin/activate; %s' % (env.root, cmd))
def sshagent_run(cmd):
"""
Helper function.
Runs a command with SSH agent forwarding enabled.
Note:: Fabric (and paramiko) can't forward your SSH agent.
This helper uses your system's ssh to do so.
"""
# Handle context manager modifications
wrapped_cmd = _prefix_commands(_prefix_env_vars(cmd), 'remote')
try:
host, port = env.host_string.split(':')
return local(
"ssh -p %s -A %s@%s '%s'" % (port, env.user, host, wrapped_cmd)
)
except ValueError:
return local(
"ssh -A %s@%s '%s'" % (env.user, env.host_string, wrapped_cmd)
)

0
pastebin/__init__.py Normal file
View file

View file

View file

View file

@ -0,0 +1,29 @@
import datetime
import re
from piston.utils import rc
from piston.handler import AnonymousBaseHandler
from pastebin.apps.dpaste.models import Snippet
class SnippetHandler(AnonymousBaseHandler):
allowed_methods = ('GET', 'POST')
fields = ('title', 'content',)
exclude = ('id', re.compile(r'^private_'))
model = Snippet
def content_size(self, blogpost):
return len(blogpost.content)
def read(self, request, secret_id):
post = Snippet.objects.get(secret_id=secret_id)
return post
def create(self, request):
if not request.POST.get('content'):
return rc.BAD_REQUEST
s = Snippet.objects.create(
content=request.POST.get('content'),
expires=datetime.datetime.now()+datetime.timedelta(seconds=60*60*24*30)
)
s.save()
return 'http://dpaste.de%s' % s.get_absolute_url()

View file

@ -0,0 +1 @@
__version__ = '0.2.3'

View file

@ -0,0 +1,13 @@
from pastebin.apps.dpaste.models import Snippet
from django.contrib import admin
class SnippetAdmin(admin.ModelAdmin):
list_display = (
'__unicode__',
'author',
'lexer',
'published',
'expires',
)
admin.site.register(Snippet, SnippetAdmin)

View file

@ -0,0 +1,109 @@
from django import forms
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from pastebin.apps.dpaste.models import Snippet
from pastebin.apps.dpaste.highlight import LEXER_LIST_ALL, LEXER_LIST, LEXER_DEFAULT
import datetime
#===============================================================================
# Snippet Form and Handling
#===============================================================================
EXPIRE_CHOICES = (
(3600, _(u'In one hour')),
(3600*24*7, _(u'In one week')),
(3600*24*30, _(u'In one month')),
(3600*24*30*12*100, _(u'Save forever')), # 100 years, I call it forever ;)
)
EXPIRE_DEFAULT = 3600*24*30
class SnippetForm(forms.ModelForm):
lexer = forms.ChoiceField(
choices=LEXER_LIST,
initial=LEXER_DEFAULT,
label=_(u'Lexer'),
)
expire_options = forms.ChoiceField(
choices=EXPIRE_CHOICES,
initial=EXPIRE_DEFAULT,
label=_(u'Expires'),
)
def __init__(self, request, *args, **kwargs):
super(SnippetForm, self).__init__(*args, **kwargs)
self.request = request
try:
if self.request.session['userprefs'].get('display_all_lexer', False):
self.fields['lexer'].choices = LEXER_LIST_ALL
except KeyError:
pass
try:
self.fields['author'].initial = self.request.session['userprefs'].get('default_name', '')
except KeyError:
pass
def save(self, parent=None, *args, **kwargs):
# Set parent snippet
if parent:
self.instance.parent = parent
# Add expire datestamp
self.instance.expires = datetime.datetime.now() + \
datetime.timedelta(seconds=int(self.cleaned_data['expire_options']))
# Save snippet in the db
super(SnippetForm, self).save(*args, **kwargs)
# Add the snippet to the user session list
if self.request.session.get('snippet_list', False):
if len(self.request.session['snippet_list']) >= getattr(settings, 'MAX_SNIPPETS_PER_USER', 10):
self.request.session['snippet_list'].pop(0)
self.request.session['snippet_list'] += [self.instance.pk]
else:
self.request.session['snippet_list'] = [self.instance.pk]
return self.request, self.instance
class Meta:
model = Snippet
fields = (
'title',
'content',
'author',
'lexer',
)
#===============================================================================
# User Settings
#===============================================================================
USERPREFS_FONT_CHOICES = [(None, _(u'Default'))] + [
(i, i) for i in sorted((
'Monaco',
'Bitstream Vera Sans Mono',
'Courier New',
'Consolas',
))
]
USERPREFS_SIZES = [(None, _(u'Default'))] + [(i, '%dpx' % i) for i in range(5, 25)]
class UserSettingsForm(forms.Form):
default_name = forms.CharField(label=_(u'Default Name'), required=False)
display_all_lexer = forms.BooleanField(
label=_(u'Display all lexer'),
required=False,
widget=forms.CheckboxInput,
help_text=_(u'This also enables the super secret \'guess lexer\' function.'),
)
font_family = forms.ChoiceField(label=_(u'Font Family'), required=False, choices=USERPREFS_FONT_CHOICES)
font_size = forms.ChoiceField(label=_(u'Font Size'), required=False, choices=USERPREFS_SIZES)
line_height = forms.ChoiceField(label=_(u'Line Height'), required=False, choices=USERPREFS_SIZES)

View file

@ -0,0 +1,43 @@
from pygments.lexers import get_all_lexers, get_lexer_by_name, guess_lexer
from pygments.styles import get_all_styles
from pygments.formatters import HtmlFormatter
from pygments.util import ClassNotFound
from pygments import highlight
LEXER_LIST_ALL = sorted([(i[1][0], i[0]) for i in get_all_lexers()])
LEXER_LIST = (
('bash', 'Bash'),
('c', 'C'),
('css', 'CSS'),
('diff', 'Diff'),
('django', 'Django/Jinja'),
('html', 'HTML'),
('irc', 'IRC logs'),
('js', 'JavaScript'),
('php', 'PHP'),
('pycon', 'Python console session'),
('pytb', 'Python Traceback'),
('python', 'Python'),
('python3', 'Python 3'),
('rst', 'Restructured Text'),
('sql', 'SQL'),
('text', 'Text only'),
)
LEXER_DEFAULT = 'python'
class NakedHtmlFormatter(HtmlFormatter):
def wrap(self, source, outfile):
return self._wrap_code(source)
def _wrap_code(self, source):
for i, t in source:
yield i, t
def pygmentize(code_string, lexer_name='text'):
return highlight(code_string, get_lexer_by_name(lexer_name), NakedHtmlFormatter())
def guess_code_lexer(code_string, default_lexer='unknown'):
try:
return guess_lexer(code_string).name
except ClassNotFound:
return default_lexer

Binary file not shown.

View file

@ -0,0 +1,236 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-05-07 12:23+0200\n"
"PO-Revision-Date: 2008-08-10 01:20+0100\n"
"Last-Translator: Martin Mahner <martin@mahner.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: forms.py:13
msgid "In one hour"
msgstr "In einer Stunde"
#: forms.py:14
msgid "In one week"
msgstr "In einer Woche"
#: forms.py:15
msgid "In one month"
msgstr "In einem Monat"
#: forms.py:16
msgid "Save forever"
msgstr "Für immer speichern"
#: forms.py:26 models.py:20
msgid "Lexer"
msgstr "Syntax"
#: forms.py:32 models.py:22
msgid "Expires"
msgstr "Erlischt"
#: forms.py:87 forms.py:96
msgid "Default"
msgstr "Standard"
#: forms.py:100
msgid "Default Name"
msgstr "Standard Name"
#: forms.py:102
msgid "Display all lexer"
msgstr "Alle Syntaxformate anzeigen"
#: forms.py:105
msgid "This also enables the super secret 'guess lexer' function."
msgstr "Dies aktiviert auch die super geheime 'Syntax erraten' Funktion."
#: forms.py:107
msgid "Font Family"
msgstr "Schriftart"
#: forms.py:108
msgid "Font Size"
msgstr "Schriftgröße"
#: forms.py:109
msgid "Line Height"
msgstr "Zeilenhöhe"
#: models.py:15
msgid "Secret ID"
msgstr "Geheime ID"
#: models.py:16
msgid "Title"
msgstr "Titel"
#: models.py:17
msgid "Author"
msgstr "Autor"
#: models.py:18
msgid "Content"
msgstr "Inhalt"
#: models.py:19
msgid "Highlighted Content"
msgstr "Gehighlighteter Content"
#: models.py:21
msgid "Published"
msgstr "Veröffentlicht"
#: views.py:145
msgid "No changes were made between this two files."
msgstr "Zwischen diesen beiden Dateien wurden keine Änderungen durchgeführt."
#: templates/dpaste/snippet_details.html:18
#: templates/dpaste/snippet_details.html:21
#: templates/dpaste/snippet_details.html:44
#: templates/dpaste/snippet_details.html:81
#: templates/dpaste/snippet_details.html:83
#: templates/dpaste/snippet_list.html:4 templates/dpaste/snippet_list.html:13
msgid "Snippet"
msgstr "Snippet"
#: templates/dpaste/snippet_details.html:23
#, python-format
msgid "(Copy of <a href=\"%(parent_url)s\">snippet #%(parent_id)s</a>)"
msgstr "(Kopie von <a href=\"%(parent_url)s\">Snippet #%(parent_id)s</a>)"
#: templates/dpaste/snippet_details.html:25
#: templates/dpaste/snippet_list.html:14
msgid "DATETIME_FORMAT"
msgstr ""
#: templates/dpaste/snippet_details.html:25
msgid "UTC"
msgstr "UTC"
#: templates/dpaste/snippet_details.html:35
msgid "Time to life"
msgstr ""
#: templates/dpaste/snippet_details.html:38
msgid "Really delete this snippet?"
msgstr "Wirklich dieses Snippet löschen?"
#: templates/dpaste/snippet_details.html:41
msgid "Wordwrap"
msgstr ""
#: templates/dpaste/snippet_details.html:45
#, python-format
msgid "by %(author)s"
msgstr "von %(author)s"
#: templates/dpaste/snippet_details.html:59
msgid "Write an answer"
msgstr "Schreibe eine Antwort"
#: templates/dpaste/snippet_details.html:69
msgid "History"
msgstr "Verlauf"
#: templates/dpaste/snippet_details.html:89
msgid "Compare"
msgstr "Vergleichen"
#: templates/dpaste/snippet_details.html:94
msgid "Options"
msgstr "Optionen"
#: templates/dpaste/snippet_details.html:95
msgid "View raw"
msgstr "Rohformat"
#: templates/dpaste/snippet_diff.html:4
msgid "Close"
msgstr "Schließen"
#: templates/dpaste/snippet_diff.html:5
#, python-format
msgid ""
"\n"
" Diff between\n"
" <a href=\"%(filea_url)s\">Snippet #%(filea_id)s</a>\n"
" and\n"
" <a href=\"%(fileb_url)s\">Snippet #%(fileb_id)s</a>\n"
" "
msgstr ""
"\n"
" Diff zwischen\n"
" <a href=\"%(filea_url)s\">Snippet #%(filea_id)s</a>\n"
" und\n"
" <a href=\"%(fileb_url)s\">Snippet #%(fileb_id)s</a>\n"
" "
#: templates/dpaste/snippet_form.html:10
msgid "Guess lexer"
msgstr "Syntax erraten"
#: templates/dpaste/snippet_form.html:15
msgid "Paste it"
msgstr "Paste es"
#: templates/dpaste/snippet_list.html:6
#, python-format
msgid "Your latest %(snippets_max)s snippets"
msgstr "Deine neuesten %(snippets_max)s Snippets"
#: templates/dpaste/snippet_list.html:19
msgid "No snippets available."
msgstr "Keine Snippets verfügbar"
#: templates/dpaste/snippet_list.html:24 templates/dpaste/userprefs.html:25
msgid "DATA_STORED_IN_A_COOKIE_HINT"
msgstr ""
"<p><strong>Hinweis:</strong> Deine Daten werden in einem Cookie gespeichert."
#: templates/dpaste/snippet_new.html:4 templates/dpaste/snippet_new.html:8
msgid "New snippet"
msgstr "Neues Snippet"
#: templates/dpaste/snippet_new.html:5
msgid "Paste a new snippet"
msgstr "Schreibe ein neues Snippet"
#: templates/dpaste/snippet_new.html:14
msgid "DPASTE_HOMEPAGE_TITLE"
msgstr "dpaste"
#: templates/dpaste/snippet_new.html:15
msgid "DPASTE_HOMEPAGE_DESCRIPTION"
msgstr ""
"dpaste.de ist ein Codespeicher inspiriert von <a href=\"http://dpaste.com/"
"\">dpaste.com</a>. Die Vorteile und den Quellcode dieser Seite findest du "
"bei <a href=\"http://code.google.com/p/django-paste/\">Google Code</a>."
#: templates/dpaste/userprefs.html:5 templates/dpaste/userprefs.html.py:15
msgid "User Settings"
msgstr "Benutzereinstellungen"
#: templates/dpaste/userprefs.html:11
msgid "USER_PREFS_SAVED_SUCCESSFULLY"
msgstr "Deine Einstellungen wurden erfolgreich gespeichert."
#: templates/dpaste/userprefs.html:20
msgid "Save settings"
msgstr "Einstellungen speichern"
#~ msgid "WHAT_IS_THIS_TITLE"
#~ msgstr "Was ist das hier?"
#~ msgid "Youre displaying the whole bunch of lexers!"
#~ msgstr "Du siehst derzeit das ganze Bündel an Lexern!"

Binary file not shown.

View file

@ -0,0 +1,226 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-05-07 12:23+0200\n"
"PO-Revision-Date: 2008-08-10 01:19+0100\n"
"Last-Translator: Martin Mahner <martin@mahner.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: forms.py:13
msgid "In one hour"
msgstr ""
#: forms.py:14
msgid "In one week"
msgstr ""
#: forms.py:15
msgid "In one month"
msgstr ""
#: forms.py:16
msgid "Save forever"
msgstr ""
#: forms.py:26 models.py:20
msgid "Lexer"
msgstr "Syntax"
#: forms.py:32 models.py:22
msgid "Expires"
msgstr ""
#: forms.py:87 forms.py:96
msgid "Default"
msgstr ""
#: forms.py:100
msgid "Default Name"
msgstr ""
#: forms.py:102
msgid "Display all lexer"
msgstr "Display all syntax modes"
#: forms.py:105
msgid "This also enables the super secret 'guess lexer' function."
msgstr "This also enables the super secret 'guess syntax' function."
#: forms.py:107
msgid "Font Family"
msgstr ""
#: forms.py:108
msgid "Font Size"
msgstr ""
#: forms.py:109
msgid "Line Height"
msgstr ""
#: models.py:15
msgid "Secret ID"
msgstr ""
#: models.py:16
msgid "Title"
msgstr ""
#: models.py:17
msgid "Author"
msgstr ""
#: models.py:18
msgid "Content"
msgstr ""
#: models.py:19
msgid "Highlighted Content"
msgstr ""
#: models.py:21
msgid "Published"
msgstr ""
#: views.py:145
msgid "No changes were made between this two files."
msgstr ""
#: templates/dpaste/snippet_details.html:18
#: templates/dpaste/snippet_details.html:21
#: templates/dpaste/snippet_details.html:44
#: templates/dpaste/snippet_details.html:81
#: templates/dpaste/snippet_details.html:83
#: templates/dpaste/snippet_list.html:4 templates/dpaste/snippet_list.html:13
msgid "Snippet"
msgstr ""
#: templates/dpaste/snippet_details.html:23
#, python-format
msgid "(Copy of <a href=\"%(parent_url)s\">snippet #%(parent_id)s</a>)"
msgstr ""
#: templates/dpaste/snippet_details.html:25
#: templates/dpaste/snippet_list.html:14
msgid "DATETIME_FORMAT"
msgstr ""
#: templates/dpaste/snippet_details.html:25
msgid "UTC"
msgstr ""
#: templates/dpaste/snippet_details.html:35
msgid "Time to life"
msgstr ""
#: templates/dpaste/snippet_details.html:38
msgid "Really delete this snippet?"
msgstr ""
#: templates/dpaste/snippet_details.html:41
msgid "Wordwrap"
msgstr ""
#: templates/dpaste/snippet_details.html:45
#, python-format
msgid "by %(author)s"
msgstr ""
#: templates/dpaste/snippet_details.html:59
msgid "Write an answer"
msgstr ""
#: templates/dpaste/snippet_details.html:69
msgid "History"
msgstr ""
#: templates/dpaste/snippet_details.html:89
msgid "Compare"
msgstr ""
#: templates/dpaste/snippet_details.html:94
msgid "Options"
msgstr ""
#: templates/dpaste/snippet_details.html:95
msgid "View raw"
msgstr ""
#: templates/dpaste/snippet_diff.html:4
msgid "Close"
msgstr ""
#: templates/dpaste/snippet_diff.html:5
#, python-format
msgid ""
"\n"
" Diff between\n"
" <a href=\"%(filea_url)s\">Snippet #%(filea_id)s</a>\n"
" and\n"
" <a href=\"%(fileb_url)s\">Snippet #%(fileb_id)s</a>\n"
" "
msgstr ""
#: templates/dpaste/snippet_form.html:10
msgid "Guess lexer"
msgstr "Guess syntax"
#: templates/dpaste/snippet_form.html:15
msgid "Paste it"
msgstr ""
#: templates/dpaste/snippet_list.html:6
#, python-format
msgid "Your latest %(snippets_max)s snippets"
msgstr ""
#: templates/dpaste/snippet_list.html:19
msgid "No snippets available."
msgstr ""
#: templates/dpaste/snippet_list.html:24 templates/dpaste/userprefs.html:25
msgid "DATA_STORED_IN_A_COOKIE_HINT"
msgstr "<p><strong>Remember:</strong> Your data is stored in a cookie.</p>"
#: templates/dpaste/snippet_new.html:4 templates/dpaste/snippet_new.html:8
msgid "New snippet"
msgstr ""
#: templates/dpaste/snippet_new.html:5
msgid "Paste a new snippet"
msgstr ""
#: templates/dpaste/snippet_new.html:14
msgid "DPASTE_HOMEPAGE_TITLE"
msgstr "dpaste"
#: templates/dpaste/snippet_new.html:15
msgid "DPASTE_HOMEPAGE_DESCRIPTION"
msgstr ""
"dpaste is code pastebin originally inspired by <a href=\"http://dpaste."
"com/\">dpaste.com</a>. Find the advantages and the public sourcecode on <a "
"href=\"http://code.google.com/p/django-paste/\">Google Code</a>."
#: templates/dpaste/userprefs.html:5 templates/dpaste/userprefs.html.py:15
msgid "User Settings"
msgstr ""
#: templates/dpaste/userprefs.html:11
msgid "USER_PREFS_SAVED_SUCCESSFULLY"
msgstr "Your preferences were successfully saved."
#: templates/dpaste/userprefs.html:20
msgid "Save settings"
msgstr ""
#~ msgid "WHAT_IS_THIS_TITLE"
#~ msgstr "What is this?"

View file

@ -0,0 +1,22 @@
import datetime
import sys
from optparse import make_option
from django.core.management.base import CommandError, LabelCommand
from pastebin.apps.dpaste.models import Snippet
class Command(LabelCommand):
option_list = LabelCommand.option_list + (
make_option('--dry-run', '-d', action='store_true', dest='dry_run',
help='Don\'t do anything.'),
)
help = "Purges snippets that are expired"
def handle(self, *args, **options):
deleteable_snippets = Snippet.objects.filter(expires__lte=datetime.datetime.now())
sys.stdout.write(u"%s snippets gets deleted:\n" % deleteable_snippets.count())
for d in deleteable_snippets:
sys.stdout.write(u"- %s (%s)\n" % (d.secret_id, d.expires))
if options.get('dry_run'):
sys.stdout.write(u'Dry run - Doing nothing! *crossingfingers*\n')
else:
deleteable_snippets.delete()

View file

@ -0,0 +1,48 @@
import datetime
import difflib
import random
import mptt
from django.db import models
from django.db.models import permalink
from django.utils.translation import ugettext_lazy as _
from pastebin.apps.dpaste.highlight import LEXER_DEFAULT, pygmentize
t = 'abcdefghijkmnopqrstuvwwxyzABCDEFGHIJKLOMNOPQRSTUVWXYZ1234567890'
def generate_secret_id(length=4):
return ''.join([random.choice(t) for i in range(length)])
class Snippet(models.Model):
secret_id = models.CharField(_(u'Secret ID'), max_length=4, blank=True)
title = models.CharField(_(u'Title'), max_length=120, blank=True)
author = models.CharField(_(u'Author'), max_length=30, blank=True)
content = models.TextField(_(u'Content'), )
content_highlighted = models.TextField(_(u'Highlighted Content'), blank=True)
lexer = models.CharField(_(u'Lexer'), max_length=30, default=LEXER_DEFAULT)
published = models.DateTimeField(_(u'Published'), blank=True)
expires = models.DateTimeField(_(u'Expires'), blank=True, help_text='asdf')
parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
class Meta:
ordering = ('-published',)
def get_linecount(self):
return len(self.content.splitlines())
def content_splitted(self):
return self.content_highlighted.splitlines()
def save(self, *args, **kwargs):
if not self.pk:
self.published = datetime.datetime.now()
self.secret_id = generate_secret_id()
self.content_highlighted = pygmentize(self.content, self.lexer)
super(Snippet, self).save(*args, **kwargs)
@permalink
def get_absolute_url(self):
return ('snippet_details', (self.secret_id,))
def __unicode__(self):
return '%s' % self.secret_id
mptt.register(Snippet, order_insertion_by=['content'])

View file

@ -0,0 +1 @@
{% extends "base.html" %}

View file

@ -0,0 +1,174 @@
{% extends "dpaste/base.html" %}
{% load mptt_tags %}
{% load i18n %}
{% block extrahead %}
{% if request.session.userprefs %}
<style type="text/css" media="all">
.code{
{# FIXME: Thats stupid #}
{% ifnotequal request.session.userprefs.font_family "None" %}font-family: {{ request.session.userprefs.font_family }} !important;{% endifnotequal %}
{% ifnotequal request.session.userprefs.font_size "None" %}font-size: {{ request.session.userprefs.font_size }}px !important;{% endifnotequal %}
{% ifnotequal request.session.userprefs.line_height "None" %}line-height: {{ request.session.userprefs.line_height }}px !important;{% endifnotequal %}
}
</style>
{% endif %}
{% endblock %}
{% block title %}{% trans "Snippet" %} #{{ snippet.pk }}{% endblock %}
{% block headline %}
<h1>
{% trans "Snippet" %} #{{ snippet.pk }}
{% if snippet.parent_id %}
{% blocktrans with snippet.parent.get_absolute_url as parent_url and snippet.parent.id as parent_id %}(Copy of <a href="{{ parent_url }}">snippet #{{ parent_id }}</a>){% endblocktrans %}
{% endif %}
<span class="date">{{ snippet.published|date:_("DATETIME_FORMAT") }} ({% trans "UTC" %})</span>
</h1>
{% endblock %}
{% load dpaste_tags %}
{% block content %}
<div id="diff" style="display:none;">diff</div>
<div class="accordion">
<div class="snippet-options">
<abbr title="{% trans "Time to life" %}">TTL:</abbr> {{ snippet.expires|timeuntil }}
&mdash;
{% if snippet.pk|in_list:request.session.snippet_list %}
<a onclick="return confirm('{% trans "Really delete this snippet?" %}')" href="{% url snippet_delete snippet.secret_id %}">Delete now!</a>
&mdash;
{% endif %}
<a id="toggleWordwrap" href="#">{% trans "Wordwrap" %}</a>
</div>
<h2>
{% if snippet.title %}{{ snippet.title }}{% else %} {% trans "Snippet" %} #{{ snippet.id}}{% endif %}
<span>{% if snippet.author %}{% blocktrans with snippet.author as author %}by {{ author }}{% endblocktrans %}{% endif %}</span>
</h2>
<div class="container">
<div class="snippet">
<table>
<tr>
<th><pre class="code">{% for l in lines %}<a href="#l{{ forloop.counter }}" id="l{{ forloop.counter }}">{{ forloop.counter }}</a>{% endfor %}</pre></th>
<td><pre class="code">{% for line in snippet.content_splitted %}<div class="line" id="l{{ forloop.counter }}">{% if line %}{{ line|safe }}{% else %}&nbsp;{% endif %}</div>{% endfor %}</pre></td>
</tr>
</table>
</div>
</div>
<h2>{% trans "Write an answer" %} &rarr;</h2>
<div class="container" style="display: none;">
{% include "dpaste/snippet_form.html" %}
</div>
</div>
{% endblock %}
{% block sidebar %}
<h2>{% trans "History" %}</h2>
<form method="get" id="diffform" action="{% url snippet_diff %}">
{% csrf_token %}
<div class="tree">
{% for tree_item,structure in tree|tree_info %}
{% if structure.new_level %}<ul><li>{% else %}</li><li>{% endif %}
<div>
<span class="diff">
<input type="radio" name="a" value="{{ tree_item.id }}" {% ifequal tree_item.id snippet.parent_id %}checked="checked"{% endifequal %}/>
<input type="radio" name="b" value="{{ tree_item.id }}" {% ifequal snippet tree_item %}checked="checked"{% endifequal %}/>
</span>
{% ifequal snippet tree_item %}
<strong>{% trans "Snippet" %} #{{ tree_item.id }}</strong>
{% else %}
<a href="{{ tree_item.get_absolute_url }}">{% trans "Snippet" %} #{{ tree_item.id }}</a>
{% endifequal %}
</div>
{% for level in structure.closed_levels %}</li></ul>{% endfor %}
{% endfor %}
<div class="submit">
<input type="submit" value="{% trans "Compare" %}"/>
</div>
</div>
</form>
<h2>{% trans "Options" %}</h2>
<p><a href="{% url snippet_details_raw snippet.secret_id %}">{% trans "View raw" %}</a></p>
{% endblock %}
{% block script_footer %}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.5.2/jquery-ui.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
curLine = document.location.hash;
if(curLine.substring(0,2) == '#l'){
$('div.snippet div.line'+curLine).addClass('marked');
}
$("div.accordion").accordion({
autoHeight: false,
header: 'h2',
animation: 'bounceslide',
duration: 2000,
});
/**
* Diff Ajax Call
*/
$("form#diffform").submit(function() {
$.get("{% url snippet_diff %}", {
a: $("input[name=a]:checked").val(),
b: $("input[name=b]:checked").val()
}, function(data){
$('#diff').html(data).slideDown('fast');
});
return false;
});
/**
* Wordwrap
*/
$('#toggleWordwrap').toggle(
function(){
$('div.snippet pre.code').css('white-space', 'pre-wrap');
return false;
},
function(){
$('div.snippet pre.code').css('white-space', 'pre');
return false;
}
);
/**
* Line Highlighting
*/
$('div.snippet th a').each(function(i){
$(this).click(function(){
var j = $(this).text();
$('div.snippet div.line.marked').removeClass('marked');
$('div.snippet div.line#l'+j).toggleClass('marked');
});
});
{% if request.session.userprefs.display_all_lexer %}
/**
* Lexer Guessing
*/
$('#guess_lexer_btn').click(function(){
$.getJSON('{% url snippet_guess_lexer %}',
{'codestring': $('#id_content').val()},
function(data){
if(data.lexer == "unknown"){
$('#guess_lexer_btn').css('color', 'red');
}else{
$('#id_lexer').val(data.lexer);
$('#guess_lexer_btn').css('color', 'inherit');
}
});
});
{% endif %}
});
</script>
{% endblock %}

View file

@ -0,0 +1 @@
{{ snippet.content|safe }}

View file

@ -0,0 +1,13 @@
{% load i18n %}
<h2>
<span style="float:right;">(<a href="#" onclick="$('#diff').slideUp('fast'); return false;">{% trans "Close" %}</a>)</span>
{% blocktrans with fileA.get_absolute_url as filea_url and fileB.get_absolute_url as fileb_url and fileA.id as filea_id and fileB.id as fileb_id %}
Diff between
<a href="{{ filea_url }}">Snippet #{{ filea_id }}</a>
and
<a href="{{ fileb_url }}">Snippet #{{ fileb_id }}</a>
{% endblocktrans %}
</h2>
<pre class="code">{{ difftext|safe }}</pre>

View file

@ -0,0 +1,19 @@
{% load i18n %}
<form method="post" action="." class="snippetform">
{% csrf_token %}
<ol>
{% for field in snippet_form %}
<li>
{{ field.errors }}
{{ field.label_tag }}
{{ field }}
{% if request.session.userprefs.display_all_lexer %}
{% ifequal field.name "lexer" %}
<input type="button" value="{% trans "Guess lexer" %}" id="guess_lexer_btn"/>
{% endifequal %}
{% endif %}
</li>
{% endfor %}
<li class="submit"><input type="submit" value="{% trans "Paste it" %}"/></li>
</ol>
</form>

View file

@ -0,0 +1,26 @@
{% extends "dpaste/base.html" %}
{% load i18n %}
{% block title %}{% trans "Snippet" %} #{{ snippet.pk }}{% endblock %}
{% block headline %}
<h1>{% blocktrans %}Your latest {{ snippets_max }} snippets{% endblocktrans %}</h1>
{% endblock %}
{% block content %}
{% if snippet_list %}
{% for snippet in snippet_list %}
<h2>
<a href="{{ snippet.get_absolute_url }}">{% trans "Snippet" %} #{{ snippet.pk }}</a>
~ {{ snippet.published|date:_("DATETIME_FORMAT") }}
</h2>
<p style="color: #555; margin: 8px 0 20px 0;">{{ snippet.content|truncatewords:40 }}</p>
{% endfor %}
{% else %}
<p>{% trans "No snippets available." %}</p>
{% endif %}
<div class="hint">
{% trans "DATA_STORED_IN_A_COOKIE_HINT" %}
</div>
{% endblock %}

View file

@ -0,0 +1,39 @@
{% extends "dpaste/base.html" %}
{% load i18n %}
{% block title %}{% trans "New snippet" %}{% endblock %}
{% block headline %}<h1>{% trans "Paste a new snippet" %}</h1>{% endblock %}
{% block content %}
<h2>{% trans "New snippet" %}</h2>
{% include "dpaste/snippet_form.html" %}
{% endblock %}
{% block sidebar %}
<h2>{% trans "DPASTE_HOMEPAGE_TITLE" %}</h2>
<p>{% trans "DPASTE_HOMEPAGE_DESCRIPTION" %}</p>
{% endblock %}
{% block script_footer %}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
{% if request.session.userprefs.display_all_lexer %}
$('#guess_lexer_btn').click(function(){
$.getJSON('{% url snippet_guess_lexer %}',
{'codestring': $('#id_content').val()},
function(data){
if(data.lexer == "unknown"){
$('#guess_lexer_btn').css('color', 'red');
}else{
$('#id_lexer').val(data.lexer);
$('#guess_lexer_btn').css('color', 'inherit');
}
});
});
{% endif %}
});
</script>
{% endblock %}

View file

@ -0,0 +1,28 @@
{% extends "dpaste/base.html" %}
{% load i18n %}
{% block headline %}
<h1>{% trans "User Settings" %}</h1>
{% endblock %}
{% block content %}
{% if settings_saved %}
<div class="success">
{% trans "USER_PREFS_SAVED_SUCCESSFULLY" %}
</div>
{% endif %}
<h2>{% trans "User Settings" %}</h2>
<form class="snippetform" method="post" action=".">
{% csrf_token %}
<ol>
{{ settings_form.as_ul }}
<li class="submit"><input type="submit" value="{% trans "Save settings" %}"/></li>
</ol>
</form>
<div class="hint">
{% trans "DATA_STORED_IN_A_COOKIE_HINT" %}
</div>
{% endblock %}

View file

@ -0,0 +1 @@
__version__ = '0.1'

View file

@ -0,0 +1,7 @@
from django.template import Library
register = Library()
@register.filter
def in_list(value,arg):
return value in arg

View file

@ -0,0 +1,14 @@
from django.conf.urls.defaults import patterns, url
from django.conf import settings
urlpatterns = patterns('pastebin.apps.dpaste.views',
url(r'^$', 'snippet_new', name='snippet_new'),
url(r'^guess/$', 'guess_lexer', name='snippet_guess_lexer'),
url(r'^diff/$', 'snippet_diff', name='snippet_diff'),
url(r'^your-latest/$', 'snippet_userlist', name='snippet_userlist'),
url(r'^your-settings/$', 'userprefs', name='snippet_userprefs'),
url(r'^(?P<snippet_id>[a-zA-Z0-9]{4})/$', 'snippet_details', name='snippet_details'),
url(r'^(?P<snippet_id>[a-zA-Z0-9]{4})/delete/$', 'snippet_delete', name='snippet_delete'),
url(r'^(?P<snippet_id>[a-zA-Z0-9]{4})/raw/$', 'snippet_details', {'template_name': 'dpaste/snippet_details_raw.html', 'is_raw': True}, name='snippet_details_raw'),
)

View file

@ -0,0 +1,165 @@
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404
from django.template.context import RequestContext
from django.http import HttpResponseRedirect, HttpResponseBadRequest, HttpResponse, HttpResponseForbidden
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import ugettext_lazy as _
from pastebin.apps.dpaste.forms import SnippetForm, UserSettingsForm
from pastebin.apps.dpaste.models import Snippet
from pastebin.apps.dpaste.highlight import pygmentize, guess_code_lexer
from django.core.urlresolvers import reverse
from django.utils import simplejson
import difflib
def snippet_new(request, template_name='dpaste/snippet_new.html'):
if request.method == "POST":
snippet_form = SnippetForm(data=request.POST, request=request)
if snippet_form.is_valid():
request, new_snippet = snippet_form.save()
return HttpResponseRedirect(new_snippet.get_absolute_url())
else:
snippet_form = SnippetForm(request=request)
template_context = {
'snippet_form': snippet_form,
}
return render_to_response(
template_name,
template_context,
RequestContext(request)
)
def snippet_details(request, snippet_id, template_name='dpaste/snippet_details.html', is_raw=False):
snippet = get_object_or_404(Snippet, secret_id=snippet_id)
tree = snippet.get_root()
tree = tree.get_descendants(include_self=True)
new_snippet_initial = {
'content': snippet.content,
'lexer': snippet.lexer,
}
if request.method == "POST":
snippet_form = SnippetForm(data=request.POST, request=request, initial=new_snippet_initial)
if snippet_form.is_valid():
request, new_snippet = snippet_form.save(parent=snippet)
return HttpResponseRedirect(new_snippet.get_absolute_url())
else:
snippet_form = SnippetForm(initial=new_snippet_initial, request=request)
template_context = {
'snippet_form': snippet_form,
'snippet': snippet,
'lines': range(snippet.get_linecount()),
'tree': tree,
}
response = render_to_response(
template_name,
template_context,
RequestContext(request)
)
if is_raw:
response['Content-Type'] = 'text/plain'
return response
else:
return response
def snippet_delete(request, snippet_id):
snippet = get_object_or_404(Snippet, secret_id=snippet_id)
try:
snippet_list = request.session['snippet_list']
except KeyError:
return HttpResponseForbidden('You have no recent snippet list, cookie error?')
if not snippet.pk in snippet_list:
return HttpResponseForbidden('That\'s not your snippet, sucka!')
snippet.delete()
return HttpResponseRedirect(reverse('snippet_new'))
def snippet_userlist(request, template_name='dpaste/snippet_list.html'):
try:
snippet_list = get_list_or_404(Snippet, pk__in=request.session.get('snippet_list', None))
except ValueError:
snippet_list = None
template_context = {
'snippets_max': getattr(settings, 'MAX_SNIPPETS_PER_USER', 10),
'snippet_list': snippet_list,
}
return render_to_response(
template_name,
template_context,
RequestContext(request)
)
def userprefs(request, template_name='dpaste/userprefs.html'):
if request.method == 'POST':
settings_form = UserSettingsForm(request.POST, initial=request.session.get('userprefs', None))
if settings_form.is_valid():
request.session['userprefs'] = settings_form.cleaned_data
settings_saved = True
else:
settings_form = UserSettingsForm(initial=request.session.get('userprefs', None))
settings_saved = False
template_context = {
'settings_form': settings_form,
'settings_saved': settings_saved,
}
return render_to_response(
template_name,
template_context,
RequestContext(request)
)
def snippet_diff(request, template_name='dpaste/snippet_diff.html'):
if request.GET.get('a').isdigit() and request.GET.get('b').isdigit():
try:
fileA = Snippet.objects.get(pk=int(request.GET.get('a')))
fileB = Snippet.objects.get(pk=int(request.GET.get('b')))
except ObjectDoesNotExist:
return HttpResponseBadRequest(u'Selected file(s) does not exist.')
else:
return HttpResponseBadRequest(u'You must select two snippets.')
if fileA.content != fileB.content:
d = difflib.unified_diff(
fileA.content.splitlines(),
fileB.content.splitlines(),
'Original',
'Current',
lineterm=''
)
difftext = '\n'.join(d)
difftext = pygmentize(difftext, 'diff')
else:
difftext = _(u'No changes were made between this two files.')
template_context = {
'difftext': difftext,
'fileA': fileA,
'fileB': fileB,
}
return render_to_response(
template_name,
template_context,
RequestContext(request)
)
def guess_lexer(request):
code_string = request.GET.get('codestring', False)
response = simplejson.dumps({'lexer': guess_code_lexer(code_string)})
return HttpResponse(response)

40
pastebin/bin/manage.py Executable file
View file

@ -0,0 +1,40 @@
#!/usr/bin/env python
import os
import sys
from django import get_version
from django.core.management import execute_from_command_line, LaxOptionParser
from django.core.management.base import BaseCommand
# Work out the project module name and root directory, assuming that this file
# is located at [project]/bin/manage.py
PROJECT_DIR, PROJECT_MODULE_NAME = os.path.split(
os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
# Check that the project module can be imported.
try:
__import__(PROJECT_MODULE_NAME)
except ImportError:
# Couldn't import the project, place it on the Python path and try again.
sys.path.append(PROJECT_DIR)
try:
__import__(PROJECT_MODULE_NAME)
except ImportError:
sys.stderr.write("Error: Can't import the \"%s\" project module." %
PROJECT_MODULE_NAME)
sys.exit(1)
def has_settings_option():
parser = LaxOptionParser(usage="%prog subcommand [options] [args]",
version=get_version(),
option_list=BaseCommand.option_list)
try:
options = parser.parse_args(sys.argv[:])[0]
except:
return False # Ignore any option errors at this point.
return bool(options.settings)
if not has_settings_option() and not 'DJANGO_SETTINGS_MODULE' in os.environ:
settings_module = '%s.conf.local.settings' % PROJECT_MODULE_NAME
os.environ['DJANGO_SETTINGS_MODULE'] = settings_module
execute_from_command_line()

View file

View file

View file

View file

@ -0,0 +1,9 @@
from django.conf.urls.defaults import patterns, include
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^admin/doc/', include('django.contrib.admindocs.urls')),
(r'^admin/', include(admin.site.urls)),
)

View file

View file

@ -0,0 +1,17 @@
from pastebin.conf.settings import *
DEBUG = True
TEMPLATE_DEBUG = DEBUG
ROOT_URLCONF = 'pastebin.conf.dev.urls'
MEDIA_ROOT = os.path.join(VAR_ROOT, 'uploads')
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'pastebin',
# 'USER': 'dbuser',
# 'PASSWORD': 'dbpassword',
}
}

View file

@ -0,0 +1,9 @@
from django.conf.urls.defaults import *
from django.conf import settings
CONF_MODULE = '%s.conf' % settings.PROJECT_MODULE_NAME
urlpatterns = patterns('',
(r'', include('%s.urls' % CONF_MODULE)),
(r'', include('%s.common.urls.admin' % CONF_MODULE)),
)

105
pastebin/conf/settings.py Normal file
View file

@ -0,0 +1,105 @@
# Import global settings to make it easier to extend settings.
from django.conf.global_settings import *
#==============================================================================
# Generic Django project settings
#==============================================================================
DEBUG = False
TEMPLATE_DEBUG = DEBUG
# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
TIME_ZONE = 'America/Chicago'
USE_I18N = True
SITE_ID = 1
# Make this unique, and don't share it with anybody.
SECRET_KEY = ''
#==============================================================================
# I18N
#==============================================================================
USE_I18N = True
USE_L10N = False
LANGUAGE_CODE = 'en'
LANGUAGES = (
('en', 'English'),
)
#==============================================================================
# Calculation of directories relative to the module location
#==============================================================================
import os
import sys
import pastebin
PROJECT_DIR, PROJECT_MODULE_NAME = os.path.split(
os.path.dirname(os.path.realpath(pastebin.__file__))
)
PYTHON_BIN = os.path.dirname(sys.executable)
if os.path.exists(os.path.join(PYTHON_BIN, 'activate_this.py')):
# Assume that the presence of 'activate_this.py' in the python bin/
# directory means that we're running in a virtual environment. Set the
# variable root to $VIRTUALENV/var.
VAR_ROOT = os.path.join(os.path.dirname(PYTHON_BIN), 'var')
if not os.path.exists(VAR_ROOT):
os.mkdir(VAR_ROOT)
else:
# Set the variable root to the local configuration location (which is
# ignored by the repository).
VAR_ROOT = os.path.join(PROJECT_DIR, PROJECT_MODULE_NAME, 'conf', 'local')
#==============================================================================
# Static files
#==============================================================================
STATIC_ROOT = os.path.join(VAR_ROOT, 'static')
#==============================================================================
# Project URLS and media settings
#==============================================================================
MEDIA_URL = '/uploads/'
STATIC_URL = '/static/'
ADMIN_MEDIA_PREFIX = '/static/admin/'
MEDIA_ROOT = os.path.join(VAR_ROOT, 'uploads')
ROOT_URLCONF = 'pastebin.conf.urls'
LOGIN_URL = '/accounts/login/'
LOGOUT_URL = '/accounts/logout/'
LOGIN_REDIRECT_URL = '/'
#==============================================================================
# Templates
#==============================================================================
TEMPLATE_DIRS = (
os.path.join(PROJECT_DIR, PROJECT_MODULE_NAME, 'templates'),
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.admin',
'django.contrib.staticfiles',
'mptt',
'piston',
'pastebin',
'pastebin.apps.dpaste',
)
#==============================================================================
# App specific settings
#==============================================================================
# How many recent snippets to save for every user? IDs of this snippets are
# stored in the user session.
MAX_SNIPPETS_PER_USER = 25

View file

View file

@ -0,0 +1,16 @@
from pastebin.conf.settings import *
DEBUG = False
TEMPLATE_DEBUG = DEBUG
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory:',
}
}
ROOT_URLCONF = 'pastebin.conf.test.urls'
INSTALLED_APPS += ('django_nose',)
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'

View file

@ -0,0 +1,9 @@
from django.conf.urls.defaults import *
from django.conf import settings
CONF_MODULE = '%s.conf' % settings.PROJECT_MODULE_NAME
urlpatterns = patterns('',
(r'', include('%s.urls' % CONF_MODULE)),
(r'', include('%s.common.urls.admin' % CONF_MODULE)),
)

26
pastebin/conf/urls.py Normal file
View file

@ -0,0 +1,26 @@
from django.conf.urls.defaults import *
from django.conf import settings
from django.contrib import admin
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from piston.resource import Resource
from pastebin.apps.api.handlers import SnippetHandler
admin.autodiscover()
snippet_resource = Resource(handler=SnippetHandler)
urlpatterns = patterns('',
(r'^', include('pastebin.apps.dpaste.urls')),
# Static
url(r'^about/$', 'django.views.generic.simple.direct_to_template', {'template': 'about.html'}, name='about'),
# Bla
(r'^i18n/', include('django.conf.urls.i18n')),
(r'^admin/(.*)', include(admin.site.urls)),
# API
url(r'^api/(?P<secret_id>[^/]+)/$', snippet_resource),
url(r'^api/$', snippet_resource),
)
urlpatterns += staticfiles_urlpatterns()

Binary file not shown.

View file

@ -0,0 +1,253 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: dpaste\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-05-29 17:48-0500\n"
"PO-Revision-Date: 2011-05-30 00:56+0100\n"
"Last-Translator: Martin Mahner <martin@mahner.org>\n"
"Language-Team: de <martin@mahner.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"X-Poedit-Language: German\n"
"X-Poedit-Country: GERMANY\n"
"X-Poedit-SourceCharset: utf-8\n"
#: apps/dpaste/forms.py:13
msgid "In one hour"
msgstr "In einer Stunde"
#: apps/dpaste/forms.py:14
msgid "In one week"
msgstr "In einer Woche"
#: apps/dpaste/forms.py:15
msgid "In one month"
msgstr "In einem Monat"
#: apps/dpaste/forms.py:16
msgid "Save forever"
msgstr "Für immer"
#: apps/dpaste/forms.py:26
#: apps/dpaste/models.py:20
msgid "Lexer"
msgstr "Syntax"
#: apps/dpaste/forms.py:32
#: apps/dpaste/models.py:22
msgid "Expires"
msgstr "Verfällt"
#: apps/dpaste/forms.py:87
#: apps/dpaste/forms.py:96
msgid "Default"
msgstr "Standard"
#: apps/dpaste/forms.py:100
msgid "Default Name"
msgstr "Standardname"
#: apps/dpaste/forms.py:102
msgid "Display all lexer"
msgstr "Alle Syntax anzeigen"
#: apps/dpaste/forms.py:105
msgid "This also enables the super secret 'guess lexer' function."
msgstr "Dies aktiviert auch die super geheime 'Syntax erraten' Funktion."
#: apps/dpaste/forms.py:107
msgid "Font Family"
msgstr "Schriftart"
#: apps/dpaste/forms.py:108
msgid "Font Size"
msgstr "Schriftgröße"
#: apps/dpaste/forms.py:109
msgid "Line Height"
msgstr "Zeilenhöhe"
#: apps/dpaste/models.py:15
msgid "Secret ID"
msgstr "Geheime ID"
#: apps/dpaste/models.py:16
msgid "Title"
msgstr "Titel"
#: apps/dpaste/models.py:17
msgid "Author"
msgstr "Autor"
#: apps/dpaste/models.py:18
msgid "Content"
msgstr "Inhalt"
#: apps/dpaste/models.py:19
msgid "Highlighted Content"
msgstr "Gefärbter Inhalt"
#: apps/dpaste/models.py:21
msgid "Published"
msgstr "Veröffentlicht"
#: apps/dpaste/views.py:148
msgid "No changes were made between this two files."
msgstr "Zwischen diesen Dateien wurden keine Änderungen vorgenommen."
#: apps/dpaste/templates/dpaste/snippet_details.html:18
#: apps/dpaste/templates/dpaste/snippet_details.html:21
#: apps/dpaste/templates/dpaste/snippet_details.html:44
#: apps/dpaste/templates/dpaste/snippet_details.html:82
#: apps/dpaste/templates/dpaste/snippet_details.html:84
#: apps/dpaste/templates/dpaste/snippet_list.html:4
#: apps/dpaste/templates/dpaste/snippet_list.html:13
msgid "Snippet"
msgstr "Snippet"
#: apps/dpaste/templates/dpaste/snippet_details.html:23
#, python-format
msgid "(Copy of <a href=\"%(parent_url)s\">snippet #%(parent_id)s</a>)"
msgstr "(Kopie von <a href=\"%(parent_url)s\">Snippet #%(parent_id)s</a>)"
#: apps/dpaste/templates/dpaste/snippet_details.html:25
#: apps/dpaste/templates/dpaste/snippet_list.html:14
msgid "DATETIME_FORMAT"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_details.html:25
msgid "UTC"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_details.html:35
msgid "Time to life"
msgstr "Time to live"
#: apps/dpaste/templates/dpaste/snippet_details.html:38
msgid "Really delete this snippet?"
msgstr "Dieses Snippet wirklich löschen?"
#: apps/dpaste/templates/dpaste/snippet_details.html:41
msgid "Wordwrap"
msgstr "Wordwrap"
#: apps/dpaste/templates/dpaste/snippet_details.html:45
#, python-format
msgid "by %(author)s"
msgstr "von %(author)s"
#: apps/dpaste/templates/dpaste/snippet_details.html:59
msgid "Write an answer"
msgstr "Eine Antwort schreiben"
#: apps/dpaste/templates/dpaste/snippet_details.html:69
msgid "History"
msgstr "Geschichte"
#: apps/dpaste/templates/dpaste/snippet_details.html:90
msgid "Compare"
msgstr "Vergleichen"
#: apps/dpaste/templates/dpaste/snippet_details.html:95
msgid "Options"
msgstr "Einstellungen"
#: apps/dpaste/templates/dpaste/snippet_details.html:96
msgid "View raw"
msgstr "Rohformat"
#: apps/dpaste/templates/dpaste/snippet_diff.html:4
msgid "Close"
msgstr "Schließen"
#: apps/dpaste/templates/dpaste/snippet_diff.html:5
#, python-format
msgid ""
"\n"
" Diff between\n"
" <a href=\"%(filea_url)s\">Snippet #%(filea_id)s</a>\n"
" and\n"
" <a href=\"%(fileb_url)s\">Snippet #%(fileb_id)s</a>\n"
" "
msgstr ""
"\n"
" Diff zwischen\n"
" <a href=\"%(filea_url)s\">Snippet #%(filea_id)s</a>\n"
" und\n"
" <a href=\"%(fileb_url)s\">Snippet #%(fileb_id)s</a>\n"
" "
#: apps/dpaste/templates/dpaste/snippet_form.html:12
msgid "Guess lexer"
msgstr "Syntax erraten"
#: apps/dpaste/templates/dpaste/snippet_form.html:17
msgid "Paste it"
msgstr "Paste it"
#: apps/dpaste/templates/dpaste/snippet_list.html:6
#, python-format
msgid "Your latest %(snippets_max)s snippets"
msgstr "Deine letzten %(snippets_max)s Snippets"
#: apps/dpaste/templates/dpaste/snippet_list.html:19
msgid "No snippets available."
msgstr "Keine Snippets verfügbar."
#: apps/dpaste/templates/dpaste/snippet_list.html:24
#: apps/dpaste/templates/dpaste/userprefs.html:26
msgid "DATA_STORED_IN_A_COOKIE_HINT"
msgstr "Deine Daten werden in einem Cookie gespeichert."
#: apps/dpaste/templates/dpaste/snippet_new.html:4
#: apps/dpaste/templates/dpaste/snippet_new.html:8
#: templates/base.html:9
#: templates/base.html.py:16
msgid "New snippet"
msgstr "Neues Snippet"
#: apps/dpaste/templates/dpaste/snippet_new.html:5
msgid "Paste a new snippet"
msgstr "Paste ein neues Snippet"
#: apps/dpaste/templates/dpaste/snippet_new.html:14
msgid "DPASTE_HOMEPAGE_TITLE"
msgstr " "
#: apps/dpaste/templates/dpaste/snippet_new.html:15
msgid "DPASTE_HOMEPAGE_DESCRIPTION"
msgstr " "
#: apps/dpaste/templates/dpaste/userprefs.html:5
#: apps/dpaste/templates/dpaste/userprefs.html:15
msgid "User Settings"
msgstr "Einstellungen"
#: apps/dpaste/templates/dpaste/userprefs.html:11
msgid "USER_PREFS_SAVED_SUCCESSFULLY"
msgstr "Deine Einstellungen wurden gespeichert."
#: apps/dpaste/templates/dpaste/userprefs.html:21
msgid "Save settings"
msgstr "Einstellungen speichern"
#: templates/base.html:38
msgid "Recent snippets"
msgstr "Letzte Snippets"
#: templates/base.html:39
msgid "Settings"
msgstr "Einstellungen"
#: templates/base.html:40
#, fuzzy
msgid "About"
msgstr "Über"

Binary file not shown.

View file

@ -0,0 +1,246 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: dpaste\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-05-29 17:48-0500\n"
"PO-Revision-Date: 2011-05-30 01:01+0100\n"
"Last-Translator: Martin Mahner <martin@mahner.org>\n"
"Language-Team: en <martin@mahner.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"X-Poedit-Language: German\n"
"X-Poedit-Country: GERMANY\n"
"X-Poedit-SourceCharset: utf-8\n"
#: apps/dpaste/forms.py:13
msgid "In one hour"
msgstr ""
#: apps/dpaste/forms.py:14
msgid "In one week"
msgstr ""
#: apps/dpaste/forms.py:15
msgid "In one month"
msgstr ""
#: apps/dpaste/forms.py:16
msgid "Save forever"
msgstr ""
#: apps/dpaste/forms.py:26
#: apps/dpaste/models.py:20
msgid "Lexer"
msgstr ""
#: apps/dpaste/forms.py:32
#: apps/dpaste/models.py:22
msgid "Expires"
msgstr ""
#: apps/dpaste/forms.py:87
#: apps/dpaste/forms.py:96
msgid "Default"
msgstr ""
#: apps/dpaste/forms.py:100
msgid "Default Name"
msgstr ""
#: apps/dpaste/forms.py:102
msgid "Display all lexer"
msgstr ""
#: apps/dpaste/forms.py:105
msgid "This also enables the super secret 'guess lexer' function."
msgstr ""
#: apps/dpaste/forms.py:107
msgid "Font Family"
msgstr ""
#: apps/dpaste/forms.py:108
msgid "Font Size"
msgstr ""
#: apps/dpaste/forms.py:109
msgid "Line Height"
msgstr ""
#: apps/dpaste/models.py:15
msgid "Secret ID"
msgstr ""
#: apps/dpaste/models.py:16
msgid "Title"
msgstr ""
#: apps/dpaste/models.py:17
msgid "Author"
msgstr ""
#: apps/dpaste/models.py:18
msgid "Content"
msgstr ""
#: apps/dpaste/models.py:19
msgid "Highlighted Content"
msgstr ""
#: apps/dpaste/models.py:21
msgid "Published"
msgstr ""
#: apps/dpaste/views.py:148
msgid "No changes were made between this two files."
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_details.html:18
#: apps/dpaste/templates/dpaste/snippet_details.html:21
#: apps/dpaste/templates/dpaste/snippet_details.html:44
#: apps/dpaste/templates/dpaste/snippet_details.html:82
#: apps/dpaste/templates/dpaste/snippet_details.html:84
#: apps/dpaste/templates/dpaste/snippet_list.html:4
#: apps/dpaste/templates/dpaste/snippet_list.html:13
msgid "Snippet"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_details.html:23
#, python-format
msgid "(Copy of <a href=\"%(parent_url)s\">snippet #%(parent_id)s</a>)"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_details.html:25
#: apps/dpaste/templates/dpaste/snippet_list.html:14
msgid "DATETIME_FORMAT"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_details.html:25
msgid "UTC"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_details.html:35
msgid "Time to life"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_details.html:38
msgid "Really delete this snippet?"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_details.html:41
msgid "Wordwrap"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_details.html:45
#, python-format
msgid "by %(author)s"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_details.html:59
msgid "Write an answer"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_details.html:69
msgid "History"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_details.html:90
msgid "Compare"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_details.html:95
msgid "Options"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_details.html:96
msgid "View raw"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_diff.html:4
msgid "Close"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_diff.html:5
#, python-format
msgid ""
"\n"
" Diff between\n"
" <a href=\"%(filea_url)s\">Snippet #%(filea_id)s</a>\n"
" and\n"
" <a href=\"%(fileb_url)s\">Snippet #%(fileb_id)s</a>\n"
" "
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_form.html:12
msgid "Guess lexer"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_form.html:17
msgid "Paste it"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_list.html:6
#, python-format
msgid "Your latest %(snippets_max)s snippets"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_list.html:19
msgid "No snippets available."
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_list.html:24
#: apps/dpaste/templates/dpaste/userprefs.html:26
msgid "DATA_STORED_IN_A_COOKIE_HINT"
msgstr "Your data is stored in a cookie."
#: apps/dpaste/templates/dpaste/snippet_new.html:4
#: apps/dpaste/templates/dpaste/snippet_new.html:8
#: templates/base.html:9
#: templates/base.html.py:16
msgid "New snippet"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_new.html:5
msgid "Paste a new snippet"
msgstr ""
#: apps/dpaste/templates/dpaste/snippet_new.html:14
msgid "DPASTE_HOMEPAGE_TITLE"
msgstr "dpaste.de"
#: apps/dpaste/templates/dpaste/snippet_new.html:15
msgid "DPASTE_HOMEPAGE_DESCRIPTION"
msgstr ""
#: apps/dpaste/templates/dpaste/userprefs.html:5
#: apps/dpaste/templates/dpaste/userprefs.html:15
msgid "User Settings"
msgstr ""
#: apps/dpaste/templates/dpaste/userprefs.html:11
msgid "USER_PREFS_SAVED_SUCCESSFULLY"
msgstr "Your settings were saved."
#: apps/dpaste/templates/dpaste/userprefs.html:21
msgid "Save settings"
msgstr ""
#: templates/base.html:38
msgid "Recent snippets"
msgstr ""
#: templates/base.html:39
msgid "Settings"
msgstr ""
#: templates/base.html:40
msgid "About"
msgstr ""

0
pastebin/static/.gitignore vendored Normal file
View file

384
pastebin/static/theme.css Normal file
View file

@ -0,0 +1,384 @@
body{
margin: 0;
padding: 0;
font-family: Helvetica, Arial, sans-serif;
font-size: 13px;
}
a:link,
a:visited{
color: #3D813A;
text-decoration: none;
}
a:hover{
color: #52AA4D;
text-decoration: underline;
}
hr.clear{
clear: both;
border: none;
margin: 0;
padding: 0;
height: 0;
overflow: hidden;
font-size: 0;
line-height: 0;
visibility: hidden;
}
div.success{
background-color: green;
color: White;
margin: 10px 0;
padding: 10px 20px;
}
div.success a{
color: White;
text-decoration: underline;
}
div.hint{
padding: 5px 20px;
background-color: #F7F1C9;
margin: 20px 0;
}
/* *******************************************
* Header
******************************************* */
#header{
background-color: #D6F1B7;
border-bottom: 1px solid #C6EB9A;
padding: 10px 20px;
font-size: 14px;
}
#header span.new_snippet{
float: right;
}
#header h1{
margin: 0;
color: #555555;
font-size: 14px;
}
#header h1 span.date{
color: gray;
color: #666;
padding-left: 15px;
}
#header a:link,
#header a:visited{
text-decoration: none;
color: #333;
font-weight: Bold;
}
#header a:hover{
text-decoration: underline;
}
/* *******************************************
* Content
******************************************* */
#content{
padding: 0 20px;
margin: 0;
width: 70%;
float: left;
}
#content h2{
font-size: 1.3em;
line-height: 1.6em;
}
#content h2 span{
font-weight: normal;
}
div.accordion h2{
cursor: pointer;
color: #3D813A;
}
div.accordion h2:hover{
text-decoration: underline;
}
/* *******************************************
* Snippet table
******************************************* */
div.snippet{
overflow: auto;
}
div.snippet-options{
float: right;
font-size: 0.9em;
margin-top: 5px;
}
div.snippet table{
margin: 0;
padding: 0;
border-collapse: collapse;
}
div.snippet table td{
margin: 0;
padding: 0 4px;
vertical-align: top;
}
div.snippet table th{
border-right: 1px solid #ccc;
vertical-align: top;
}
div.snippet table th a{
display: block;
text-decoration: none;
color: #888;
text-align: right;
padding: 0 4px 0 18px;
}
/* *******************************************
* Form
******************************************* */
form.snippetform ol{
margin: 0;
padding: 0;
list-style: none;
}
form.snippetform ol li{
margin: 0;
padding: 5px 10px;
border-bottom: 1px solid #EEE;
clear: left;
}
form.snippetform label{
width: 125px;
float: left;
}
form.snippetform #id_content{
width: 80%;
height: 290px;
font-family: monospace;
font-size: 0.9em;
}
form.snippetform #id_author,
form.snippetform #id_title{
width: 60%;
opacity: 0.7;
}
form.snippetform li.submit input{
margin-left: 125px;
}
form.snippetform ul.errorlist,
form.snippetform ul.errorlist li{
margin: 0;
padding: 0;
list-style: none;
color: #c00;
font-weight: bold;
border: none;
}
form.snippetform ul.errorlist li{
padding: 10px 0 5px 0;
}
/* *******************************************
* History + Tree
******************************************* */
#sidebar{
padding: 0 20px 0 10px;
margin: 20px 0 0 0;
float: right;
width: 20%;
overflow: auto;
border-left: 1px solid #DDD;
}
#sidebar h2{
font-size: 1em;
border-bottom: 1px solid #DDD;
color: #888;
margin-top: 0;
text-transform: uppercase;
width: auto !important;
}
div.tree{
margin: 0 0 15px 0;
line-height: 1.8em;
}
div.tree ul,
div.tree ul li{
margin: 0;
padding: 0;
list-style: none;
}
div.tree ul li{
clear: both;
}
div.tree ul li div{
border-bottom: 1px solid #EEE;
}
div.tree span.diff{
float: right;
}
div.tree strong{
color: #111;
font-weight: normal;
}
div.tree ul li li{
padding-left: 0;
margin-left: 15px;
color: #ccc;
list-style: circle;
}
div.tree div.submit{
margin: 8px 0 0 0;
text-align: right;
}
div.tree div.submit input{
font-size: 0.8em;
}
/* *******************************************
* Footer
******************************************* */
#footer{
position: fixed;
right: 1em;
bottom: 1em;
}
#footer form.setlang{
display: inline;
padding-right: 15px;
}
#footer form.setlang input,
#footer form.setlang select{
font-size: 0.8em;
}
#footer a:link,
#footer a:visited{
background-color: #D6F1B7;
color: #555;
text-decoration: none;
padding: 3px 6px;
}
#footer a:hover,
#footer a:active{
background-color: #D6F1B7;
color: #000;
text-decoration: none;
}
/* *******************************************
* Pygments
******************************************* */
pre.code {
font-family: "Bitstream Vera Sans Mono", Monaco, Consolas, monospace;
font-size: 12px;
line-height: 17px;
margin: 0;
padding: 0;
}
pre.code div.line:hover{
background-color: #FFFFE6;
}
pre.code div.line.marked,
pre.code div.line.marked *{
background-color: #BAE688 !important;
}
.code .c { color: #999988; font-style: italic } /* Comment */
/* .code .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.code .k { font-weight: bold } /* Keyword */
.code .o { font-weight: bold } /* Operator */
.code .cm { color: #999988; font-style: italic } /* Comment.Multiline */
.code .cp { color: #999999; font-weight: bold } /* Comment..codeproc */
.code .c1 { color: #999988; font-style: italic } /* Comment.Single */
.code .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.code .ge { font-style: italic } /* Generic.Emph */
.code .gr { color: #aa0000 } /* Generic.Error */
.code .gh { color: #999999 } /* Generic.Heading */
.code .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.code .go { color: #888888 } /* Generic.Output */
.code .gp { color: #555555 } /* Generic.Prompt */
.code .gs { font-weight: bold } /* Generic.Strong */
.code .gu { color: #aaaaaa } /* Generic.Subheading */
.code .gt { color: #aa0000 } /* Generic.Traceback */
.code .kc { font-weight: bold } /* Keyword.Constant */
.code .kd { font-weight: bold } /* Keyword.Declaration */
.code .kp { font-weight: bold } /* Keyword.Pseudo */
.code .kr { font-weight: bold } /* Keyword.Reserved */
.code .kt { color: #445588; font-weight: bold } /* Keyword.Type */
.code .m { color: #009999 } /* Literal.Number */
.code .s { color: #bb8844 } /* Literal.String */
.code .na { color: #008080 } /* Name.Attribute */
.code .nb { color: #999999 } /* Name.Builtin */
.code .nc { color: #445588; font-weight: bold } /* Name.Class */
.code .no { color: #ff99ff } /* Name.Constant */
.code .ni { color: #800080 } /* Name.Entity */
.code .ne { color: #990000; font-weight: bold } /* Name.Exception */
.code .nf { color: #990000; font-weight: bold } /* Name.Function */
.code .nn { color: #555555 } /* Name.Namespace */
.code .nt { color: #000080 } /* Name.Tag */
.code .nv { color: purple } /* Name.Variable */
.code .ow { font-weight: bold } /* Operator.Word */
.code .mf { color: #009999 } /* Literal.Number.Float */
.code .mh { color: #009999 } /* Literal.Number.Hex */
.code .mi { color: #009999 } /* Literal.Number.Integer */
.code .mo { color: #009999 } /* Literal.Number.Oct */
.code .sb { color: #bb8844 } /* Literal.String.Backtick */
.code .sc { color: #bb8844 } /* Literal.String.Char */
.code .sd { color: #bb8844 } /* Literal.String.Doc */
.code .s2 { color: #bb8844 } /* Literal.String.Double */
.code .se { color: #bb8844 } /* Literal.String.Escape */
.code .sh { color: #bb8844 } /* Literal.String.Heredoc */
.code .si { color: #bb8844 } /* Literal.String.Interpol */
.code .sx { color: #bb8844 } /* Literal.String.Other */
.code .sr { color: #808000 } /* Literal.String.Regex */
.code .s1 { color: #bb8844 } /* Literal.String.Single */
.code .ss { color: #bb8844 } /* Literal.String.Symbol */
.code .bp { color: #999999 } /* Name.Builtin.Pseudo */
.code .vc { color: #ff99ff } /* Name.Variable.Class */
.code .vg { color: #ff99ff } /* Name.Variable.Global */
.code .vi { color: #ff99ff } /* Name.Variable.Instance */
.code .il { color: #009999 } /* Literal.Number.Integer.Long */

View file

@ -0,0 +1,9 @@
{% extends "base.html" %}
{% block headline %}
<h1>404 Not found</h1>
{% endblock %}
{% block content %}
<p>Snippet you have searched is not available (anymore).</p>
{% endblock %}

View file

@ -0,0 +1,9 @@
{% extends "base.html" %}
{% block headline %}
<h1>500 Internal Server Error</h1>
{% endblock %}
{% block content %}
<p>Sorry, there was an error with your request. My fault!</p>
{% endblock %}

View file

@ -0,0 +1,64 @@
{% extends "base.html" %}
{% block headline %}
<h1>About dpaste.de</h1>
{% endblock %}
{% block content %}
<p>Description follows...</p>
<h2>API</h2>
<pre>#!/usr/bin/env python
import urllib
import urllib2
import sys
def paste_code():
request = urllib2.Request(
'http://dpaste.de/api/',
urllib.urlencode([('content', ''.join(sys.stdin.readlines()))]),
)
response = urllib2.urlopen(request)
print response.read()[1:-1]
if __name__ == '__main__':
paste_code()</pre>
<p>Save this script in <code>/usr/local/bin/dpaste</code> and <code>chmod +x ..filepath</code>.</p>
<p>Usage: <code>cat foo.txt | dpaste</code></p>
{% endblock %}
{% block sidebar %}
<h2>Imprint</h2>
<p>
<strong>Address</strong>
</p>
<p>
Martin Mahner<br/>
Lauterbacher Str. 4<br/>
DE-18581 Putbus<br/>
Germany
</p>
<p>
<strong>Jabber/E-Mail:</strong>
</p>
<p>
<a href="mailto:martin@mahner.org">martin@mahner.org</a>
</p>
<p>
<strong>Phone:</strong>
</p>
<p>
+49 38301 890(770+8)<sup>1</sup><br/><br/>
<small style="font-size:0.9em;"><sup>1</sup> Yes, that's math!</small>
</p>
{% endblock %}

View file

@ -0,0 +1,62 @@
{% load i18n %}
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>dpaste.de: {% block title %}{% trans "New snippet" %}{% endblock %}</title>
<link rel="stylesheet" media="screen, projection" href="{{ STATIC_URL }}theme.css"/>
{% block extrahead %}{% endblock %}
</head>
<body>
<div id="header">
<span class="new_snippet"><a href="{% url snippet_new %}">{% trans "New snippet" %} &rarr;</a></span>
{% block headline %}{% endblock %}
</div>
<div id="sidebar">
{% block sidebar %}{% endblock %}
</div>
<div id="content">
{% block content %}{% endblock %}
</div>
<div id="footer">
{% comment %}
<form action="/i18n/setlang/" method="post" class="setlang">
{% csrf_token %}
<select name="language">
{% for lang in LANGUAGES %}
<option {% ifequal LANGUAGE_CODE lang.0 %}selected="selected"{% endifequal %} value="{{ lang.0 }}">{{ lang.1 }}</option>
{% endfor %}
</select>
<input type="submit" value="Go" />
</form>
{% endcomment %}
<a href="{% url snippet_userlist %}">{% trans "Recent snippets" %}</a>
<a href="{% url snippet_userprefs %}">{% trans "Settings" %}</a>
<a href="{% url about %}">{% trans "About" %}</a>
</div>
{% block script_footer %}{% endblock %}
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-90910-20']);
_gaq.push(['_setDomainName', '.dpaste.de']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</body>
</html>

4
requirements.pip Normal file
View file

@ -0,0 +1,4 @@
django==1.3
mptt==0.4.2
piston==0.2.2
pygments==1.4

View file

@ -0,0 +1,16 @@
<VirtualHost *:9000>
ServerName pastebin.dev.lincolnloop.com
ServerAdmin webmaster@dev.lincolnloop.com
ErrorLog /var/log/apache2/pastebin.dev.lincolnloop.com.log
WSGIDaemonProcess pastebin user=www-data inactivity-timeout=600
WSGIProcessGroup pastebin
WSGIScriptAlias / /opt/webapps/pastebin.dev.lincolnloop.com/etc/apache/django.wsgi
<Directory /opt/webapps/pastebin.dev.lincolnloop.com/etc/apache>
Order deny,allow
Allow from all
</Directory>
</VirtualHost>

View file

@ -0,0 +1,13 @@
import os, sys
import site
site.addsitedir('/opt/webapps/pastebin/lib/python2.5/site-packages')
sys.stdout = sys.stderr
os.environ['DJANGO_SETTINGS_MODULE'] = 'pastebin.conf.local.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

View file

@ -0,0 +1,31 @@
upstream pastebin {
server pastebin.dev.lincolnloop.com:9000;
}
server {
listen 80;
server_name www.pastebin.dev.lincolnloop.com;
rewrite ^/(.*) http://pastebin.dev.lincolnloop.com/$1 permanent;
}
server {
listen 80;
server_name pastebin.dev.lincolnloop.com;
root /var/www/pastebin.dev.lincolnloop.com/;
access_log /var/log/nginx/pastebin.dev.lincolnloop.com.access.log;
location / {
if (-f $request_filename/index.html) {
rewrite (.*) $1/index.html break;
}
if (!-f $request_filename) {
proxy_pass http://pastebin;
}
include /etc/nginx/proxy-setup.inc.conf;
}
# Serve up apache log on dev host. Useful for debugging.
location /apache.log {
alias /var/log/apache2/pastebin.dev.lincolnloop.com.log;
}
}

9
setup.py Normal file
View file

@ -0,0 +1,9 @@
#!/usr/bin/env python
from setuptools import setup, find_packages
setup(name='pastebin',
version='0.1',
packages=find_packages(),
package_data={'pastebin': ['bin/*.*', 'static/*.*', 'templates/*.*']},
exclude_package_data={'pastebin': ['bin/*.pyc']},
scripts=['pastebin/bin/manage.py'])