aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Law <simon.law@ecometrica.com>2012-08-23 16:34:40 -0400
committerSimon Law <simon.law@ecometrica.com>2012-08-23 16:34:40 -0400
commit0aa9bd310e5d66a76a109174f12885d0629861a3 (patch)
tree2dc6de394f24d7d68a5e3e932b07491a7c170dce
parentf90cff165af1ea1ede5cf4679e44735400cd649f (diff)
parent8d8d7ba99640366ac8304390b97a4f03842c1254 (diff)
downloaddjango-wkhtmltopdf-0aa9bd310e5d66a76a109174f12885d0629861a3.tar.gz
django-wkhtmltopdf-0aa9bd310e5d66a76a109174f12885d0629861a3.tar.bz2
django-wkhtmltopdf-0aa9bd310e5d66a76a109174f12885d0629861a3.zip
Merge with incuna
-rw-r--r--MANIFEST.in1
-rw-r--r--Makefile2
-rw-r--r--wkhtmltopdf/__init__.py3
-rw-r--r--wkhtmltopdf/_testproject/manage.py14
-rw-r--r--wkhtmltopdf/_testproject/requirements.txt1
-rw-r--r--wkhtmltopdf/_testproject/settings.py152
-rw-r--r--wkhtmltopdf/_testproject/urls.py17
-rw-r--r--wkhtmltopdf/test_settings.py16
-rw-r--r--wkhtmltopdf/tests/__init__.py (renamed from wkhtmltopdf/_testproject/__init__.py)0
-rw-r--r--wkhtmltopdf/tests/models.py0
-rw-r--r--wkhtmltopdf/tests/templates/footer.html (renamed from wkhtmltopdf/_testproject/templates/footer.html)0
-rw-r--r--wkhtmltopdf/tests/templates/sample.html (renamed from wkhtmltopdf/_testproject/templates/sample.html)0
-rw-r--r--wkhtmltopdf/tests/tests.py (renamed from wkhtmltopdf/tests.py)66
-rw-r--r--wkhtmltopdf/utils.py20
-rw-r--r--wkhtmltopdf/views.py45
15 files changed, 41 insertions, 296 deletions
diff --git a/MANIFEST.in b/MANIFEST.in
index 05c4bc6..df4289a 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,3 +1,2 @@
include README.rst
recursive-include * *.html
-
diff --git a/Makefile b/Makefile
index c5f9321..f7ad668 100644
--- a/Makefile
+++ b/Makefile
@@ -3,3 +3,5 @@ SHELL := /bin/bash
release:
python setup.py register sdist upload
+test:
+ PYTHONPATH=.:$$PYTHONPATH; django-admin.py test tests --settings=wkhtmltopdf.test_settings
diff --git a/wkhtmltopdf/__init__.py b/wkhtmltopdf/__init__.py
index 39b1413..7411417 100644
--- a/wkhtmltopdf/__init__.py
+++ b/wkhtmltopdf/__init__.py
@@ -3,5 +3,4 @@ if 'DJANGO_SETTINGS_MODULE' in os.environ:
from .utils import *
__author__ = 'Incuna Ltd'
-__version__ = '0.3'
-
+__version__ = '1.0'
diff --git a/wkhtmltopdf/_testproject/manage.py b/wkhtmltopdf/_testproject/manage.py
deleted file mode 100644
index 3e4eedc..0000000
--- a/wkhtmltopdf/_testproject/manage.py
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env python
-from django.core.management import execute_manager
-import imp
-try:
- imp.find_module('settings') # Assumed to be in the same directory.
-except ImportError:
- import sys
- sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__)
- sys.exit(1)
-
-import settings
-
-if __name__ == "__main__":
- execute_manager(settings)
diff --git a/wkhtmltopdf/_testproject/requirements.txt b/wkhtmltopdf/_testproject/requirements.txt
deleted file mode 100644
index 74c18fb..0000000
--- a/wkhtmltopdf/_testproject/requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-Django==1.3.1
diff --git a/wkhtmltopdf/_testproject/settings.py b/wkhtmltopdf/_testproject/settings.py
deleted file mode 100644
index 0454766..0000000
--- a/wkhtmltopdf/_testproject/settings.py
+++ /dev/null
@@ -1,152 +0,0 @@
-import os
-
-PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))
-
-# Django settings for testproject project.
-
-DEBUG = True
-TEMPLATE_DEBUG = DEBUG
-
-ADMINS = (
- # ('Your Name', 'your_email@example.com'),
-)
-
-MANAGERS = ADMINS
-
-DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
- 'NAME': 'test.db', # Or path to database file if using sqlite3.
- 'USER': '', # Not used with sqlite3.
- 'PASSWORD': '', # Not used with sqlite3.
- 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
- 'PORT': '', # Set to empty string for default. Not used with sqlite3.
- }
-}
-
-# Local time zone for this installation. Choices can be found here:
-# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
-# although not all choices may be available on all operating systems.
-# On Unix systems, a value of None will cause Django to use the same
-# timezone as the operating system.
-# If running in a Windows environment this must be set to the same as your
-# system time zone.
-TIME_ZONE = 'America/Chicago'
-
-# Language code for this installation. All choices can be found here:
-# http://www.i18nguy.com/unicode/language-identifiers.html
-LANGUAGE_CODE = 'en-us'
-
-SITE_ID = 1
-
-# If you set this to False, Django will make some optimizations so as not
-# to load the internationalization machinery.
-USE_I18N = True
-
-# If you set this to False, Django will not format dates, numbers and
-# calendars according to the current locale
-USE_L10N = True
-
-# Absolute filesystem path to the directory that will hold user-uploaded files.
-# Example: "/home/media/media.lawrence.com/media/"
-MEDIA_ROOT = ''
-
-# URL that handles the media served from MEDIA_ROOT. Make sure to use a
-# trailing slash.
-# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
-MEDIA_URL = ''
-
-# Absolute path to the directory static files should be collected to.
-# Don't put anything in this directory yourself; store your static files
-# in apps' "static/" subdirectories and in STATICFILES_DIRS.
-# Example: "/home/media/media.lawrence.com/static/"
-STATIC_ROOT = ''
-
-# URL prefix for static files.
-# Example: "http://media.lawrence.com/static/"
-STATIC_URL = '/static/'
-
-# URL prefix for admin static files -- CSS, JavaScript and images.
-# Make sure to use a trailing slash.
-# Examples: "http://foo.com/static/admin/", "/static/admin/".
-ADMIN_MEDIA_PREFIX = '/static/admin/'
-
-# Additional locations of static files
-STATICFILES_DIRS = (
- # Put strings here, like "/home/html/static" or "C:/www/django/static".
- # Always use forward slashes, even on Windows.
- # Don't forget to use absolute paths, not relative paths.
-)
-
-# List of finder classes that know how to find static files in
-# various locations.
-STATICFILES_FINDERS = (
- 'django.contrib.staticfiles.finders.FileSystemFinder',
- 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
-# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
-)
-
-# Make this unique, and don't share it with anybody.
-SECRET_KEY = '$)v)0$h)^c5!h2wms8*wn1c!7)7dp@qb87h7q)zecp2@$pnv=g'
-
-# List of callables that know how to import templates from various sources.
-TEMPLATE_LOADERS = (
- 'django.template.loaders.filesystem.Loader',
- 'django.template.loaders.app_directories.Loader',
-# 'django.template.loaders.eggs.Loader',
-)
-
-MIDDLEWARE_CLASSES = (
- 'django.middleware.common.CommonMiddleware',
- 'django.contrib.sessions.middleware.SessionMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
-)
-
-ROOT_URLCONF = 'testproject.urls'
-
-TEMPLATE_DIRS = (
- os.path.join(PROJECT_PATH, 'templates')
- # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
- # Always use forward slashes, even on Windows.
- # Don't forget to use absolute paths, not relative paths.
-)
-
-INSTALLED_APPS = (
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.sites',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
- # Uncomment the next line to enable the admin:
- # 'django.contrib.admin',
- # Uncomment the next line to enable admin documentation:
- # 'django.contrib.admindocs',
-
- 'wkhtmltopdf',
-)
-
-# A sample logging configuration. The only tangible logging
-# performed by this configuration is to send an email to
-# the site admins on every HTTP 500 error.
-# See http://docs.djangoproject.com/en/dev/topics/logging for
-# more details on how to customize your logging configuration.
-LOGGING = {
- 'version': 1,
- 'disable_existing_loggers': False,
- 'handlers': {
- 'mail_admins': {
- 'level': 'ERROR',
- 'class': 'django.utils.log.AdminEmailHandler'
- }
- },
- 'loggers': {
- 'django.request': {
- 'handlers': ['mail_admins'],
- 'level': 'ERROR',
- 'propagate': True,
- },
- }
-}
diff --git a/wkhtmltopdf/_testproject/urls.py b/wkhtmltopdf/_testproject/urls.py
deleted file mode 100644
index 039e61a..0000000
--- a/wkhtmltopdf/_testproject/urls.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from django.conf.urls.defaults import patterns, include, url
-
-# Uncomment the next two lines to enable the admin:
-# from django.contrib import admin
-# admin.autodiscover()
-
-urlpatterns = patterns('',
- # Examples:
- # url(r'^$', 'testproject.views.home', name='home'),
- # url(r'^testproject/', include('testproject.foo.urls')),
-
- # Uncomment the admin/doc line below to enable admin documentation:
- # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
-
- # Uncomment the next line to enable the admin:
- # url(r'^admin/', include(admin.site.urls)),
-)
diff --git a/wkhtmltopdf/test_settings.py b/wkhtmltopdf/test_settings.py
new file mode 100644
index 0000000..37d086f
--- /dev/null
+++ b/wkhtmltopdf/test_settings.py
@@ -0,0 +1,16 @@
+DEBUG = True
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.sqlite3',
+ 'NAME': ':memory:',
+ }
+}
+
+MEDIA_URL = ''
+STATIC_URL = ''
+
+INSTALLED_APPS = (
+ 'wkhtmltopdf.tests',
+ 'wkhtmltopdf',
+)
diff --git a/wkhtmltopdf/_testproject/__init__.py b/wkhtmltopdf/tests/__init__.py
index e69de29..e69de29 100644
--- a/wkhtmltopdf/_testproject/__init__.py
+++ b/wkhtmltopdf/tests/__init__.py
diff --git a/wkhtmltopdf/tests/models.py b/wkhtmltopdf/tests/models.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wkhtmltopdf/tests/models.py
diff --git a/wkhtmltopdf/_testproject/templates/footer.html b/wkhtmltopdf/tests/templates/footer.html
index 3ae09cb..3ae09cb 100644
--- a/wkhtmltopdf/_testproject/templates/footer.html
+++ b/wkhtmltopdf/tests/templates/footer.html
diff --git a/wkhtmltopdf/_testproject/templates/sample.html b/wkhtmltopdf/tests/templates/sample.html
index 3dfbdbb..3dfbdbb 100644
--- a/wkhtmltopdf/_testproject/templates/sample.html
+++ b/wkhtmltopdf/tests/templates/sample.html
diff --git a/wkhtmltopdf/tests.py b/wkhtmltopdf/tests/tests.py
index 3bdc481..6d8f3ac 100644
--- a/wkhtmltopdf/tests.py
+++ b/wkhtmltopdf/tests/tests.py
@@ -4,16 +4,13 @@ from __future__ import absolute_import
import os
import sys
-import warnings
from django.test import TestCase
from django.test.client import RequestFactory
-from .subprocess import CalledProcessError
-from .utils import (override_settings,
- _options_to_args, template_to_temp_file, wkhtmltopdf)
-from .views import (PDFResponse, PdfResponse, PDFTemplateResponse,
- PDFTemplateView, PdfTemplateView)
+from wkhtmltopdf.subprocess import CalledProcessError
+from wkhtmltopdf.utils import override_settings, _options_to_args, wkhtmltopdf
+from wkhtmltopdf.views import PDFResponse, PDFTemplateView, PDFTemplateResponse
class TestUtils(TestCase):
@@ -21,6 +18,7 @@ class TestUtils(TestCase):
# Clear standard error
self._stderr = sys.stderr
sys.stderr = open(os.devnull, 'w')
+ self.factory = RequestFactory()
def tearDown(self):
sys.stderr = self._stderr
@@ -36,39 +34,36 @@ class TestUtils(TestCase):
def test_wkhtmltopdf(self):
"""Should run wkhtmltopdf to generate a PDF"""
title = 'A test template.'
- temp_file = template_to_temp_file('sample.html', {'title': title})
- pdf_output = None
+ response = PDFTemplateResponse(self.factory.get('/'), None, context={'title': title})
+ temp_file = response.render_to_temporary_file('sample.html')
try:
# Standard call
- pdf_output = wkhtmltopdf(pages=[temp_file])
+ pdf_output = wkhtmltopdf(pages=[temp_file.name])
self.assertTrue(pdf_output.startswith('%PDF'), pdf_output)
# Single page
- pdf_output = wkhtmltopdf(pages=temp_file)
+ pdf_output = wkhtmltopdf(pages=temp_file.name)
self.assertTrue(pdf_output.startswith('%PDF'), pdf_output)
# Unicode
- pdf_output = wkhtmltopdf(pages=[temp_file], title=u'♥')
+ pdf_output = wkhtmltopdf(pages=[temp_file.name], title=u'♥')
self.assertTrue(pdf_output.startswith('%PDF'), pdf_output)
# Invalid arguments
self.assertRaises(CalledProcessError,
wkhtmltopdf, pages=[])
finally:
- if os.path.exists(temp_file):
- os.remove(temp_file)
+ temp_file.close()
- def test_template_to_temp_file(self):
+ def test_PDFTemplateResponse_render_to_temporary_file(self):
"""Should render a template to a temporary file."""
title = 'A test template.'
- temp_file = template_to_temp_file('sample.html', {'title': title})
- try:
- with open(temp_file, 'r') as f:
- saved_content = f.read()
- self.assertTrue(title in saved_content)
- finally:
- if os.path.exists(temp_file):
- os.remove(temp_file)
+ response = PDFTemplateResponse(self.factory.get('/'), None, context={'title': title})
+ temp_file = response.render_to_temporary_file('sample.html')
+ temp_file.seek(0)
+ saved_content = temp_file.read()
+ self.assertTrue(title in saved_content)
+ temp_file.close()
class TestViews(TestCase):
@@ -275,30 +270,3 @@ class TestViews(TestCase):
view.cmd_options.update(cmd_options)
self.assertEqual(view.cmd_options, cmd_options)
self.assertEqual(PDFTemplateView.cmd_options, {})
-
- def test_deprecated(self):
- """Should warn when using deprecated views."""
- with warnings.catch_warnings(record=True) as w:
- warnings.simplefilter('always')
- PdfTemplateView()
- self.assertEqual(len(w), 1)
- self.assertEqual(w[0].category, PendingDeprecationWarning)
- self.assertTrue(
- 'PDFTemplateView' in str(w[0].message),
- "'PDFTemplateView' not in {0!r}".format(w[0].message))
- with warnings.catch_warnings(record=True) as w:
- warnings.simplefilter('always')
- PdfResponse(None, None)
- self.assertEqual(len(w), 1)
- self.assertEqual(w[0].category, PendingDeprecationWarning)
- self.assertTrue(
- 'PDFResponse' in str(w[0].message),
- "'PDFResponse' not in {0!r}".format(w[0].message))
- with warnings.catch_warnings(record=True) as w:
- warnings.simplefilter('always')
- PDFTemplateView().get_pdf_kwargs()
- self.assertEqual(len(w), 1)
- self.assertEqual(w[0].category, PendingDeprecationWarning)
- self.assertTrue(
- 'get_pdf_kwargs()' in str(w[0].message),
- "'get_pdf_kwargs()' not in {0!r}".format(w[0].message))
diff --git a/wkhtmltopdf/utils.py b/wkhtmltopdf/utils.py
index 29e4ef6..99998a2 100644
--- a/wkhtmltopdf/utils.py
+++ b/wkhtmltopdf/utils.py
@@ -1,23 +1,19 @@
from __future__ import absolute_import
from copy import copy
+from functools import wraps
from itertools import chain
-from os import fdopen
import os
import sys
-from tempfile import mkstemp
import urllib
-import warnings
from django.conf import settings
-from django.template import loader
-from django.utils.encoding import smart_str
from .subprocess import check_output
def _options_to_args(**options):
- """Converts ``options`` into a string of command-line arguments."""
+ """Converts ``options`` into a list of command-line arguments."""
flags = []
for name in sorted(options):
value = options[name]
@@ -87,18 +83,6 @@ def wkhtmltopdf(pages, output=None, **kwargs):
return check_output(args, stderr=sys.stderr, env=env)
-def template_to_temp_file(template_name, dictionary=None, context_instance=None):
- """
- Renders a template to a temp file, and returns the path of the file.
- """
- warnings.warn('template_to_temp_file is deprecated in favour of PDFResponse. It will be removed in version 1.',
- PendingDeprecationWarning, 2)
- file_descriptor, tempfile_path = mkstemp(suffix='.html')
- with fdopen(file_descriptor, 'wt') as f:
- f.write(smart_str(loader.render_to_string(template_name, dictionary=dictionary, context_instance=context_instance)))
- return tempfile_path
-
-
def content_disposition_filename(filename):
"""
Sanitize a file name to be used in the Content-Disposition HTTP
diff --git a/wkhtmltopdf/views.py b/wkhtmltopdf/views.py
index 741742f..210ff0a 100644
--- a/wkhtmltopdf/views.py
+++ b/wkhtmltopdf/views.py
@@ -1,8 +1,7 @@
from __future__ import absolute_import
-from re import compile
from tempfile import NamedTemporaryFile
-import warnings
+import re
from django.conf import settings
from django.http import HttpResponse
@@ -39,13 +38,6 @@ class PDFResponse(HttpResponse):
del self['Content-Disposition']
-class PdfResponse(PDFResponse):
- def __init__(self, content, filename):
- warnings.warn('PdfResponse is deprecated in favour of PDFResponse. It will be removed in version 1.',
- PendingDeprecationWarning, 2)
- super(PdfResponse, self).__init__(content, filename=filename)
-
-
class PDFTemplateResponse(TemplateResponse, PDFResponse):
"""Renders a Template into a PDF using wkhtmltopdf"""
@@ -75,7 +67,7 @@ class PDFTemplateResponse(TemplateResponse, PDFResponse):
self.override_settings = override_settings
def render_to_temporary_file(self, template_name, mode='w+b', bufsize=-1,
- suffix='', prefix='tmp', dir=None,
+ suffix='.html', prefix='tmp', dir=None,
delete=True):
template = self.resolve_template(template_name)
@@ -169,7 +161,7 @@ class PDFTemplateResponse(TemplateResponse, PDFResponse):
if self.override_settings is not None:
overrides.update(self.override_settings)
- has_scheme = compile(r'^[^:/]+://')
+ has_scheme = re.compile(r'^[^:/]+://')
# If MEDIA_URL doesn't have a scheme, we transform it into a
# file:// URL based on MEDIA_ROOT.
@@ -230,11 +222,6 @@ class PDFTemplateView(TemplateView):
def get_cmd_options(self):
return self.cmd_options
- def get_pdf_kwargs(self):
- warnings.warn('PDFTemplateView.get_pdf_kwargs() is deprecated in favour of get_cmd_options(). It will be removed in version 1.',
- PendingDeprecationWarning, 2)
- return self.get_cmd_options()
-
def render_to_response(self, context, **response_kwargs):
"""
Returns a PDF response with a template rendered with the given context.
@@ -262,29 +249,3 @@ class PDFTemplateView(TemplateView):
context=context,
**response_kwargs
)
-
-
-class PdfTemplateView(PDFTemplateView): #TODO: Remove this in v1.0
- orientation = 'portrait'
- margin_bottom = 0
- margin_left = 0
- margin_right = 0
- margin_top = 0
-
- def __init__(self, *args, **kwargs):
- warnings.warn('PdfTemplateView is deprecated in favour of PDFTemplateView. It will be removed in version 1.',
- PendingDeprecationWarning, 2)
- super(PdfTemplateView, self).__init__(*args, **kwargs)
-
- def get_cmd_options(self):
- return self.get_pdf_kwargs()
-
- def get_pdf_kwargs(self):
- kwargs = {
- 'margin_bottom': self.margin_bottom,
- 'margin_left': self.margin_left,
- 'margin_right': self.margin_right,
- 'margin_top': self.margin_top,
- 'orientation': self.orientation,
- }
- return kwargs