From 9fe6391baa20c87842dd8475b6d8732d0a34b24b Mon Sep 17 00:00:00 2001 From: Charlie Denton Date: Fri, 27 Jul 2012 09:34:22 +0100 Subject: Fix typo in docstring. --- wkhtmltopdf/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wkhtmltopdf/utils.py b/wkhtmltopdf/utils.py index 29e4ef6..69114b7 100644 --- a/wkhtmltopdf/utils.py +++ b/wkhtmltopdf/utils.py @@ -17,7 +17,7 @@ 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] -- cgit v1.2.3 From 887ab7ce4ee31cf924e28f3c85783b5cf8352cc1 Mon Sep 17 00:00:00 2001 From: Marc Tamlyn Date: Fri, 27 Jul 2012 11:31:48 +0100 Subject: Remove deprecated methods/views. --- wkhtmltopdf/views.py | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/wkhtmltopdf/views.py b/wkhtmltopdf/views.py index fff98c8..20002bd 100644 --- a/wkhtmltopdf/views.py +++ b/wkhtmltopdf/views.py @@ -2,7 +2,6 @@ from __future__ import absolute_import from re import compile from tempfile import NamedTemporaryFile -import warnings from django.conf import settings from django.http import HttpResponse @@ -38,13 +37,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""" @@ -229,11 +221,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. @@ -261,29 +248,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 -- cgit v1.2.3 From e4a84d5f2e1282ed62d19ce7c52ca57eabb54598 Mon Sep 17 00:00:00 2001 From: Marc Tamlyn Date: Fri, 27 Jul 2012 11:36:02 +0100 Subject: Don't override builtins by importing. --- wkhtmltopdf/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wkhtmltopdf/views.py b/wkhtmltopdf/views.py index 20002bd..6668474 100644 --- a/wkhtmltopdf/views.py +++ b/wkhtmltopdf/views.py @@ -1,7 +1,7 @@ from __future__ import absolute_import -from re import compile from tempfile import NamedTemporaryFile +import re from django.conf import settings from django.http import HttpResponse @@ -160,7 +160,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. -- cgit v1.2.3 From f172db7a2a7f404e6543f04fc8664800591848e4 Mon Sep 17 00:00:00 2001 From: Marc Tamlyn Date: Fri, 27 Jul 2012 11:37:19 +0100 Subject: Remove more deprecated stuff and tests for them. --- wkhtmltopdf/tests.py | 28 ---------------------------- wkhtmltopdf/utils.py | 13 ------------- 2 files changed, 41 deletions(-) diff --git a/wkhtmltopdf/tests.py b/wkhtmltopdf/tests.py index 3bdc481..c55d6f9 100644 --- a/wkhtmltopdf/tests.py +++ b/wkhtmltopdf/tests.py @@ -4,7 +4,6 @@ from __future__ import absolute_import import os import sys -import warnings from django.test import TestCase from django.test.client import RequestFactory @@ -275,30 +274,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 69114b7..f95eddf 100644 --- a/wkhtmltopdf/utils.py +++ b/wkhtmltopdf/utils.py @@ -7,7 +7,6 @@ import os import sys from tempfile import mkstemp import urllib -import warnings from django.conf import settings from django.template import loader @@ -87,18 +86,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 -- cgit v1.2.3 From dde369a6963382fe452b4f82f3953ca8c7f00e63 Mon Sep 17 00:00:00 2001 From: Marc Tamlyn Date: Fri, 27 Jul 2012 12:39:03 +0100 Subject: Tidy up imports. --- wkhtmltopdf/utils.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/wkhtmltopdf/utils.py b/wkhtmltopdf/utils.py index f95eddf..99998a2 100644 --- a/wkhtmltopdf/utils.py +++ b/wkhtmltopdf/utils.py @@ -1,16 +1,13 @@ 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 from django.conf import settings -from django.template import loader -from django.utils.encoding import smart_str from .subprocess import check_output -- cgit v1.2.3 From 3a4201aeb1c8f7727a333f07eccd763624337e94 Mon Sep 17 00:00:00 2001 From: Marc Tamlyn Date: Fri, 27 Jul 2012 14:48:12 +0100 Subject: Add testing to the makefile. --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index c5f9321..b15be42 100644 --- a/Makefile +++ b/Makefile @@ -3,3 +3,5 @@ SHELL := /bin/bash release: python setup.py register sdist upload +test: + python wkhtmltopdf/_testproject/manage.py test wkhtmltopdf -- cgit v1.2.3 From d236427edccbd2fcb5dac438845d7de48ed2398d Mon Sep 17 00:00:00 2001 From: Marc Tamlyn Date: Fri, 27 Jul 2012 14:48:37 +0100 Subject: Update tests to remove deprecateded functions. --- wkhtmltopdf/tests.py | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/wkhtmltopdf/tests.py b/wkhtmltopdf/tests.py index c55d6f9..cd0213d 100644 --- a/wkhtmltopdf/tests.py +++ b/wkhtmltopdf/tests.py @@ -9,10 +9,8 @@ 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 .utils import override_settings, _options_to_args, wkhtmltopdf +from .views import PDFResponse, PDFTemplateView, PDFTemplateResponse class TestUtils(TestCase): @@ -20,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 @@ -35,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): -- cgit v1.2.3 From 1ef1a0bc443f1d8bbc8bddcda3562550a5b63119 Mon Sep 17 00:00:00 2001 From: Marc Tamlyn Date: Fri, 27 Jul 2012 14:59:43 +0100 Subject: Move the testproject out of the main folder. Also exclude it from distributions using the MANIFEST. --- MANIFEST.in | 2 +- Makefile | 2 +- testproject/__init__.py | 0 testproject/manage.py | 14 +++ testproject/requirements.txt | 1 + testproject/settings.py | 153 +++++++++++++++++++++++++ testproject/templates/footer.html | 2 + testproject/templates/sample.html | 7 ++ testproject/urls.py | 17 +++ wkhtmltopdf/_testproject/__init__.py | 0 wkhtmltopdf/_testproject/manage.py | 14 --- wkhtmltopdf/_testproject/requirements.txt | 1 - wkhtmltopdf/_testproject/settings.py | 152 ------------------------ wkhtmltopdf/_testproject/templates/footer.html | 2 - wkhtmltopdf/_testproject/templates/sample.html | 7 -- wkhtmltopdf/_testproject/urls.py | 17 --- 16 files changed, 196 insertions(+), 195 deletions(-) create mode 100644 testproject/__init__.py create mode 100644 testproject/manage.py create mode 100644 testproject/requirements.txt create mode 100644 testproject/settings.py create mode 100644 testproject/templates/footer.html create mode 100644 testproject/templates/sample.html create mode 100644 testproject/urls.py delete mode 100644 wkhtmltopdf/_testproject/__init__.py delete mode 100644 wkhtmltopdf/_testproject/manage.py delete mode 100644 wkhtmltopdf/_testproject/requirements.txt delete mode 100644 wkhtmltopdf/_testproject/settings.py delete mode 100644 wkhtmltopdf/_testproject/templates/footer.html delete mode 100644 wkhtmltopdf/_testproject/templates/sample.html delete mode 100644 wkhtmltopdf/_testproject/urls.py diff --git a/MANIFEST.in b/MANIFEST.in index 05c4bc6..234eb1f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,3 @@ include README.rst recursive-include * *.html - +recursive-exclude testproject * diff --git a/Makefile b/Makefile index b15be42..08f30ec 100644 --- a/Makefile +++ b/Makefile @@ -4,4 +4,4 @@ release: python setup.py register sdist upload test: - python wkhtmltopdf/_testproject/manage.py test wkhtmltopdf + python testproject/manage.py test wkhtmltopdf diff --git a/testproject/__init__.py b/testproject/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/testproject/manage.py b/testproject/manage.py new file mode 100644 index 0000000..3e4eedc --- /dev/null +++ b/testproject/manage.py @@ -0,0 +1,14 @@ +#!/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/testproject/requirements.txt b/testproject/requirements.txt new file mode 100644 index 0000000..74c18fb --- /dev/null +++ b/testproject/requirements.txt @@ -0,0 +1 @@ +Django==1.3.1 diff --git a/testproject/settings.py b/testproject/settings.py new file mode 100644 index 0000000..33674d4 --- /dev/null +++ b/testproject/settings.py @@ -0,0 +1,153 @@ +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', + + 'testproject', + '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/testproject/templates/footer.html b/testproject/templates/footer.html new file mode 100644 index 0000000..3ae09cb --- /dev/null +++ b/testproject/templates/footer.html @@ -0,0 +1,2 @@ +MEDIA_URL = {{ MEDIA_URL }} +STATIC_URL = {{ STATIC_URL }} diff --git a/testproject/templates/sample.html b/testproject/templates/sample.html new file mode 100644 index 0000000..3dfbdbb --- /dev/null +++ b/testproject/templates/sample.html @@ -0,0 +1,7 @@ + + + + +

{{ title }}

+ + diff --git a/testproject/urls.py b/testproject/urls.py new file mode 100644 index 0000000..039e61a --- /dev/null +++ b/testproject/urls.py @@ -0,0 +1,17 @@ +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/_testproject/__init__.py b/wkhtmltopdf/_testproject/__init__.py deleted file mode 100644 index e69de29..0000000 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/templates/footer.html b/wkhtmltopdf/_testproject/templates/footer.html deleted file mode 100644 index 3ae09cb..0000000 --- a/wkhtmltopdf/_testproject/templates/footer.html +++ /dev/null @@ -1,2 +0,0 @@ -MEDIA_URL = {{ MEDIA_URL }} -STATIC_URL = {{ STATIC_URL }} diff --git a/wkhtmltopdf/_testproject/templates/sample.html b/wkhtmltopdf/_testproject/templates/sample.html deleted file mode 100644 index 3dfbdbb..0000000 --- a/wkhtmltopdf/_testproject/templates/sample.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - -

{{ title }}

- - 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)), -) -- cgit v1.2.3 From 36a349a93ccfa5afa68b51214e1d6582cb1f5383 Mon Sep 17 00:00:00 2001 From: Marc Tamlyn Date: Fri, 27 Jul 2012 15:01:29 +0100 Subject: Update version to 1.0-rc1. --- wkhtmltopdf/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wkhtmltopdf/__init__.py b/wkhtmltopdf/__init__.py index 39b1413..d9c3b26 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-rc1' -- cgit v1.2.3 From 111c43882d156d4dd307e9f9c3298839c7955e7a Mon Sep 17 00:00:00 2001 From: Marc Tamlyn Date: Fri, 27 Jul 2012 16:31:57 +0100 Subject: Exclude tests file from distributions as well. --- MANIFEST.in | 1 + 1 file changed, 1 insertion(+) diff --git a/MANIFEST.in b/MANIFEST.in index 234eb1f..3f82fe9 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,4 @@ include README.rst recursive-include * *.html +exclude wkhtmltopdf/tests.py recursive-exclude testproject * -- cgit v1.2.3 From dc9f1fb46f587f2b8dbbfc440a72944b183c0fcd Mon Sep 17 00:00:00 2001 From: Marc Tamlyn Date: Fri, 27 Jul 2012 16:33:39 +0100 Subject: .html default suffix for render_to_temporary_file It's expected by wkhtmltopdf that the files should end in .html, so it may as well be the default. --- wkhtmltopdf/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wkhtmltopdf/views.py b/wkhtmltopdf/views.py index 6668474..f7e2feb 100644 --- a/wkhtmltopdf/views.py +++ b/wkhtmltopdf/views.py @@ -66,7 +66,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) -- cgit v1.2.3 From 9fc1d90c7db78d95b9c3b9a8d0329b472b8a4280 Mon Sep 17 00:00:00 2001 From: Marc Tamlyn Date: Fri, 3 Aug 2012 10:42:20 +0100 Subject: Move tests into wkhtmltopdf.tests.* Fixes #11. --- Makefile | 2 +- testproject/__init__.py | 0 testproject/manage.py | 14 -- testproject/requirements.txt | 1 - testproject/settings.py | 153 ------------------ testproject/templates/footer.html | 2 - testproject/templates/sample.html | 7 - testproject/urls.py | 17 -- wkhtmltopdf/test_settings.py | 16 ++ wkhtmltopdf/tests.py | 272 -------------------------------- wkhtmltopdf/tests/__init__.py | 0 wkhtmltopdf/tests/models.py | 0 wkhtmltopdf/tests/templates/footer.html | 2 + wkhtmltopdf/tests/templates/sample.html | 7 + wkhtmltopdf/tests/tests.py | 272 ++++++++++++++++++++++++++++++++ 15 files changed, 298 insertions(+), 467 deletions(-) delete mode 100644 testproject/__init__.py delete mode 100644 testproject/manage.py delete mode 100644 testproject/requirements.txt delete mode 100644 testproject/settings.py delete mode 100644 testproject/templates/footer.html delete mode 100644 testproject/templates/sample.html delete mode 100644 testproject/urls.py create mode 100644 wkhtmltopdf/test_settings.py delete mode 100644 wkhtmltopdf/tests.py create mode 100644 wkhtmltopdf/tests/__init__.py create mode 100644 wkhtmltopdf/tests/models.py create mode 100644 wkhtmltopdf/tests/templates/footer.html create mode 100644 wkhtmltopdf/tests/templates/sample.html create mode 100644 wkhtmltopdf/tests/tests.py diff --git a/Makefile b/Makefile index 08f30ec..c691507 100644 --- a/Makefile +++ b/Makefile @@ -4,4 +4,4 @@ release: python setup.py register sdist upload test: - python testproject/manage.py test wkhtmltopdf + django-admin.py test tests --settings=wkhtmltopdf.test_settings diff --git a/testproject/__init__.py b/testproject/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/testproject/manage.py b/testproject/manage.py deleted file mode 100644 index 3e4eedc..0000000 --- a/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/testproject/requirements.txt b/testproject/requirements.txt deleted file mode 100644 index 74c18fb..0000000 --- a/testproject/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -Django==1.3.1 diff --git a/testproject/settings.py b/testproject/settings.py deleted file mode 100644 index 33674d4..0000000 --- a/testproject/settings.py +++ /dev/null @@ -1,153 +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', - - 'testproject', - '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/testproject/templates/footer.html b/testproject/templates/footer.html deleted file mode 100644 index 3ae09cb..0000000 --- a/testproject/templates/footer.html +++ /dev/null @@ -1,2 +0,0 @@ -MEDIA_URL = {{ MEDIA_URL }} -STATIC_URL = {{ STATIC_URL }} diff --git a/testproject/templates/sample.html b/testproject/templates/sample.html deleted file mode 100644 index 3dfbdbb..0000000 --- a/testproject/templates/sample.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - -

{{ title }}

- - diff --git a/testproject/urls.py b/testproject/urls.py deleted file mode 100644 index 039e61a..0000000 --- a/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/tests.py b/wkhtmltopdf/tests.py deleted file mode 100644 index cd0213d..0000000 --- a/wkhtmltopdf/tests.py +++ /dev/null @@ -1,272 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import absolute_import - -import os -import sys - -from django.test import TestCase -from django.test.client import RequestFactory - -from .subprocess import CalledProcessError -from .utils import override_settings, _options_to_args, wkhtmltopdf -from .views import PDFResponse, PDFTemplateView, PDFTemplateResponse - - -class TestUtils(TestCase): - def setUp(self): - # Clear standard error - self._stderr = sys.stderr - sys.stderr = open(os.devnull, 'w') - self.factory = RequestFactory() - - def tearDown(self): - sys.stderr = self._stderr - - def test_options_to_args(self): - self.assertEqual(_options_to_args(), []) - self.assertEqual(_options_to_args(heart=u'♥', verbose=True, - file_name='file-name'), - ['--file-name', 'file-name', - '--heart', u'♥', - '--verbose']) - - def test_wkhtmltopdf(self): - """Should run wkhtmltopdf to generate a PDF""" - title = 'A test template.' - 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.name]) - self.assertTrue(pdf_output.startswith('%PDF'), pdf_output) - - # Single page - pdf_output = wkhtmltopdf(pages=temp_file.name) - self.assertTrue(pdf_output.startswith('%PDF'), pdf_output) - - # Unicode - 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: - temp_file.close() - - def test_PDFTemplateResponse_render_to_temporary_file(self): - """Should render a template to a temporary file.""" - title = 'A test template.' - 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): - def test_pdf_response(self): - """Should generate the correct HttpResponse object and mimetype""" - # 404 - response = PDFResponse(content='', status=404) - self.assertEqual(response.status_code, 404) - self.assertEqual(response.content, '') - self.assertEqual(response['Content-Type'], 'application/pdf') - self.assertFalse(response.has_header('Content-Disposition')) - - content = '%PDF-1.4\n%%EOF' - # Without filename - response = PDFResponse(content=content) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.content, content) - self.assertEqual(response['Content-Type'], 'application/pdf') - self.assertFalse(response.has_header('Content-Disposition')) - - # With filename - response = PDFResponse(content=content, filename="nospace.pdf") - self.assertEqual(response['Content-Disposition'], - 'attachment; filename="nospace.pdf"') - response = PDFResponse(content=content, filename="one space.pdf") - self.assertEqual(response['Content-Disposition'], - 'attachment; filename="one space.pdf"') - response = PDFResponse(content=content, filename="4'5\".pdf") - self.assertEqual(response['Content-Disposition'], - 'attachment; filename="4\'5.pdf"') - response = PDFResponse(content=content, filename=u"♥.pdf") - self.assertEqual(response['Content-Disposition'], - 'attachment; filename="?.pdf"') - - # Content-Type - response = PDFResponse(content=content, - content_type='application/x-pdf') - self.assertEqual(response['Content-Type'], 'application/x-pdf') - response = PDFResponse(content=content, - mimetype='application/x-pdf') - self.assertEqual(response['Content-Type'], 'application/x-pdf') - - def test_pdf_template_response(self): - """Test PDFTemplateResponse.""" - from django.conf import settings - - with override_settings( - MEDIA_URL='/media/', - MEDIA_ROOT='/tmp/media', - STATIC_URL='/static/', - STATIC_ROOT='/tmp/static', - TEMPLATE_CONTEXT_PROCESSORS=[ - 'django.core.context_processors.media', - 'django.core.context_processors.static', - ], - TEMPLATE_LOADERS=['django.template.loaders.filesystem.Loader'], - TEMPLATE_DIRS=[os.path.join(os.path.dirname(__file__), - '_testproject', 'templates')], - WKHTMLTOPDF_DEBUG=False, - ): - # Setup sample.html - template = 'sample.html' - context = {'title': 'Heading'} - request = RequestFactory().get('/') - response = PDFTemplateResponse(request=request, - template=template, - context=context) - self.assertEqual(response._request, request) - self.assertEqual(response.template_name, template) - self.assertEqual(response.context_data, context) - self.assertEqual(response.filename, None) - self.assertEqual(response.header_template, None) - self.assertEqual(response.footer_template, None) - self.assertEqual(response.cmd_options, {}) - self.assertFalse(response.has_header('Content-Disposition')) - - # Render to temporary file - tempfile = response.render_to_temporary_file(template) - tempfile.seek(0) - html_content = tempfile.read() - self.assertTrue(html_content.startswith('')) - self.assertTrue('

{title}

'.format(**context) - in html_content) - - pdf_content = response.rendered_content - self.assertTrue(pdf_content.startswith('%PDF-')) - self.assertTrue(pdf_content.endswith('%%EOF\n')) - - # Footer - filename = 'output.pdf' - footer_template = 'footer.html' - cmd_options = {'title': 'Test PDF'} - response = PDFTemplateResponse(request=request, - template=template, - context=context, - filename=filename, - footer_template=footer_template, - cmd_options=cmd_options) - self.assertEqual(response.filename, filename) - self.assertEqual(response.header_template, None) - self.assertEqual(response.footer_template, footer_template) - self.assertEqual(response.cmd_options, cmd_options) - self.assertTrue(response.has_header('Content-Disposition')) - - tempfile = response.render_to_temporary_file(footer_template) - tempfile.seek(0) - footer_content = tempfile.read() - - media_url = 'MEDIA_URL = file://{0}/'.format(settings.MEDIA_ROOT) - self.assertTrue( - media_url in footer_content, - "{0!r} not in {1!r}".format(media_url, footer_content) - ) - - static_url = 'STATIC_URL = file://{0}/'.format(settings.STATIC_ROOT) - self.assertTrue( - static_url in footer_content, - "{0!r} not in {1!r}".format(static_url, footer_content) - ) - - pdf_content = response.rendered_content - self.assertTrue('\0'.join('{title}'.format(**cmd_options)) - in pdf_content) - - # Override settings - response = PDFTemplateResponse(request=request, - template=template, - context=context, - filename=filename, - footer_template=footer_template, - cmd_options=cmd_options, - override_settings={ - 'STATIC_URL': 'file:///tmp/s/' - }) - tempfile = response.render_to_temporary_file(footer_template) - tempfile.seek(0) - footer_content = tempfile.read() - - static_url = 'STATIC_URL = {0}'.format('file:///tmp/s/') - self.assertTrue( - static_url in footer_content, - "{0!r} not in {1!r}".format(static_url, footer_content) - ) - self.assertEqual(settings.STATIC_URL, '/static/') - - def test_pdf_template_view(self): - """Test PDFTemplateView.""" - with override_settings( - MEDIA_URL='/media/', - STATIC_URL='/static/', - TEMPLATE_CONTEXT_PROCESSORS=[ - 'django.core.context_processors.media', - 'django.core.context_processors.static', - ], - TEMPLATE_LOADERS=['django.template.loaders.filesystem.Loader'], - TEMPLATE_DIRS=[os.path.join(os.path.dirname(__file__), - '_testproject', 'templates')], - WKHTMLTOPDF_DEBUG=False, - ): - # Setup sample.html - template = 'sample.html' - filename = 'output.pdf' - view = PDFTemplateView.as_view(filename=filename, - template_name=template, - footer_template='footer.html') - - # As PDF - request = RequestFactory().get('/') - response = view(request) - self.assertEqual(response.status_code, 200) - response.render() - self.assertEqual(response['Content-Disposition'], - 'attachment; filename="{0}"'.format(filename)) - self.assertTrue(response.content.startswith('%PDF-')) - self.assertTrue(response.content.endswith('%%EOF\n')) - - # As HTML - request = RequestFactory().get('/?as=html') - response = view(request) - self.assertEqual(response.status_code, 200) - response.render() - self.assertFalse(response.has_header('Content-Disposition')) - self.assertTrue(response.content.startswith('')) - - # POST - request = RequestFactory().post('/') - response = view(request) - self.assertEqual(response.status_code, 405) - - def test_get_cmd_options(self): - # Default cmd_options - view = PDFTemplateView() - self.assertEqual(view.cmd_options, PDFTemplateView.cmd_options) - self.assertEqual(PDFTemplateView.cmd_options, {}) - - # Instantiate with new cmd_options - cmd_options = {'orientation': 'landscape'} - view = PDFTemplateView(cmd_options=cmd_options) - self.assertEqual(view.cmd_options, cmd_options) - self.assertEqual(PDFTemplateView.cmd_options, {}) - - # Update local instance of cmd_options - view = PDFTemplateView() - view.cmd_options.update(cmd_options) - self.assertEqual(view.cmd_options, cmd_options) - self.assertEqual(PDFTemplateView.cmd_options, {}) diff --git a/wkhtmltopdf/tests/__init__.py b/wkhtmltopdf/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/wkhtmltopdf/tests/models.py b/wkhtmltopdf/tests/models.py new file mode 100644 index 0000000..e69de29 diff --git a/wkhtmltopdf/tests/templates/footer.html b/wkhtmltopdf/tests/templates/footer.html new file mode 100644 index 0000000..3ae09cb --- /dev/null +++ b/wkhtmltopdf/tests/templates/footer.html @@ -0,0 +1,2 @@ +MEDIA_URL = {{ MEDIA_URL }} +STATIC_URL = {{ STATIC_URL }} diff --git a/wkhtmltopdf/tests/templates/sample.html b/wkhtmltopdf/tests/templates/sample.html new file mode 100644 index 0000000..3dfbdbb --- /dev/null +++ b/wkhtmltopdf/tests/templates/sample.html @@ -0,0 +1,7 @@ + + + + +

{{ title }}

+ + diff --git a/wkhtmltopdf/tests/tests.py b/wkhtmltopdf/tests/tests.py new file mode 100644 index 0000000..6d8f3ac --- /dev/null +++ b/wkhtmltopdf/tests/tests.py @@ -0,0 +1,272 @@ +# -*- coding: utf-8 -*- + +from __future__ import absolute_import + +import os +import sys + +from django.test import TestCase +from django.test.client import RequestFactory + +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): + def setUp(self): + # Clear standard error + self._stderr = sys.stderr + sys.stderr = open(os.devnull, 'w') + self.factory = RequestFactory() + + def tearDown(self): + sys.stderr = self._stderr + + def test_options_to_args(self): + self.assertEqual(_options_to_args(), []) + self.assertEqual(_options_to_args(heart=u'♥', verbose=True, + file_name='file-name'), + ['--file-name', 'file-name', + '--heart', u'♥', + '--verbose']) + + def test_wkhtmltopdf(self): + """Should run wkhtmltopdf to generate a PDF""" + title = 'A test template.' + 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.name]) + self.assertTrue(pdf_output.startswith('%PDF'), pdf_output) + + # Single page + pdf_output = wkhtmltopdf(pages=temp_file.name) + self.assertTrue(pdf_output.startswith('%PDF'), pdf_output) + + # Unicode + 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: + temp_file.close() + + def test_PDFTemplateResponse_render_to_temporary_file(self): + """Should render a template to a temporary file.""" + title = 'A test template.' + 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): + def test_pdf_response(self): + """Should generate the correct HttpResponse object and mimetype""" + # 404 + response = PDFResponse(content='', status=404) + self.assertEqual(response.status_code, 404) + self.assertEqual(response.content, '') + self.assertEqual(response['Content-Type'], 'application/pdf') + self.assertFalse(response.has_header('Content-Disposition')) + + content = '%PDF-1.4\n%%EOF' + # Without filename + response = PDFResponse(content=content) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.content, content) + self.assertEqual(response['Content-Type'], 'application/pdf') + self.assertFalse(response.has_header('Content-Disposition')) + + # With filename + response = PDFResponse(content=content, filename="nospace.pdf") + self.assertEqual(response['Content-Disposition'], + 'attachment; filename="nospace.pdf"') + response = PDFResponse(content=content, filename="one space.pdf") + self.assertEqual(response['Content-Disposition'], + 'attachment; filename="one space.pdf"') + response = PDFResponse(content=content, filename="4'5\".pdf") + self.assertEqual(response['Content-Disposition'], + 'attachment; filename="4\'5.pdf"') + response = PDFResponse(content=content, filename=u"♥.pdf") + self.assertEqual(response['Content-Disposition'], + 'attachment; filename="?.pdf"') + + # Content-Type + response = PDFResponse(content=content, + content_type='application/x-pdf') + self.assertEqual(response['Content-Type'], 'application/x-pdf') + response = PDFResponse(content=content, + mimetype='application/x-pdf') + self.assertEqual(response['Content-Type'], 'application/x-pdf') + + def test_pdf_template_response(self): + """Test PDFTemplateResponse.""" + from django.conf import settings + + with override_settings( + MEDIA_URL='/media/', + MEDIA_ROOT='/tmp/media', + STATIC_URL='/static/', + STATIC_ROOT='/tmp/static', + TEMPLATE_CONTEXT_PROCESSORS=[ + 'django.core.context_processors.media', + 'django.core.context_processors.static', + ], + TEMPLATE_LOADERS=['django.template.loaders.filesystem.Loader'], + TEMPLATE_DIRS=[os.path.join(os.path.dirname(__file__), + '_testproject', 'templates')], + WKHTMLTOPDF_DEBUG=False, + ): + # Setup sample.html + template = 'sample.html' + context = {'title': 'Heading'} + request = RequestFactory().get('/') + response = PDFTemplateResponse(request=request, + template=template, + context=context) + self.assertEqual(response._request, request) + self.assertEqual(response.template_name, template) + self.assertEqual(response.context_data, context) + self.assertEqual(response.filename, None) + self.assertEqual(response.header_template, None) + self.assertEqual(response.footer_template, None) + self.assertEqual(response.cmd_options, {}) + self.assertFalse(response.has_header('Content-Disposition')) + + # Render to temporary file + tempfile = response.render_to_temporary_file(template) + tempfile.seek(0) + html_content = tempfile.read() + self.assertTrue(html_content.startswith('')) + self.assertTrue('

{title}

'.format(**context) + in html_content) + + pdf_content = response.rendered_content + self.assertTrue(pdf_content.startswith('%PDF-')) + self.assertTrue(pdf_content.endswith('%%EOF\n')) + + # Footer + filename = 'output.pdf' + footer_template = 'footer.html' + cmd_options = {'title': 'Test PDF'} + response = PDFTemplateResponse(request=request, + template=template, + context=context, + filename=filename, + footer_template=footer_template, + cmd_options=cmd_options) + self.assertEqual(response.filename, filename) + self.assertEqual(response.header_template, None) + self.assertEqual(response.footer_template, footer_template) + self.assertEqual(response.cmd_options, cmd_options) + self.assertTrue(response.has_header('Content-Disposition')) + + tempfile = response.render_to_temporary_file(footer_template) + tempfile.seek(0) + footer_content = tempfile.read() + + media_url = 'MEDIA_URL = file://{0}/'.format(settings.MEDIA_ROOT) + self.assertTrue( + media_url in footer_content, + "{0!r} not in {1!r}".format(media_url, footer_content) + ) + + static_url = 'STATIC_URL = file://{0}/'.format(settings.STATIC_ROOT) + self.assertTrue( + static_url in footer_content, + "{0!r} not in {1!r}".format(static_url, footer_content) + ) + + pdf_content = response.rendered_content + self.assertTrue('\0'.join('{title}'.format(**cmd_options)) + in pdf_content) + + # Override settings + response = PDFTemplateResponse(request=request, + template=template, + context=context, + filename=filename, + footer_template=footer_template, + cmd_options=cmd_options, + override_settings={ + 'STATIC_URL': 'file:///tmp/s/' + }) + tempfile = response.render_to_temporary_file(footer_template) + tempfile.seek(0) + footer_content = tempfile.read() + + static_url = 'STATIC_URL = {0}'.format('file:///tmp/s/') + self.assertTrue( + static_url in footer_content, + "{0!r} not in {1!r}".format(static_url, footer_content) + ) + self.assertEqual(settings.STATIC_URL, '/static/') + + def test_pdf_template_view(self): + """Test PDFTemplateView.""" + with override_settings( + MEDIA_URL='/media/', + STATIC_URL='/static/', + TEMPLATE_CONTEXT_PROCESSORS=[ + 'django.core.context_processors.media', + 'django.core.context_processors.static', + ], + TEMPLATE_LOADERS=['django.template.loaders.filesystem.Loader'], + TEMPLATE_DIRS=[os.path.join(os.path.dirname(__file__), + '_testproject', 'templates')], + WKHTMLTOPDF_DEBUG=False, + ): + # Setup sample.html + template = 'sample.html' + filename = 'output.pdf' + view = PDFTemplateView.as_view(filename=filename, + template_name=template, + footer_template='footer.html') + + # As PDF + request = RequestFactory().get('/') + response = view(request) + self.assertEqual(response.status_code, 200) + response.render() + self.assertEqual(response['Content-Disposition'], + 'attachment; filename="{0}"'.format(filename)) + self.assertTrue(response.content.startswith('%PDF-')) + self.assertTrue(response.content.endswith('%%EOF\n')) + + # As HTML + request = RequestFactory().get('/?as=html') + response = view(request) + self.assertEqual(response.status_code, 200) + response.render() + self.assertFalse(response.has_header('Content-Disposition')) + self.assertTrue(response.content.startswith('')) + + # POST + request = RequestFactory().post('/') + response = view(request) + self.assertEqual(response.status_code, 405) + + def test_get_cmd_options(self): + # Default cmd_options + view = PDFTemplateView() + self.assertEqual(view.cmd_options, PDFTemplateView.cmd_options) + self.assertEqual(PDFTemplateView.cmd_options, {}) + + # Instantiate with new cmd_options + cmd_options = {'orientation': 'landscape'} + view = PDFTemplateView(cmd_options=cmd_options) + self.assertEqual(view.cmd_options, cmd_options) + self.assertEqual(PDFTemplateView.cmd_options, {}) + + # Update local instance of cmd_options + view = PDFTemplateView() + view.cmd_options.update(cmd_options) + self.assertEqual(view.cmd_options, cmd_options) + self.assertEqual(PDFTemplateView.cmd_options, {}) -- cgit v1.2.3 From 16916a83251a2b1f601842d52abd0577486c0a0f Mon Sep 17 00:00:00 2001 From: Marc Tamlyn Date: Fri, 3 Aug 2012 10:45:41 +0100 Subject: Update version to rc2. --- MANIFEST.in | 2 -- wkhtmltopdf/__init__.py | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index 3f82fe9..df4289a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,2 @@ include README.rst recursive-include * *.html -exclude wkhtmltopdf/tests.py -recursive-exclude testproject * diff --git a/wkhtmltopdf/__init__.py b/wkhtmltopdf/__init__.py index d9c3b26..890b800 100644 --- a/wkhtmltopdf/__init__.py +++ b/wkhtmltopdf/__init__.py @@ -3,4 +3,4 @@ if 'DJANGO_SETTINGS_MODULE' in os.environ: from .utils import * __author__ = 'Incuna Ltd' -__version__ = '1.0-rc1' +__version__ = '1.0-rc2' -- cgit v1.2.3 From 77b0b2e4ba2604ff728f9cf84dc728de36abb974 Mon Sep 17 00:00:00 2001 From: Marc Tamlyn Date: Mon, 6 Aug 2012 09:42:02 +0100 Subject: Check PYTHONPATH in the Makefile. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c691507..f7ad668 100644 --- a/Makefile +++ b/Makefile @@ -4,4 +4,4 @@ release: python setup.py register sdist upload test: - django-admin.py test tests --settings=wkhtmltopdf.test_settings + PYTHONPATH=.:$$PYTHONPATH; django-admin.py test tests --settings=wkhtmltopdf.test_settings -- cgit v1.2.3 From 8d8d7ba99640366ac8304390b97a4f03842c1254 Mon Sep 17 00:00:00 2001 From: Marc Tamlyn Date: Mon, 6 Aug 2012 10:26:05 +0100 Subject: Bump to full 1.0 version. --- wkhtmltopdf/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wkhtmltopdf/__init__.py b/wkhtmltopdf/__init__.py index 890b800..7411417 100644 --- a/wkhtmltopdf/__init__.py +++ b/wkhtmltopdf/__init__.py @@ -3,4 +3,4 @@ if 'DJANGO_SETTINGS_MODULE' in os.environ: from .utils import * __author__ = 'Incuna Ltd' -__version__ = '1.0-rc2' +__version__ = '1.0' -- cgit v1.2.3