Fix passing named arguments to link's views
This commit is contained in:
@@ -1,122 +0,0 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import hashlib
|
||||
import logging
|
||||
import os
|
||||
|
||||
from django.utils.encoding import smart_str
|
||||
|
||||
from common.settings import TEMPORARY_DIRECTORY
|
||||
from common.utils import fs_cleanup
|
||||
|
||||
from .exceptions import OfficeConversionError, UnknownFileFormat
|
||||
from .literals import (
|
||||
DEFAULT_PAGE_NUMBER, DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION,
|
||||
DEFAULT_FILE_FORMAT, TRANSFORMATION_CHOICES, TRANSFORMATION_RESIZE,
|
||||
TRANSFORMATION_ROTATE, TRANSFORMATION_ZOOM, DIMENSION_SEPARATOR
|
||||
)
|
||||
|
||||
HASH_FUNCTION = lambda x: hashlib.sha256(x).hexdigest()
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def cache_cleanup(input_filepath, *args, **kwargs):
|
||||
try:
|
||||
os.remove(create_image_cache_filename(input_filepath, *args, **kwargs))
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
def create_image_cache_filename(input_filepath, *args, **kwargs):
|
||||
if input_filepath:
|
||||
hash_value = HASH_FUNCTION(''.join([HASH_FUNCTION(smart_str(input_filepath)), unicode(args), unicode(kwargs)]))
|
||||
return os.path.join(TEMPORARY_DIRECTORY, hash_value)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def convert(input_filepath, output_filepath=None, cleanup_files=False, mimetype=None, *args, **kwargs):
|
||||
size = kwargs.get('size')
|
||||
file_format = kwargs.get('file_format', DEFAULT_FILE_FORMAT)
|
||||
zoom = kwargs.get('zoom', DEFAULT_ZOOM_LEVEL)
|
||||
rotation = kwargs.get('rotation', DEFAULT_ROTATION)
|
||||
page = kwargs.get('page', DEFAULT_PAGE_NUMBER)
|
||||
transformations = kwargs.get('transformations', [])
|
||||
|
||||
if transformations is None:
|
||||
transformations = []
|
||||
|
||||
if output_filepath is None:
|
||||
output_filepath = create_image_cache_filename(input_filepath, *args, **kwargs)
|
||||
|
||||
if os.path.exists(output_filepath):
|
||||
return output_filepath
|
||||
|
||||
if office_converter:
|
||||
try:
|
||||
office_converter.convert(input_filepath, mimetype=mimetype)
|
||||
if office_converter.exists:
|
||||
input_filepath = office_converter.output_filepath
|
||||
mimetype = 'application/pdf'
|
||||
else:
|
||||
# Recycle the already detected mimetype
|
||||
mimetype = office_converter.mimetype
|
||||
|
||||
except OfficeConversionError:
|
||||
raise UnknownFileFormat('office converter exception')
|
||||
|
||||
if size:
|
||||
transformations.append(
|
||||
{
|
||||
'transformation': TRANSFORMATION_RESIZE,
|
||||
'arguments': dict(zip(['width', 'height'], size.split(DIMENSION_SEPARATOR)))
|
||||
}
|
||||
)
|
||||
|
||||
if zoom != 100:
|
||||
transformations.append(
|
||||
{
|
||||
'transformation': TRANSFORMATION_ZOOM,
|
||||
'arguments': {'percent': zoom}
|
||||
}
|
||||
)
|
||||
|
||||
if rotation != 0 and rotation != 360:
|
||||
transformations.append(
|
||||
{
|
||||
'transformation': TRANSFORMATION_ROTATE,
|
||||
'arguments': {'degrees': rotation}
|
||||
}
|
||||
)
|
||||
|
||||
try:
|
||||
backend.convert_file(input_filepath=input_filepath, output_filepath=output_filepath, transformations=transformations, page=page, file_format=file_format, mimetype=mimetype)
|
||||
finally:
|
||||
if cleanup_files:
|
||||
fs_cleanup(input_filepath)
|
||||
|
||||
return output_filepath
|
||||
|
||||
|
||||
def get_page_count(input_filepath):
|
||||
logger.debug('office_converter: %s', office_converter)
|
||||
if office_converter:
|
||||
try:
|
||||
office_converter.convert(input_filepath)
|
||||
logger.debug('office_converter.exists: %s', office_converter.exists)
|
||||
if office_converter.exists:
|
||||
input_filepath = office_converter.output_filepath
|
||||
|
||||
except OfficeConversionError:
|
||||
raise UnknownFileFormat('office converter exception')
|
||||
|
||||
return backend.get_page_count(input_filepath)
|
||||
|
||||
|
||||
def get_available_transformations_choices():
|
||||
result = []
|
||||
for transformation in backend.get_available_transformations():
|
||||
result.append((transformation, TRANSFORMATION_CHOICES[transformation]['label']))
|
||||
|
||||
return result
|
||||
@@ -1,149 +0,0 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from common.settings import TEMPORARY_DIRECTORY
|
||||
from mimetype.api import get_mimetype
|
||||
|
||||
from .exceptions import OfficeBackendError, UnknownFileFormat
|
||||
from .settings import LIBREOFFICE_PATH
|
||||
|
||||
CACHED_FILE_SUFFIX = '_office_converter'
|
||||
|
||||
CONVERTER_OFFICE_FILE_MIMETYPES = [
|
||||
'application/msword',
|
||||
'application/mswrite',
|
||||
'application/mspowerpoint',
|
||||
'application/msexcel',
|
||||
'application/pgp-keys',
|
||||
'application/vnd.ms-excel',
|
||||
'application/vnd.ms-excel.addin.macroEnabled.12',
|
||||
'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
|
||||
'application/vnd.ms-powerpoint',
|
||||
'application/vnd.oasis.opendocument.chart',
|
||||
'application/vnd.oasis.opendocument.chart-template',
|
||||
'application/vnd.oasis.opendocument.formula',
|
||||
'application/vnd.oasis.opendocument.formula-template',
|
||||
'application/vnd.oasis.opendocument.graphics',
|
||||
'application/vnd.oasis.opendocument.graphics-template',
|
||||
'application/vnd.oasis.opendocument.image',
|
||||
'application/vnd.oasis.opendocument.image-template',
|
||||
'application/vnd.oasis.opendocument.presentation',
|
||||
'application/vnd.oasis.opendocument.presentation-template',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.template',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.slide',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
|
||||
'application/vnd.oasis.opendocument.spreadsheet',
|
||||
'application/vnd.oasis.opendocument.spreadsheet-template',
|
||||
'application/vnd.oasis.opendocument.text',
|
||||
'application/vnd.oasis.opendocument.text-master',
|
||||
'application/vnd.oasis.opendocument.text-template',
|
||||
'application/vnd.oasis.opendocument.text-web',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'application/vnd.ms-office',
|
||||
'application/xml',
|
||||
'text/x-c',
|
||||
'text/x-c++',
|
||||
'text/x-pascal',
|
||||
'text/x-msdos-batch',
|
||||
'text/x-python',
|
||||
'text/x-shellscript',
|
||||
'text/plain',
|
||||
'text/rtf',
|
||||
]
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OfficeConverter(object):
|
||||
def __init__(self):
|
||||
self.backend_class = OfficeConverterBackendDirect
|
||||
self.backend = self.backend_class()
|
||||
self.exists = False
|
||||
self.mimetype = None
|
||||
self.encoding = None
|
||||
|
||||
def mimetypes(self):
|
||||
return CONVERTER_OFFICE_FILE_MIMETYPES
|
||||
|
||||
def convert(self, input_filepath, mimetype=None):
|
||||
self.exists = False
|
||||
self.mimetype = None
|
||||
self.encoding = None
|
||||
|
||||
self.input_filepath = input_filepath
|
||||
|
||||
# Make sure file is of a known office format
|
||||
if mimetype:
|
||||
self.mimetype = mimetype
|
||||
else:
|
||||
self.mimetype, self.encoding = get_mimetype(open(self.input_filepath), self.input_filepath, mimetype_only=True)
|
||||
|
||||
if self.mimetype in CONVERTER_OFFICE_FILE_MIMETYPES:
|
||||
# Cache results of conversion
|
||||
self.output_filepath = os.path.join(TEMPORARY_DIRECTORY, ''.join([self.input_filepath, CACHED_FILE_SUFFIX]))
|
||||
self.exists = os.path.exists(self.output_filepath)
|
||||
if not self.exists:
|
||||
try:
|
||||
self.backend.convert(self.input_filepath, self.output_filepath)
|
||||
self.exists = True
|
||||
except OfficeBackendError as exception:
|
||||
# convert exception so that at least the mime type icon is displayed
|
||||
raise UnknownFileFormat(exception)
|
||||
|
||||
|
||||
class OfficeConverterBackendDirect(object):
|
||||
def __init__(self):
|
||||
self.libreoffice_path = LIBREOFFICE_PATH
|
||||
if not os.path.exists(self.libreoffice_path):
|
||||
raise OfficeBackendError('cannot find LibreOffice executable')
|
||||
logger.debug('self.libreoffice_path: %s', self.libreoffice_path)
|
||||
|
||||
def convert(self, input_filepath, output_filepath):
|
||||
"""
|
||||
Executes libreoffice using subprocess's Popen
|
||||
"""
|
||||
self.input_filepath = input_filepath
|
||||
self.output_filepath = output_filepath
|
||||
|
||||
command = []
|
||||
command.append(self.libreoffice_path)
|
||||
|
||||
command.append('--headless')
|
||||
command.append('--convert-to')
|
||||
command.append('pdf')
|
||||
command.append(self.input_filepath)
|
||||
command.append('--outdir')
|
||||
command.append(TEMPORARY_DIRECTORY)
|
||||
|
||||
logger.debug('command: %s', command)
|
||||
|
||||
try:
|
||||
os.environ['HOME'] = TEMPORARY_DIRECTORY
|
||||
proc = subprocess.Popen(command, close_fds=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
return_code = proc.wait()
|
||||
logger.debug('return_code: %s', return_code)
|
||||
|
||||
readline = proc.stderr.readline()
|
||||
logger.debug('stderr: %s', readline)
|
||||
if return_code != 0:
|
||||
raise OfficeBackendError(readline)
|
||||
filename, extension = os.path.splitext(os.path.basename(self.input_filepath))
|
||||
logger.debug('filename: %s', filename)
|
||||
logger.debug('extension: %s', extension)
|
||||
|
||||
converted_output = os.path.join(TEMPORARY_DIRECTORY, os.path.extsep.join([filename, 'pdf']))
|
||||
logger.debug('converted_output: %s', converted_output)
|
||||
|
||||
os.rename(converted_output, self.output_filepath)
|
||||
except OSError as exception:
|
||||
raise OfficeBackendError(exception)
|
||||
except Exception as exception:
|
||||
logger.error('Unhandled exception', exc_info=exception)
|
||||
@@ -178,7 +178,7 @@ class Link(object):
|
||||
kwargs = {key: Variable(value) for key, value in self.kwargs.iteritems()}
|
||||
|
||||
# Use Django's exact {% url %} code to resolve the link
|
||||
node = URLNode(view_name=view_name, args=args, kwargs={}, asvar=None)
|
||||
node = URLNode(view_name=view_name, args=args, kwargs=kwargs, asvar=None)
|
||||
|
||||
# If we were passed an instance of the view context object we are
|
||||
# resolving, inject it into the context. This help resolve links for
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from ast import literal_eval
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db import models
|
||||
|
||||
|
||||
class SourceTransformationManager(models.Manager):
|
||||
def get_for_object(self, obj):
|
||||
ct = ContentType.objects.get_for_model(obj)
|
||||
return self.model.objects.filter(content_type=ct).filter(object_id=obj.pk)
|
||||
|
||||
def get_for_object_as_list(self, obj):
|
||||
warnings = []
|
||||
transformations = []
|
||||
for transformation in self.get_for_object(obj).values('transformation', 'arguments'):
|
||||
try:
|
||||
transformations.append(
|
||||
{
|
||||
'transformation': transformation['transformation'],
|
||||
'arguments': literal_eval(transformation['arguments'].strip())
|
||||
}
|
||||
)
|
||||
except (ValueError, SyntaxError) as exception:
|
||||
warnings.append(exception)
|
||||
|
||||
return transformations, warnings
|
||||
Reference in New Issue
Block a user