[uilib] refactor json_dumps code organization
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 08 Jul 2010 13:33:40 +0200
changeset 5940 0e3ae19b181a
parent 5939 a33402c1aa79
child 5941 f6c890ad4fd4
[uilib] refactor json_dumps code organization
etwist/server.py
utils.py
web/__init__.py
web/_exceptions.py
web/component.py
web/request.py
web/test/unittest_views_basecontrollers.py
web/test/unittest_views_baseviews.py
web/views/autoform.py
web/views/basecontrollers.py
web/views/editforms.py
web/views/facets.py
web/views/formrenderers.py
web/views/igeocodable.py
web/views/plots.py
web/views/reledit.py
web/views/tableview.py
web/views/timeline.py
web/views/treeview.py
--- a/etwist/server.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/etwist/server.py	Thu Jul 08 13:33:40 2010 +0200
@@ -38,11 +38,11 @@
 from twisted.web import static, resource
 from twisted.web.server import NOT_DONE_YET
 
-from cubicweb.web import dumps
 
 from logilab.common.decorators import monkeypatch
 
 from cubicweb import AuthenticationError, ConfigurationError, CW_EVENT_MANAGER
+from cubicweb.utils import json_dumps
 from cubicweb.web import Redirect, DirectResponse, StatusResponse, LogOut
 from cubicweb.web.application import CubicWebPublisher
 from cubicweb.web.http_headers import generateDateTime
@@ -317,12 +317,12 @@
         self.setResponseCode(http.BAD_REQUEST)
         if path in JSON_PATHS: # XXX better json path detection
             self.setHeader('content-type',"application/json")
-            body = dumps({'reason': 'request max size exceeded'})
+            body = json_dumps({'reason': 'request max size exceeded'})
         elif path in FRAME_POST_PATHS: # XXX better frame post path detection
             self.setHeader('content-type',"text/html")
             body = ('<script type="text/javascript">'
                     'window.parent.handleFormValidationResponse(null, null, null, %s, null);'
-                    '</script>' % dumps( (False, 'request max size exceeded', None) ))
+                    '</script>' % json_dumps( (False, 'request max size exceeded', None) ))
         else:
             self.setHeader('content-type',"text/html")
             body = ("<html><head><title>Processing Failed</title></head><body>"
--- a/utils.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/utils.py	Thu Jul 08 13:33:40 2010 +0200
@@ -327,12 +327,13 @@
 
 try:
     # may not be there if cubicweb-web not installed
-    if sys.version_info < (2,6):
+    if sys.version_info < (2, 6):
         import simplejson as json
     else:
         import json
 except ImportError:
-    pass
+    json_dumps = None
+
 else:
 
     class CubicWebJsonEncoder(json.JSONEncoder):
@@ -360,6 +361,9 @@
                 # just return None in those cases.
                 return None
 
+    def json_dumps(value):
+        return json.dumps(value, cls=CubicWebJsonEncoder)
+
 
 @deprecated('[3.7] merge_dicts is deprecated')
 def merge_dicts(dict1, dict2):
--- a/web/__init__.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/web/__init__.py	Thu Jul 08 13:33:40 2010 +0200
@@ -22,20 +22,14 @@
 __docformat__ = "restructuredtext en"
 _ = unicode
 
-import sys
-if sys.version_info < (2,6):
-    import simplejson as json
-else:
-    import json
-
-dumps = json.dumps
-
 from urllib import quote as urlquote
 
 from logilab.common.deprecation import deprecated
 
 from cubicweb.web._exceptions import *
-from cubicweb.utils import CubicWebJsonEncoder
+from cubicweb.utils import json_dumps
+
+dumps = deprecated('[3.9] use cubicweb.utils.json_dumps instead of dumps')(json_dumps)
 
 INTERNAL_FIELD_VALUE = '__cubicweb_internal_field__'
 
@@ -64,9 +58,6 @@
 FACETTES = set()
 
 
-def json_dumps(value):
-    return dumps(value, cls=CubicWebJsonEncoder)
-
 def jsonize(function):
     def newfunc(*args, **kwargs):
         value = function(*args, **kwargs)
--- a/web/_exceptions.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/web/_exceptions.py	Thu Jul 08 13:33:40 2010 +0200
@@ -16,12 +16,12 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""exceptions used in the core of the CubicWeb web application
+"""exceptions used in the core of the CubicWeb web application"""
 
-"""
 __docformat__ = "restructuredtext en"
 
 from cubicweb._exceptions import *
+from cubicweb.utils import json_dumps
 
 class PublishException(CubicWebException):
     """base class for publishing related exception"""
@@ -66,8 +66,7 @@
         self.reason = reason
 
     def dumps(self):
-        from cubicweb.web import json
-        return json.dumps({'reason': self.reason})
+        return json_dumps({'reason': self.reason})
 
 class LogOut(PublishException):
     """raised to ask for deauthentication of a logged in user"""
--- a/web/component.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/web/component.py	Thu Jul 08 13:33:40 2010 +0200
@@ -26,7 +26,7 @@
 from logilab.mtconverter import xml_escape
 
 from cubicweb import role
-from cubicweb.web import json
+from cubicweb.utils import json_dumps
 from cubicweb.view import Component
 from cubicweb.selectors import (
     paginated_rset, one_line_rset, primary_view, match_context_prop,
@@ -146,9 +146,9 @@
             rql = params.pop('rql', self.cw_rset.printable_rql())
             # latest 'true' used for 'swap' mode
             url = 'javascript: replacePageChunk(%s, %s, %s, %s, true)' % (
-                json.dumps(params.get('divid', 'pageContent')),
-                json.dumps(rql), json.dumps(params.pop('vid', None)),
-                json.dumps(params))
+                json_dumps(params.get('divid', 'pageContent')),
+                json_dumps(rql), json_dumps(params.pop('vid', None)),
+                json_dumps(params))
         else:
             url = self._cw.build_url(path, **params)
         return url
--- a/web/request.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/web/request.py	Thu Jul 08 13:33:40 2010 +0200
@@ -37,14 +37,12 @@
 from cubicweb.dbapi import DBAPIRequest
 from cubicweb.mail import header
 from cubicweb.uilib import remove_html_tags
-from cubicweb.utils import SizeConstrainedList, HTMLHead, make_uid
+from cubicweb.utils import SizeConstrainedList, HTMLHead, make_uid, json_dumps
 from cubicweb.view import STRICT_DOCTYPE, TRANSITIONAL_DOCTYPE_NOEXT
 from cubicweb.web import (INTERNAL_FIELD_VALUE, LOGGER, NothingToEdit,
-                          RequestError, StatusResponse, json)
+                          RequestError, StatusResponse)
 from cubicweb.web.http_headers import Headers
 
-dumps = json.dumps
-
 _MARKER = object()
 
 
@@ -358,7 +356,7 @@
         """
         self.add_js('cubicweb.ajax.js')
         cbname = self.register_onetime_callback(cb, *args)
-        msg = dumps(msg or '')
+        msg = json_dumps(msg or '')
         return "javascript:userCallbackThenReloadPage('%s', %s)" % (
             cbname, msg)
 
@@ -592,7 +590,7 @@
         extraparams.setdefault('fname', 'view')
         url = self.build_url('json', **extraparams)
         return "javascript: $('#%s').loadxhtml(%s, null, 'get', '%s'); noop()" % (
-                nodeid, dumps(url), replacemode)
+                nodeid, json_dumps(url), replacemode)
 
     # urls/path management ####################################################
 
--- a/web/test/unittest_views_basecontrollers.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/web/test/unittest_views_basecontrollers.py	Thu Jul 08 13:33:40 2010 +0200
@@ -15,15 +15,14 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""cubicweb.web.views.basecontrollers unit tests
-
-"""
+"""cubicweb.web.views.basecontrollers unit tests"""
 
 from logilab.common.testlib import unittest_main, mock_object
 
 from cubicweb import Binary, NoSelectableObject, ValidationError
 from cubicweb.view import STRICT_DOCTYPE
 from cubicweb.devtools.testlib import CubicWebTC
+from cubicweb.utils import json_dumps
 from cubicweb.uilib import rql_for_eid
 from cubicweb.web import INTERNAL_FIELD_VALUE, Redirect, RequestError, json
 from cubicweb.entities.authobjs import CWUser
@@ -562,7 +561,7 @@
 #         rql = 'Any T,N WHERE T is Tag, T name N'
 #         ctrl = self.ctrl(self.request(mode='json', rql=rql, pageid='123'))
 #         self.assertEquals(ctrl.publish(),
-#                           json.dumps(self.execute(rql).rows))
+#                           json_dumps(self.execute(rql).rows))
 
     def test_remote_add_existing_tag(self):
         self.remote_call('tag_entity', self.john.eid, ['python'])
@@ -643,14 +642,14 @@
     # silly tests
     def test_external_resource(self):
         self.assertEquals(self.remote_call('external_resource', 'RSS_LOGO')[0],
-                          json.dumps(self.config.uiprops['RSS_LOGO']))
+                          json_dumps(self.config.uiprops['RSS_LOGO']))
     def test_i18n(self):
         self.assertEquals(self.remote_call('i18n', ['bimboom'])[0],
-                          json.dumps(['bimboom']))
+                          json_dumps(['bimboom']))
 
     def test_format_date(self):
         self.assertEquals(self.remote_call('format_date', '2007-01-01 12:00:00')[0],
-                          json.dumps('2007/01/01'))
+                          json_dumps('2007/01/01'))
 
 
 
--- a/web/test/unittest_views_baseviews.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/web/test/unittest_views_baseviews.py	Thu Jul 08 13:33:40 2010 +0200
@@ -15,21 +15,17 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
 
-"""
 from logilab.common.testlib import unittest_main
 from logilab.mtconverter import html_unescape
 
 from cubicweb.devtools.testlib import CubicWebTC
-
+from cubicweb.utils import json
 from cubicweb.web.htmlwidgets import TableWidget
 from cubicweb.web.views import vid_from_rset
-from cubicweb.web import json
-loads = json.loads
 
 def loadjson(value):
-    return loads(html_unescape(value))
+    return json.loads(html_unescape(value))
 
 class VidFromRsetTC(CubicWebTC):
 
--- a/web/views/autoform.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/web/views/autoform.py	Thu Jul 08 13:33:40 2010 +0200
@@ -134,8 +134,9 @@
 from cubicweb.selectors import (
     match_kwargs, match_form_params, non_final_entity,
     specified_etype_implements)
-from cubicweb.web import stdmsgs, uicfg, eid_param, dumps, \
-     form as f, formwidgets as fw, formfields as ff
+from cubicweb.utils import json_dumps
+from cubicweb.web import (stdmsgs, uicfg, eid_param,
+                          form as f, formwidgets as fw, formfields as ff)
 from cubicweb.web.views import forms
 
 _AFS = uicfg.autoform_section
@@ -374,7 +375,7 @@
     entities
     """
     js = u"javascript: togglePendingDelete('%s', %s);" % (
-        nodeid, xml_escape(dumps(eid)))
+        nodeid, xml_escape(json_dumps(eid)))
     return u'[<a class="handle" href="%s" id="handle%s">%s</a>]' % (
         js, nodeid, label)
 
@@ -475,7 +476,7 @@
         w(u'<th class="labelCol">')
         w(u'<select id="relationSelector_%s" tabindex="%s" '
           'onchange="javascript:showMatchingSelect(this.options[this.selectedIndex].value,%s);">'
-          % (eid, req.next_tabindex(), xml_escape(dumps(eid))))
+          % (eid, req.next_tabindex(), xml_escape(json_dumps(eid))))
         w(u'<option value="">%s</option>' % _('select a relation'))
         for i18nrtype, rschema, role in field.relations:
             # more entities to link to
@@ -599,7 +600,7 @@
   </select>
 </div>
 """ % (hidden and 'hidden' or '', divid, selectid,
-       xml_escape(dumps(entity.eid)), is_cell and 'true' or 'null', relname,
+       xml_escape(json_dumps(entity.eid)), is_cell and 'true' or 'null', relname,
        '\n'.join(options))
 
     def _get_select_options(self, entity, rschema, role):
--- a/web/views/basecontrollers.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/web/views/basecontrollers.py	Thu Jul 08 13:33:40 2010 +0200
@@ -26,11 +26,10 @@
 
 from cubicweb import (NoSelectableObject, ObjectNotFound, ValidationError,
                       AuthenticationError, typed_eid)
-from cubicweb.utils import CubicWebJsonEncoder
+from cubicweb.utils import json, json_dumps
 from cubicweb.selectors import authenticated_user, anonymous_user, match_form_params
 from cubicweb.mail import format_mail
-from cubicweb.web import (Redirect, RemoteCallFailed, DirectResponse,
-                          json, json_dumps)
+from cubicweb.web import Redirect, RemoteCallFailed, DirectResponse
 from cubicweb.web.controller import Controller
 from cubicweb.web.views import vid_from_rset, formrenderers
 
@@ -42,7 +41,7 @@
     HAS_SEARCH_RESTRICTION = False
 
 def jsonize(func):
-    """decorator to sets correct content_type and calls `json.dumps` on
+    """decorator to sets correct content_type and calls `json_dumps` on
     results
     """
     def wrapper(self, *args, **kwargs):
--- a/web/views/editforms.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/web/views/editforms.py	Thu Jul 08 13:33:40 2010 +0200
@@ -33,7 +33,7 @@
                                 specified_etype_implements, is_instance, yes)
 from cubicweb.view import EntityView
 from cubicweb.schema import display_name
-from cubicweb.web import uicfg, stdmsgs, eid_param, dumps, \
+from cubicweb.web import uicfg, stdmsgs, eid_param, \
      formfields as ff, formwidgets as fw
 from cubicweb.web.form import FormViewMixIn, FieldNotFound
 from cubicweb.web.views import forms, reledit
--- a/web/views/facets.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/web/views/facets.py	Thu Jul 08 13:33:40 2010 +0200
@@ -15,9 +15,8 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""the facets box and some basic facets
+"""the facets box and some basic facets"""
 
-"""
 __docformat__ = "restructuredtext en"
 
 from logilab.mtconverter import xml_escape
@@ -25,7 +24,7 @@
 from cubicweb.appobject import objectify_selector
 from cubicweb.selectors import (non_final_entity, multi_lines_rset,
                                 match_context_prop, yes, relation_possible)
-from cubicweb.web import dumps
+from cubicweb.utils import json_dumps
 from cubicweb.web.box import BoxTemplate
 from cubicweb.web.facet import (AbstractFacet, FacetStringWidget, RelationFacet,
                                 prepare_facets_rqlst, filter_hiddens, _cleanup_rqlst,
@@ -102,7 +101,7 @@
             self.display_bookmark_link(rset)
         w = self.w
         w(u'<form method="post" id="%sForm" cubicweb:facetargs="%s" action="">'  % (
-            divid, xml_escape(dumps([divid, vid, paginate, self.facetargs()]))))
+            divid, xml_escape(json_dumps([divid, vid, paginate, self.facetargs()]))))
         w(u'<fieldset>')
         hiddens = {'facets': ','.join(wdg.facet.__regid__ for wdg in widgets),
                    'baserql': baserql}
--- a/web/views/formrenderers.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/web/views/formrenderers.py	Thu Jul 08 13:33:40 2010 +0200
@@ -41,7 +41,8 @@
 from cubicweb import tags
 from cubicweb.appobject import AppObject
 from cubicweb.selectors import is_instance, yes
-from cubicweb.web import dumps, eid_param, formwidgets as fwdgs
+from cubicweb.utils import json_dumps
+from cubicweb.web import eid_param, formwidgets as fwdgs
 
 
 def checkbox(name, value, attrs='', checked=None):
@@ -359,7 +360,7 @@
             values = form.form_previous_values
             qeid = eid_param('eid', entity.eid)
             cbsetstate = "setCheckboxesState('eid', %s, 'checked')" % \
-                         xml_escape(dumps(entity.eid))
+                         xml_escape(json_dumps(entity.eid))
             w(u'<tr class="%s">' % (entity.cw_row % 2 and u'even' or u'odd'))
             # XXX turn this into a widget used on the eid field
             w(u'<td>%s</td>' % checkbox('eid', entity.eid,
--- a/web/views/igeocodable.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/web/views/igeocodable.py	Thu Jul 08 13:33:40 2010 +0200
@@ -22,7 +22,7 @@
 from cubicweb.interfaces import IGeocodable
 from cubicweb.view import EntityView, EntityAdapter, implements_adapter_compat
 from cubicweb.selectors import implements, adaptable
-from cubicweb.web import json
+from cubicweb.utils import json_dumps
 
 class IGeocodableAdapter(EntityAdapter):
     """interface required by geocoding views such as gmap-view"""
@@ -82,7 +82,7 @@
             'center': center,
             'markers': markers,
             }
-        self.w(json.dumps(geodata))
+        self.w(json_dumps(geodata))
 
     def build_marker_data(self, entity, igeocodable, extraparams):
         return {'latitude': igeocodable.latitude,
--- a/web/views/plots.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/web/views/plots.py	Thu Jul 08 13:33:40 2010 +0200
@@ -23,10 +23,9 @@
 from logilab.common.date import datetime2ticks
 from logilab.mtconverter import xml_escape
 
-from cubicweb.utils import UStringIO
+from cubicweb.utils import UStringIO, json_dumps
 from cubicweb.appobject import objectify_selector
 from cubicweb.selectors import multi_columns_rset
-from cubicweb.web import dumps
 from cubicweb.web.views import baseviews
 
 @objectify_selector
@@ -107,7 +106,7 @@
         #     cf. function onPlotHover in cubicweb.flot.js
         if self.timemode:
             plot = [(datetime2ticks(x), y, datetime2ticks(x)) for x, y in plot]
-        return dumps(plot)
+        return json_dumps(plot)
 
     def _render(self, req, width=500, height=400):
         if req.ie_browser():
--- a/web/views/reledit.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/web/views/reledit.py	Thu Jul 08 13:33:40 2010 +0200
@@ -1,10 +1,30 @@
+# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of CubicWeb.
+#
+# CubicWeb is free software: you can redistribute it and/or modify it under the
+# terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option)
+# any later version.
+#
+# CubicWeb 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 Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
+"""the 'reedit' feature (eg edit attribute/relation from primary view)
+"""
+
 import copy
 
 from logilab.mtconverter import xml_escape
 
 from cubicweb import neg_role
 from cubicweb.schema import display_name
-from cubicweb.utils import json
+from cubicweb.utils import json_dumps
 from cubicweb.selectors import non_final_entity, match_kwargs
 from cubicweb.view import EntityView
 from cubicweb.web import uicfg, stdmsgs
@@ -194,7 +214,7 @@
                     extradata=None):
         divid = self._build_divid(rtype, role, entity.eid)
         event_args = {'divid' : divid, 'eid' : entity.eid, 'rtype' : rtype, 'formid': formid,
-                      'reload' : json.dumps(reload), 'default_value' : default_value,
+                      'reload' : json_dumps(reload), 'default_value' : default_value,
                       'role' : role, 'vid' : u''}
         if extradata:
             event_args.update(extradata)
--- a/web/views/tableview.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/web/views/tableview.py	Thu Jul 08 13:33:40 2010 +0200
@@ -16,17 +16,13 @@
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
 """generic table view, including filtering abilities"""
+
 __docformat__ = "restructuredtext en"
 
-try:
-    from json import dumps
-except ImportError:
-    from simplejson import dumps
-
 from logilab.mtconverter import xml_escape
 
 from cubicweb.selectors import nonempty_rset, match_form_params
-from cubicweb.utils import make_uid
+from cubicweb.utils import make_uid, json_dumps
 from cubicweb.view import EntityView, AnyRsetView
 from cubicweb import tags
 from cubicweb.uilib import toggle_action, limitsize, htmlescape
@@ -77,7 +73,7 @@
         # drop False / None values from vidargs
         vidargs = dict((k, v) for k, v in vidargs.iteritems() if v)
         w(u'<form method="post" cubicweb:facetargs="%s" action="">' %
-          xml_escape(dumps([divid, self.__regid__, False, vidargs])))
+          xml_escape(json_dumps([divid, self.__regid__, False, vidargs])))
         w(u'<fieldset id="%sForm" class="%s">' % (divid, hidden and 'hidden' or ''))
         w(u'<input type="hidden" name="divid" value="%s" />' % divid)
         w(u'<input type="hidden" name="fromformfilter" value="1" />')
@@ -197,7 +193,8 @@
         rql = params.pop('rql', self.cw_rset.printable_rql())
         # latest 'true' used for 'swap' mode
         return 'javascript: replacePageChunk(%s, %s, %s, %s, true)' % (
-            dumps(divid), dumps(rql), dumps(self.__regid__), dumps(params))
+            json_dumps(divid), json_dumps(rql), json_dumps(self.__regid__),
+            json_dumps(params))
 
     def show_hide_actions(self, divid, currentlydisplayed=False):
         showhide = u';'.join(toggle_action('%s%s' % (divid, what))[11:]
--- a/web/views/timeline.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/web/views/timeline.py	Thu Jul 08 13:33:40 2010 +0200
@@ -26,7 +26,7 @@
 
 from cubicweb.selectors import adaptable
 from cubicweb.view import EntityView, StartupView
-from cubicweb.web import json
+from cubicweb.utils import json_dumps
 
 _ = unicode
 
@@ -52,7 +52,7 @@
                 events.append(event)
         timeline_data = {'dateTimeFormat': self.date_fmt,
                          'events': events}
-        self.w(json.dumps(timeline_data))
+        self.w(json_dumps(timeline_data))
 
     # FIXME: those properties should be defined by the entity class
     def onclick_url(self, entity):
--- a/web/views/treeview.py	Thu Jul 08 12:54:28 2010 +0200
+++ b/web/views/treeview.py	Thu Jul 08 13:33:40 2010 +0200
@@ -25,11 +25,10 @@
 
 from logilab.mtconverter import xml_escape
 
-from cubicweb.utils import make_uid
+from cubicweb.utils import make_uid, json
 from cubicweb.selectors import adaptable
 from cubicweb.view import EntityView
 from cubicweb.mixins import _done_init
-from cubicweb.web import json
 from cubicweb.web.views import baseviews
 
 def treecookiename(treeid):