diff --git a/.coverage.rc b/.coverage.rc index b7b5d0e..3742123 100644 --- a/.coverage.rc +++ b/.coverage.rc @@ -3,6 +3,7 @@ source = dpaste branch = True omit = dpaste/migrations/* + dpaste/south_migrations/* dpaste/tests/* dpaste/settings/* diff --git a/.travis.yml b/.travis.yml index 9d9b34e..1d148da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,25 +1,22 @@ +sudo: false + language: python python: - 2.7 - - 3.3 - 3.4 env: - - DJANGO=1.4.16 - - DJANGO=1.6.8 - - DJANGO=1.7.1 + - DJANGO=1.4.21 + - DJANGO=1.7.9 + - DJANGO=1.8.3 matrix: exclude: - - python: 3.3 - env: DJANGO=1.4.16 - - python: 3.3 - env: DJANGO=1.6.8 - python: 3.4 - env: DJANGO=1.4.16 + env: DJANGO=1.4.21 - python: 3.4 - env: DJANGO=1.6.8 + env: DJANGO=1.7.9 branches: only: @@ -27,9 +24,8 @@ branches: - develop install: - - "pip install coverage==3.7" - "pip install Django==$DJANGO" - "pip install -e ." script: - coverage run --rcfile=.coverage.rc runtests.py + python runtests.py diff --git a/CHANGELOG b/CHANGELOG index 83e352b..c36390d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,16 +1,21 @@ Changelog ========= +2.10 (...) +---------------- +* tbd -2.9 (DEV) +2.9 (2015-08-12) ---------------- * Full Django 1.7 support * Full Django 1.8 support * New Django migrations, with fallback to South migrations if South is - installed. -* Added i18n support and several languages + installed. If you want to switch from South to native Django migrations, + and have an existing databsae, fake the initial migrations: + `manage.py migrate --fake-initial` +* Added full i18n support and several languages * More settings can be overrridden, like the jQuery URL, site name and wether you want to enable Gthub Gist. * Ships a middleware that blocks anonymous proxies and TOR nodes. Not enabled diff --git a/README.rst b/README.rst index 1cd4f4c..74a4af8 100644 --- a/README.rst +++ b/README.rst @@ -4,10 +4,6 @@ dpaste .. image:: https://travis-ci.org/bartTC/dpaste.png?branch=master :target: https://travis-ci.org/bartTC/dpaste -.. image:: https://coveralls.io/repos/bartTC/dpaste/badge.png?branch=master - :target: https://coveralls.io/r/bartTC/dpaste?branch=master -.. image:: https://api.flattr.com/button/flattr-badge-large.png - :target: https://flattr.com/submit/auto?user_id=bartTC&url=https%3A%2F%2Fgithub.com%2FbartTC%2Fdpaste dpaste is a Django based pastebin. It's intended to run separately but its also possible to be installed into an existing Django project like a regular app. diff --git a/docs/integration.rst b/docs/integration.rst index acaa4b6..287be49 100644 --- a/docs/integration.rst +++ b/docs/integration.rst @@ -10,7 +10,7 @@ necessary dependencies of dpaste as well:: pip install dpaste -Add ``dpaste`` and (preferred) ``south`` to your ``INSTALLED_APPS``:: +Add ``dpaste`` and ``mptt`` to your ``INSTALLED_APPS``:: INSTALLED_APPS = ( 'django.contrib.sessions', @@ -19,10 +19,9 @@ Add ``dpaste`` and (preferred) ``south`` to your ``INSTALLED_APPS``:: 'mptt', 'dpaste', - # 'south', (supported) ) -Add ``dpaste`` and if you want the ``dpaste_api`` to your urlpatterns:: +Add ``dpaste`` — and if you want — the ``dpaste_api`` to your urlpatterns:: urlpatterns = patterns('', # ... @@ -31,7 +30,7 @@ Add ``dpaste`` and if you want the ``dpaste_api`` to your urlpatterns:: url(r'pastebin/api/', include('dpaste.urls.dpaste_api')), ) -Finally just ``syncdb`` or if you use South, migrate:: +Finally just migrate the database schema:: manage.py migrate dpaste diff --git a/dpaste/middleware.py b/dpaste/middleware.py index c221240..d152c08 100644 --- a/dpaste/middleware.py +++ b/dpaste/middleware.py @@ -6,7 +6,8 @@ tor_bl = ( '{remote_addr}.{server_port}.{server_ip}' '.ip-port.exitlist.torproject.org') open_proxy_bl = ('{remote_addr}.dnsbl.proxybl.org') -rev_ip = lambda ip: '.'.join(reversed(ip.split('.'))) + +rev_ip = lambda ip: '.'.join(reversed(ip.split('.'))) # pragma: no cover response = """

Access denied

It appears you're requesting this page from an open proxy or @@ -15,7 +16,7 @@ statutory violation related posts in the past.

If you think this is wrong, file a bug on Github please.

""" -def in_blacklist(request, bl, ip=None): +def in_blacklist(request, bl, ip=None): # pragma: no cover ip = ip or request.META['REMOTE_ADDR'] try: server_ip = socket.gethostbyname(request.META['SERVER_NAME']) @@ -37,15 +38,13 @@ def in_blacklist(request, bl, ip=None): return lookup == '127.0.0.2' -class SuspiciousIPMiddleware(object): +class SuspiciousIPMiddleware(object): # pragma: no cover def process_request(self, request): - def check_tor(): if not hasattr(request, '_is_tor_exit_node'): request._is_tor_exit_node = in_blacklist(request, tor_bl) return request._is_tor_exit_node - request.is_tor_exit_node = check_tor def check_open_proxy(): @@ -53,13 +52,11 @@ class SuspiciousIPMiddleware(object): request._is_open_proxy = in_blacklist( request, open_proxy_bl) return request._is_open_proxy - request.is_open_proxy = check_open_proxy def check_suspicious(): return request.is_tor_exit_node() or request.is_open_proxy() request.is_suspicious = check_suspicious - if request.method == 'POST' and request.is_suspicious(): return HttpResponseBadRequest(response) diff --git a/dpaste/settings/__init__.py b/dpaste/settings/__init__.py index 488aee4..e69de29 100644 --- a/dpaste/settings/__init__.py +++ b/dpaste/settings/__init__.py @@ -1,151 +0,0 @@ -# Import global settings to make it easier to extend settings. -from django.conf.global_settings import * - - -#============================================================================== -# Calculation of directories relative to the module location -#============================================================================== -import os -import sys -import dpaste - -PROJECT_DIR, PROJECT_MODULE_NAME = os.path.split( - os.path.dirname(os.path.realpath(dpaste.__file__)) -) - -# Set the variable root to $VIRTUALENV/var. -PYTHON_BIN = os.path.dirname(sys.executable) - -VAR_ROOT = os.path.join(os.path.dirname(PYTHON_BIN), 'var') -if not os.path.exists(VAR_ROOT): - os.mkdir(VAR_ROOT) - -#============================================================================== -# 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 = 'UTC' -SITE_ID = 1 - -# Make this unique, and don't share it with anybody. -SECRET_KEY = '' - -ALLOWED_HOSTS = ( - 'dpaste.de', - 'www.dpaste.de', - 'dpaste.org', - 'www.dpaste.org', - '127.0.0.1', -) - -SECRET_KEY = 'CHANGE_ME' - -#============================================================================== -# I18N -#============================================================================== - -USE_I18N = True -USE_L10N = False - -LANGUAGE_CODE = 'en' -LANGUAGES = ( - ('en', 'English'), - ('de', 'German'), - ('es', 'Spanish'), - ('pt-br', 'Portugese (Brasil)'), -) - -LOCALE_PATHS = ( - os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'locale')), -) - -#============================================================================== -# Static files -#============================================================================== - -STATIC_ROOT = os.path.join(VAR_ROOT, 'static') - -#============================================================================== -# Project URLS and media settings -#============================================================================== - -STATIC_URL = '/static/' -ADMIN_MEDIA_PREFIX = '/static/admin/' - -ROOT_URLCONF = 'dpaste.urls' - -LOGIN_URL = '/accounts/login/' -LOGOUT_URL = '/accounts/logout/' -LOGIN_REDIRECT_URL = '/' - -#============================================================================== -# Templates -#============================================================================== - -MIDDLEWARE_CLASSES = ( - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.locale.LocaleMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', -) - -TEMPLATE_CONTEXT_PROCESSORS += ( - 'django.core.context_processors.request', - 'django.core.context_processors.i18n', -) - -INSTALLED_APPS = ( - 'django.contrib.staticfiles', - 'django.contrib.sessions', - - 'mptt', - 'gunicorn', - 'dpaste', -) - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': 'dev.db', - 'USER': '', - 'PASSWORD': '', - } -} - -#============================================================================== -# 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 - -LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'filters': { - 'require_debug_false': { - '()': 'django.utils.log.RequireDebugFalse' - } - }, - 'handlers': { - 'mail_admins': { - 'level': 'ERROR', - 'filters': ['require_debug_false'], - 'class': 'django.utils.log.AdminEmailHandler' - } - }, - 'loggers': { - 'django.request': { - 'handlers': ['mail_admins'], - 'level': 'ERROR', - 'propagate': True, - }, - } -} diff --git a/dpaste/settings/base.py b/dpaste/settings/base.py new file mode 100644 index 0000000..488aee4 --- /dev/null +++ b/dpaste/settings/base.py @@ -0,0 +1,151 @@ +# Import global settings to make it easier to extend settings. +from django.conf.global_settings import * + + +#============================================================================== +# Calculation of directories relative to the module location +#============================================================================== +import os +import sys +import dpaste + +PROJECT_DIR, PROJECT_MODULE_NAME = os.path.split( + os.path.dirname(os.path.realpath(dpaste.__file__)) +) + +# Set the variable root to $VIRTUALENV/var. +PYTHON_BIN = os.path.dirname(sys.executable) + +VAR_ROOT = os.path.join(os.path.dirname(PYTHON_BIN), 'var') +if not os.path.exists(VAR_ROOT): + os.mkdir(VAR_ROOT) + +#============================================================================== +# 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 = 'UTC' +SITE_ID = 1 + +# Make this unique, and don't share it with anybody. +SECRET_KEY = '' + +ALLOWED_HOSTS = ( + 'dpaste.de', + 'www.dpaste.de', + 'dpaste.org', + 'www.dpaste.org', + '127.0.0.1', +) + +SECRET_KEY = 'CHANGE_ME' + +#============================================================================== +# I18N +#============================================================================== + +USE_I18N = True +USE_L10N = False + +LANGUAGE_CODE = 'en' +LANGUAGES = ( + ('en', 'English'), + ('de', 'German'), + ('es', 'Spanish'), + ('pt-br', 'Portugese (Brasil)'), +) + +LOCALE_PATHS = ( + os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'locale')), +) + +#============================================================================== +# Static files +#============================================================================== + +STATIC_ROOT = os.path.join(VAR_ROOT, 'static') + +#============================================================================== +# Project URLS and media settings +#============================================================================== + +STATIC_URL = '/static/' +ADMIN_MEDIA_PREFIX = '/static/admin/' + +ROOT_URLCONF = 'dpaste.urls' + +LOGIN_URL = '/accounts/login/' +LOGOUT_URL = '/accounts/logout/' +LOGIN_REDIRECT_URL = '/' + +#============================================================================== +# Templates +#============================================================================== + +MIDDLEWARE_CLASSES = ( + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.locale.LocaleMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +) + +TEMPLATE_CONTEXT_PROCESSORS += ( + 'django.core.context_processors.request', + 'django.core.context_processors.i18n', +) + +INSTALLED_APPS = ( + 'django.contrib.staticfiles', + 'django.contrib.sessions', + + 'mptt', + 'gunicorn', + 'dpaste', +) + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': 'dev.db', + 'USER': '', + 'PASSWORD': '', + } +} + +#============================================================================== +# 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 + +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'filters': { + 'require_debug_false': { + '()': 'django.utils.log.RequireDebugFalse' + } + }, + 'handlers': { + 'mail_admins': { + 'level': 'ERROR', + 'filters': ['require_debug_false'], + 'class': 'django.utils.log.AdminEmailHandler' + } + }, + 'loggers': { + 'django.request': { + 'handlers': ['mail_admins'], + 'level': 'ERROR', + 'propagate': True, + }, + } +} diff --git a/dpaste/settings/local.py.example b/dpaste/settings/local.py.example index 94010cf..b9e789a 100644 --- a/dpaste/settings/local.py.example +++ b/dpaste/settings/local.py.example @@ -1,4 +1,4 @@ -from .settings import * +from dpaste.settings.base import * DEBUG = True TEMPLATE_DEBUG = DEBUG diff --git a/requirements.txt b/requirements.txt index ebf2719..f2e70bf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,12 +11,12 @@ pygments==2.0.1 requests==2.5.1 # Testing -python-coveralls==2.4.3 -coverage==3.7.1 -tox==1.8.1 -docutils==0.12 -sphinx==1.2.3 +coverage +tox +docutils +sphinx sphinx_rtd_theme +mysql-python # Deployment specific django-redis==3.8.0 diff --git a/runtests.py b/runtests.py index 4ab82e3..06c67ce 100644 --- a/runtests.py +++ b/runtests.py @@ -3,30 +3,39 @@ import sys from django.conf import settings -if not settings.configured: - settings.configure( - DATABASES={ - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': 'dev.db', - } +SETTINGS = { + 'DATABASES': { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': 'dev.db', }, - INSTALLED_APPS=[ - 'django.contrib.sessions', - 'django.contrib.staticfiles', - 'mptt', - 'dpaste', - ], - MIDDLEWARE_CLASSES=( - 'django.contrib.sessions.middleware.SessionMiddleware', - ), - STATIC_ROOT='/tmp/dpaste_test_static/', - STATIC_URL='/static/', - ROOT_URLCONF='dpaste.urls', - ) + # 'default': { + # 'ENGINE': 'django.db.backends.mysql', + # 'NAME': 'dpaste', + # 'USER': 'root', + # 'PASSWORD': '', + # } + }, + 'INSTALLED_APPS': [ + 'django.contrib.sessions', + 'django.contrib.staticfiles', + 'mptt', + 'dpaste', + ], + 'MIDDLEWARE_CLASSES': ( + 'django.contrib.sessions.middleware.SessionMiddleware', + ), + 'STATIC_ROOT': '/tmp/dpaste_test_static/', + 'STATIC_URL': '/static/', + 'ROOT_URLCONF': 'dpaste.urls' +} def runtests(*test_args): - # New Django 1.7 app registry + # Setup settings + if not settings.configured: + settings.configure(**SETTINGS) + + # New Django 1.7 app registry setup try: from django import setup setup() @@ -40,7 +49,7 @@ def runtests(*test_args): from django.test.simple import DjangoTestSuiteRunner as TestRunner test_runner = TestRunner(verbosity=1) - failures = test_runner.run_tests(['dpaste', ]) + failures = test_runner.run_tests(['dpaste']) if failures: sys.exit(failures) diff --git a/runtests.sh b/runtests.sh new file mode 100644 index 0000000..c0cd54b --- /dev/null +++ b/runtests.sh @@ -0,0 +1,3 @@ +coverage run --rcfile=./.coverage.rc runtests.py && \ +coverage html --rcfile=./.coverage.rc + diff --git a/setup.py b/setup.py index 8acdd01..ae3eb0a 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ long_description = u'\n\n'.join(( setup( name='dpaste', - version='2.9', + version='2.10', description='dpaste is a Django based pastebin. It\'s intended to run ' 'separately but its also possible to be installed into an ' 'existing Django project like a regular app.', diff --git a/tox.ini b/tox.ini index 2e4ddf2..0ea4bdd 100644 --- a/tox.ini +++ b/tox.ini @@ -3,8 +3,8 @@ toxworkdir=/tmp/tox/dpaste envlist= py27-django-1.4, py27-django-1.7, - py27-django-latest, - py34-django-latest + py27-django-1.8, + py34-django-1.8 [testenv] commands= @@ -16,8 +16,8 @@ deps=django==1.4.21 [testenv:py27-django-1.7] deps=django==1.7.9 -[testenv:py27-django-latest] +[testenv:py27-django-1.8] deps=django==1.8.3 -[testenv:py34-django-latest] +[testenv:py34-django-1.8] deps=django==1.8.3