formdef: add support for files in workflow options (#15781)

This commit is contained in:
Frédéric Péters 2017-04-06 13:10:24 +02:00
parent 699e9f63b2
commit 62f0007524
3 changed files with 51 additions and 3 deletions

View File

@ -162,6 +162,27 @@ def test_workflow_options_with_no_values():
fd2 = assert_json_import_export_works(formdef)
assert fd2.workflow_options == formdef.workflow_options
def test_workflow_options_with_file():
from quixote.http_request import Upload
from wcs.qommon.form import UploadedFile
upload = Upload('/foo/bar', content_type='application/vnd.oasis.opendocument.text')
file_content = '''PK\x03\x04\x14\x00\x00\x08\x00\x00\'l\x8eG^\xc62\x0c\'\x00'''
upload.fp = StringIO.StringIO()
upload.fp.write(file_content)
upload.fp.seek(0)
model_file = UploadedFile(pub.APP_DIR, None, upload)
formdef = FormDef()
formdef.name = 'foo'
formdef.workflow_options = {'foo': model_file}
fd2 = assert_xml_import_export_works(formdef)
assert formdef.workflow_options['foo'].filename == fd2.workflow_options['foo'].filename
assert formdef.workflow_options['foo'].get_content() == fd2.workflow_options['foo'].get_content()
fd2 = assert_json_import_export_works(formdef)
assert formdef.workflow_options['foo'].filename == fd2.workflow_options['foo'].filename
assert formdef.workflow_options['foo'].get_content() == fd2.workflow_options['foo'].get_content()
def test_workflow_reference():
Workflow.wipe()
FormDef.wipe()

View File

@ -14,6 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
import base64
import new
import sys
import json
@ -21,6 +22,7 @@ import xml.etree.ElementTree as ET
import datetime
from quixote import get_request, get_publisher
from quixote.http_request import Upload
from qommon import _
from qommon.storage import StorableObject, fix_key
@ -699,6 +701,13 @@ class FormDef(StorableObject):
if value.get('options'):
formdef.workflow_options = value.get('options')
for option_key, option_value in formdef.workflow_options.items():
if isinstance(option_value, dict) and 'filename' in option_value:
filename = option_value['filename']
upload = Upload(filename, content_type=option_value['content_type'])
new_value = UploadedFile(get_publisher().app_dir, filename, upload)
new_value.set_content(base64.decodestring(option_value['content']))
formdef.workflow_options[option_key] = new_value
if value.get('geolocations'):
formdef.geolocations = value.get('geolocations')
@ -807,6 +816,11 @@ class FormDef(StorableObject):
option_value = self.workflow_options.get(option)
if isinstance(option_value, basestring):
element.text = unicode(self.workflow_options.get(option, ''), charset)
elif hasattr(option_value, 'base_filename'):
ET.SubElement(element, 'filename').text = option_value.base_filename
ET.SubElement(element, 'content_type').text = (
option_value.content_type or 'application/octet-stream')
ET.SubElement(element, 'content').text = base64.b64encode(option_value.get_content())
else:
pass # TODO: extend support to other types
@ -915,6 +929,11 @@ class FormDef(StorableObject):
option_value = None
if option.text:
option_value = option.text.encode(charset)
elif option.findall('filename'):
filename = option.find('filename').text
upload = Upload(filename, content_type=option.find('content_type').text)
option_value = UploadedFile(get_publisher().app_dir, filename, upload)
option_value.set_content(base64.decodestring(option.find('content').text))
formdef.workflow_options[option.attrib.get('varname')] = option_value
if tree.find('last_modification') is not None:

View File

@ -527,8 +527,7 @@ class UploadedFile: #pylint: disable=C1001
self.directory = directory
self.base_filename = upload.base_filename
self.content_type = upload.content_type
content = upload.fp.read()
self.size = len(content)
# Find a good filename
if filename:
self.filename = filename
@ -540,10 +539,16 @@ class UploadedFile: #pylint: disable=C1001
dir=self.dir_path())
os.close(fd)
self.filename = os.path.basename(filename)
if upload.fp:
self.set_content(upload.fp.read())
def set_content(self, content):
self.size = len(content)
file_path = self.build_file_path()
if not os.path.exists(self.dir_path()):
os.mkdir(self.dir_path())
file(file_path, 'w').write(content)
open(file_path, 'w').write(content)
def dir_path(self):
return os.path.join(get_publisher().app_dir, self.directory)
@ -555,6 +560,9 @@ class UploadedFile: #pylint: disable=C1001
def get_file(self):
return file(self.build_file_path())
def get_content(self):
return self.get_file().read()
def build_response(self):
response = get_response()
response.content_type = self.content_type