124 lines
4.5 KiB
Python
124 lines
4.5 KiB
Python
# w.c.s. - web application for online forms
|
|
# Copyright (C) 2005-2012 Entr'ouvert
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# 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 collections
|
|
import json
|
|
import urllib2
|
|
|
|
from quixote.html import TemplateIO
|
|
from qommon.form import *
|
|
from qommon.misc import get_variadic_url
|
|
from qommon import get_logger
|
|
|
|
|
|
data_source_functions = {}
|
|
|
|
def register_data_source_function(function, function_name=None):
|
|
if not function_name:
|
|
function_name = function.__name__
|
|
if not function_name in data_source_functions:
|
|
data_source_functions[function_name] = function
|
|
|
|
|
|
class DataSourceSelectionWidget(CompositeWidget):
|
|
def __init__(self, name, value=None, allow_jsonp=True, **kwargs):
|
|
CompositeWidget.__init__(self, name, value, **kwargs)
|
|
|
|
if not value:
|
|
value = {}
|
|
|
|
options = [('none', _('None')),
|
|
('formula', _('Formula (Python)')),
|
|
('json', _('JSON URL'))]
|
|
if allow_jsonp:
|
|
options.append(('jsonp', _('JSONP URL')))
|
|
|
|
self.add(SingleSelectWidget, 'type', options = options, value = value.get('type'))
|
|
|
|
self.parse()
|
|
if not self.value:
|
|
self.value = {}
|
|
|
|
if self.value.get('type') in ('formula', 'json', 'jsonp'):
|
|
self.add(StringWidget, 'value', value = value.get('value'), size=80)
|
|
|
|
self.add(SubmitWidget, 'apply', value = _('Apply'))
|
|
|
|
self._parsed = False
|
|
|
|
def _parse(self, request):
|
|
values = {}
|
|
for name in ('type', 'value'):
|
|
value = self.get(name)
|
|
if value:
|
|
values[name] = value
|
|
if values.get('type', '') == 'none':
|
|
values = None
|
|
self.value = values or None
|
|
|
|
def render_content(self):
|
|
r = TemplateIO(html=True)
|
|
for widget in self.get_widgets():
|
|
r += widget.render_content()
|
|
return r.getvalue()
|
|
|
|
|
|
def get_items(data_source):
|
|
if data_source.get('type') == 'formula':
|
|
vars = get_publisher().substitutions.get_context_variables()
|
|
try:
|
|
value = eval(data_source.get('value'), vars, data_source_functions)
|
|
if not isinstance(value, collections.Iterable):
|
|
get_logger().warn('Python data source (%r) gave a non-iterable result' % \
|
|
data_source.get('value'))
|
|
return []
|
|
return value
|
|
except:
|
|
get_logger().warn('Failed to eval() Python data source (%r)' % data_source.get('value'))
|
|
return []
|
|
elif data_source.get('type') == 'json':
|
|
url = data_source.get('value')
|
|
if not url:
|
|
get_logger().warn('Empty URL in JSON data source')
|
|
return []
|
|
if '[' in url:
|
|
vars = get_publisher().substitutions.get_context_variables()
|
|
url = get_variadic_url(url, vars)
|
|
charset = get_publisher().site_charset
|
|
try:
|
|
results = []
|
|
entries = json.load(urllib2.urlopen(url))
|
|
if type(entries) is not dict:
|
|
raise ValueError('not a json dict')
|
|
if type(entries.get('data')) is not list:
|
|
raise ValueError('not a json dict with a data list attribute')
|
|
for entry in entries.get('data'):
|
|
id = entry.get('id')
|
|
text = entry.get('text')
|
|
if type(id) is unicode:
|
|
id = id.encode(charset)
|
|
if type(text) is unicode:
|
|
text = text.encode(charset)
|
|
results.append((id, text, id))
|
|
return results
|
|
except urllib2.HTTPError as e:
|
|
get_logger().warn('Error loading JSON data source (%s)' % str(e))
|
|
except urllib2.URLError as e:
|
|
get_logger().warn('Error loading JSON data source (%s)' % str(e))
|
|
except ValueError as e:
|
|
get_logger().warn('Error reading JSON data source output (%s)' % str(e))
|
|
return []
|