Port to Python 3 and removed legacy code

This commit is contained in:
Jannis Leidel 2016-09-20 10:31:18 +02:00
parent 1e2a4f0dff
commit d7ecd93cce
20 changed files with 168 additions and 248 deletions

6
.coveragerc Normal file
View file

@ -0,0 +1,6 @@
[run]
source = dbtemplates
branch = 1
[report]
omit = *tests*,*migrations*

1
.gitignore vendored
View file

@ -4,7 +4,6 @@ MANIFEST
build
dist
*.egg-info
example/example.db
docs/_build
.tox/
*.egg/

View file

@ -1,34 +1,32 @@
language: python
python: 3.5
sudo: false
cache: pip
language: python
python:
- 2.6
- 2.7
install:
- pip install -e .
- pip install -r requirements/tests.txt Django==$DJANGO
before_script:
- flake8 dbtemplates --ignore=E501 --exclude=migrations
script:
- coverage run --branch --source=dbtemplates `which django-admin.py` test dbtemplates
- coverage report --omit="dbtemplates/test*,dbtemplates/migrations*"
env:
global:
- DJANGO_SETTINGS_MODULE=dbtemplates.test_settings
matrix:
- DJANGO="1.4.5 importlib"
- DJANGO="1.5.1 importlib"
- DJANGO=1.7.8
- DJANGO=1.8.11
- DJANGO=1.9.4
matrix:
exclude:
- python: 2.6
env: DJANGO=1.7.8
- python: 2.6
env: DJANGO=1.8.11
- python: 2.6
env: DJANGO=1.9.4
- TOXENV=flake8-py27
- TOXENV=flake8-py35
- TOXENV=readme-py27
- TOXENV=py27-dj18
- TOXENV=py27-dj19
- TOXENV=py27-dj110
- TOXENV=py27-djmaster
- TOXENV=py34-dj18
- TOXENV=py34-dj19
- TOXENV=py34-dj110
- TOXENV=py34-djmaster
- TOXENV=py35-dj18
- TOXENV=py35-dj19
- TOXENV=py35-dj110
- TOXENV=py35-djmaster
- TOXENV=pypy-dj18
- TOXENV=pypy-dj19
- TOXENV=pypy-dj110
- TOXENV=pypy-djmaster
install:
- pip install tox codecov
script: tox -v
after_success:
- codecov
deploy:
provider: pypi
user: jazzband
@ -39,4 +37,4 @@ deploy:
tags: true
repo: jazzband/django-dbtemplates
python: "2.7"
condition: "$DJANGO = 1.8.11"
condition: "$TOXENV = py27-dj110"

View file

@ -1,4 +1,4 @@
Copyright (c) 2007-2012, Jannis Leidel and contributors
Copyright (c) 2007-2016, Jannis Leidel and contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without

View file

@ -1,2 +1 @@
# following PEP 386
__version__ = "1.3.2"
__version__ = "2.0"

View file

@ -1,17 +1,12 @@
import django
from django.contrib.sites.models import Site
from django.db import router
from django.template import TemplateDoesNotExist
from django.template.loaders.base import Loader as BaseLoader
from dbtemplates.models import Template
from dbtemplates.utils.cache import (cache, get_cache_key,
set_and_return, get_cache_notfound_key)
if django.VERSION[:2] >= (1, 8):
from django.template.loaders.base import Loader as BaseLoader
else:
from django.template.loader import BaseLoader # noqa
class Loader(BaseLoader):
"""

View file

@ -1,13 +1,13 @@
from django.core.management.base import CommandError, NoArgsCommand
from django.core.management.base import CommandError, BaseCommand
from dbtemplates.models import Template
from dbtemplates.utils.template import check_template_syntax
class Command(NoArgsCommand):
class Command(BaseCommand):
help = "Ensures templates stored in the database don't have syntax errors."
def handle_noargs(self, **options):
def handle(self, **options):
errors = []
for template in Template.objects.all():
valid, error = check_template_syntax(template)
@ -16,6 +16,4 @@ class Command(NoArgsCommand):
if errors:
raise CommandError(
'Some templates contained errors\n%s' % '\n'.join(errors))
# NOTE: printing instead of using self.stdout.write to maintain
# Django 1.2 compatibility
print('OK')
self.stdout.write('OK')

View file

@ -1,7 +1,5 @@
import sys
from optparse import make_option
from django.core.management.base import CommandError, NoArgsCommand
from django.core.management.base import CommandError, BaseCommand
from django.contrib.sites.models import Site
from dbtemplates.models import Template
@ -26,14 +24,15 @@ TEMPLATES = {
}
class Command(NoArgsCommand):
class Command(BaseCommand):
help = "Creates the default error templates as database template objects."
option_list = NoArgsCommand.option_list + (
make_option("-f", "--force", action="store_true", dest="force",
default=False,
help="overwrite existing database templates"),)
def handle_noargs(self, **options):
def add_arguments(self, parser):
parser.add_argument(
"-f", "--force", action="store_true", dest="force",
default=False, help="overwrite existing database templates")
def handle(self, **options):
force = options.get('force')
try:
site = Site.objects.get_current()

View file

@ -1,56 +1,54 @@
import os
import codecs
from optparse import make_option
from django import VERSION
from django.contrib.sites.models import Site
from django.core.management.base import CommandError, NoArgsCommand
from django.core.management.base import CommandError, BaseCommand
from django.template.utils import get_app_template_dirs
from django.template.loader import _engine_list
try:
from django.utils.six import input as raw_input
except ImportError:
pass
from dbtemplates.conf import settings
from dbtemplates.models import Template
ALWAYS_ASK, FILES_TO_DATABASE, DATABASE_TO_FILES = ('0', '1', '2')
DIRS = []
if VERSION[:2] < (1, 8):
from django.template.loaders.app_directories import app_template_dirs
DIRS = settings.TEMPLATE_DIRS
else:
from django.template.utils import get_app_template_dirs
from django.template.loader import _engine_list
for engine in _engine_list():
DIRS.extend(engine.dirs)
app_template_dirs = get_app_template_dirs('templates')
for engine in _engine_list():
DIRS.extend(engine.dirs)
app_template_dirs = get_app_template_dirs('templates')
class Command(NoArgsCommand):
class Command(BaseCommand):
help = "Syncs file system templates with the database bidirectionally."
option_list = NoArgsCommand.option_list + (
make_option("-e", "--ext",
dest="ext", action="store", default="html",
help="extension of the files you want to "
"sync with the database [default: %default]"),
make_option("-f", "--force",
action="store_true", dest="force", default=False,
help="overwrite existing database templates"),
make_option("-o", "--overwrite",
action="store", dest="overwrite", default='0',
help="'0' - ask always, '1' - overwrite database "
"templates from template files, '2' - overwrite "
"template files from database templates"),
make_option("-a", "--app-first",
action="store_true", dest="app_first", default=False,
help="look for templates in applications "
"directories before project templates"),
make_option("-d", "--delete",
action="store_true", dest="delete", default=False,
help="Delete templates after syncing"))
def handle_noargs(self, **options):
def add_arguments(self, parser):
parser.add_argument(
"-e", "--ext",
dest="ext", action="store", default="html",
help="extension of the files you want to "
"sync with the database [default: %default]")
parser.add_argument(
"-f", "--force",
action="store_true", dest="force", default=False,
help="overwrite existing database templates")
parser.add_argument(
"-o", "--overwrite",
action="store", dest="overwrite", default='0',
help="'0' - ask always, '1' - overwrite database "
"templates from template files, '2' - overwrite "
"template files from database templates")
parser.add_argument(
"-a", "--app-first",
action="store_true", dest="app_first", default=False,
help="look for templates in applications "
"directories before project templates")
parser.add_argument(
"-d", "--delete",
action="store_true", dest="delete", default=False,
help="Delete templates after syncing")
def handle(self, **options):
extension = options.get('ext')
force = options.get('force')
overwrite = options.get('overwrite')
@ -66,10 +64,6 @@ class Command(NoArgsCommand):
raise CommandError("Please make sure to have the sites contrib "
"app installed and setup with a site object")
if not type(settings.TEMPLATE_DIRS) in (tuple, list):
raise CommandError("Please make sure settings.TEMPLATE_DIRS is a "
"list or tuple.")
if app_first:
tpl_dirs = app_template_dirs + DIRS
else:

View file

@ -36,7 +36,7 @@ class Migration(migrations.Migration):
'verbose_name_plural': 'templates',
},
bases=(models.Model,),
managers = [
managers=[
('objects', django.db.models.manager.Manager()),
('on_site', django.contrib.sites.managers.CurrentSiteManager(
b'sites')),

View file

@ -9,12 +9,7 @@ from django.db import models
from django.db.models import signals
from django.template import TemplateDoesNotExist
from django.utils.translation import ugettext_lazy as _
try:
from django.utils.timezone import now
except ImportError:
from datetime import datetime
now = datetime.now
from django.utils.timezone import now
class Template(models.Model):

View file

@ -1,55 +0,0 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'Template'
db.create_table('django_template', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=100)),
('content', self.gf('django.db.models.fields.TextField')(blank=True)),
('creation_date', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
('last_changed', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
))
db.send_create_signal('dbtemplates', ['Template'])
# Adding M2M table for field sites on 'Template'
db.create_table('django_template_sites', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('template', models.ForeignKey(orm['dbtemplates.template'], null=False)),
('site', models.ForeignKey(orm['sites.site'], null=False))
))
db.create_unique('django_template_sites', ['template_id', 'site_id'])
def backwards(self, orm):
# Deleting model 'Template'
db.delete_table('django_template')
# Removing M2M table for field sites on 'Template'
db.delete_table('django_template_sites')
models = {
'dbtemplates.template': {
'Meta': {'ordering': "('name',)", 'object_name': 'Template', 'db_table': "'django_template'"},
'content': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'creation_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_changed': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'sites': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['sites.Site']", 'symmetrical': 'False'})
},
'sites.site': {
'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
}
}
complete_apps = ['dbtemplates']

View file

@ -1,34 +0,0 @@
# encoding: utf-8
from south.db import db
from south.v2 import SchemaMigration
class Migration(SchemaMigration):
def forwards(self, orm):
# Removing unique constraint on 'Template', fields ['name']
db.delete_unique('django_template', ['name'])
def backwards(self, orm):
# Adding unique constraint on 'Template', fields ['name']
db.create_unique('django_template', ['name'])
models = {
'dbtemplates.template': {
'Meta': {'ordering': "('name',)", 'object_name': 'Template', 'db_table': "'django_template'"},
'content': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'creation_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_changed': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'sites': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['sites.Site']", 'symmetrical': 'False'})
},
'sites.site': {
'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
}
}
complete_apps = ['dbtemplates']

View file

@ -99,17 +99,17 @@ class DbTemplatesTestCase(TestCase):
self.assertEqual(admin_base_template, template.content)
def test_sync_templates(self):
old_template_dirs = settings.TEMPLATE_DIRS
old_template_dirs = settings.TEMPLATES[0].get('DIRS', [])
temp_template_dir = tempfile.mkdtemp('dbtemplates')
temp_template_path = os.path.join(temp_template_dir, 'temp_test.html')
temp_template = codecs.open(temp_template_path, 'w')
try:
temp_template.write('temp test')
settings.TEMPLATE_DIRS = (temp_template_dir,)
settings.TEMPLATES[0]['DIRS'] = (temp_template_dir,)
# these works well if is not settings patched at runtime
# for supporting django < 1.7 tests we must patch dirs in runtime
from dbtemplates.management.commands import sync_templates
sync_templates.DIRS = settings.TEMPLATE_DIRS
sync_templates.DIRS = settings.TEMPLATES[0]['DIRS']
self.assertFalse(
Template.objects.filter(name='temp_test.html').exists())
@ -133,7 +133,7 @@ class DbTemplatesTestCase(TestCase):
Template.objects.filter(name='temp_test.html').exists())
finally:
temp_template.close()
settings.TEMPLATE_DIRS = old_template_dirs
settings.TEMPLATES[0]['DIRS'] = old_template_dirs
shutil.rmtree(temp_template_dir)
def test_get_cache(self):

View file

@ -1,6 +1,3 @@
import django
DBTEMPLATES_CACHE_BACKEND = 'dummy://'
DATABASE_ENGINE = 'sqlite3'
@ -37,5 +34,11 @@ TEMPLATE_LOADERS = (
'dbtemplates.loader.Loader',
)
if django.VERSION[:2] <= (1, 6):
TEST_RUNNER = 'discover_runner.DiscoverRunner'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'OPTIONS': {
'loaders': TEMPLATE_LOADERS,
}
},
]

View file

@ -9,16 +9,10 @@ def get_cache_backend():
"""
Compatibilty wrapper for getting Django's cache backend instance
"""
try:
from django.core.cache import _create_cache
except ImportError:
# Django < 1.7
from django.core.cache import get_cache as _get_cache
return _get_cache(settings.DBTEMPLATES_CACHE_BACKEND)
from django.core.cache import _create_cache
cache = _create_cache(settings.DBTEMPLATES_CACHE_BACKEND)
# Some caches -- python-memcached in particular -- need to do a cleanup at the
# end of a request cycle. If not implemented in a particular backend
# Some caches -- python-memcached in particular -- need to do a cleanup at
# the end of a request cycle. If not implemented in a particular backend
# cache.close is a no-op
signals.request_finished.connect(cache.close)
return cache

View file

@ -1,29 +1,14 @@
from django import VERSION
from django.template import (Template, TemplateDoesNotExist,
TemplateSyntaxError)
from importlib import import_module
def get_loaders():
if VERSION[:2] < (1, 8):
from django.template.loader import template_source_loaders
if template_source_loaders is None:
try:
from django.template.loader import find_template as finder
except ImportError:
from django.template.loader import find_template_source as finder # noqa
try:
source, name = finder('test')
except TemplateDoesNotExist:
pass
from django.template.loader import template_source_loaders
return template_source_loaders or []
else:
from django.template.loader import _engine_list
loaders = []
for engine in _engine_list():
loaders.extend(engine.engine.template_loaders)
return loaders
from django.template.loader import _engine_list
loaders = []
for engine in _engine_list():
loaders.extend(engine.engine.template_loaders)
return loaders
def get_template_source(name):
@ -45,15 +30,6 @@ def get_template_source(name):
pass
except TemplateDoesNotExist:
pass
if source is None and VERSION[:2] < (1, 2):
# Django supported template source extraction still :/
try:
from django.template.loader import find_template_source
template, origin = find_template_source(name, None)
if not hasattr(template, 'render'):
return template
except (ImportError, TemplateDoesNotExist):
pass
return None

View file

@ -1,22 +1,28 @@
import ast
import os
import re
import codecs
from setuptools import setup, find_packages
class VersionFinder(ast.NodeVisitor):
def __init__(self):
self.version = None
def visit_Assign(self, node):
if node.targets[0].id == '__version__':
self.version = node.value.s
def read(*parts):
filename = os.path.join(os.path.dirname(__file__), *parts)
with codecs.open(filename, encoding='utf-8') as fp:
return fp.read()
def find_version(*file_paths):
version_file = read(*file_paths)
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
version_file, re.M)
if version_match:
return version_match.group(1)
raise RuntimeError("Unable to find version string.")
def find_version(*parts):
finder = VersionFinder()
finder.visit(ast.parse(read(*parts)))
return finder.version
setup(
@ -27,7 +33,7 @@ setup(
author='Jannis Leidel',
author_email='jannis@leidel.info',
url='https://django-dbtemplates.readthedocs.io/',
packages=find_packages(exclude=['example']),
packages=find_packages(),
zip_safe=False,
package_data={
'dbtemplates': [
@ -44,9 +50,10 @@ setup(
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.5',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Framework :: Django',
],
install_requires=['django-appconf >= 0.4'],

46
tox.ini Normal file
View file

@ -0,0 +1,46 @@
[tox]
skipsdist = True
usedevelop = True
minversion = 1.8
envlist =
flake8-py27,
flake8-py35,
readme-py27,
py{27,34,35,py}-dj{18,19,110,master}
[testenv]
basepython =
py27: python2.7
py34: python3.4
py35: python3.5
pypy: pypy
usedevelop = true
setenv =
DJANGO_SETTINGS_MODULE = dbtemplates.test_settings
deps =
-rrequirements/tests.txt
dj18: https://github.com/django/django/archive/stable/1.8.x.tar.gz#egg=django
dj19: https://github.com/django/django/archive/stable/1.9.x.tar.gz#egg=django
dj110: https://github.com/django/django/archive/stable/1.10.x.tar.gz#egg=django
djmaster: https://github.com/django/django/archive/master.tar.gz#egg=django
commands =
python --version
coverage run {envbindir}/django-admin.py test -v2 {posargs:dbtemplates}
coverage report
[testenv:readme-py27]
commands = python setup.py check -r -s
deps = readme_renderer
[testenv:flake8-py27]
commands = flake8 dbtemplates
deps = flake8
[testenv:flake8-py35]
commands = flake8 dbtemplates
deps = flake8
[flake8]
exclude=.tox
ignore=E501,E127,E128,E124