[service] allow repo_stats for users
It's used by the siteinfo view, which is available to managers and
users. This change prevents a crash in that view.
# copyright 2003-2012 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/>."""basic plot views"""__docformat__="restructuredtext en"_=unicodefromlogilab.common.dateimportdatetime2ticksfromlogilab.common.deprecationimportclass_deprecatedfromlogilab.common.registryimportobjectify_predicatefromlogilab.mtconverterimportxml_escapefromcubicweb.utilsimportUStringIO,json_dumpsfromcubicweb.predicatesimportmulti_columns_rsetfromcubicweb.web.viewsimportbaseviews@objectify_predicatedefall_columns_are_numbers(cls,req,rset=None,*args,**kwargs):"""accept result set with at least one line and two columns of result all columns after second must be of numerical types"""foretypeinrset.description[0]:ifetypenotin('Int','BigInt','Float'):return0return1@objectify_predicatedefsecond_column_is_number(cls,req,rset=None,*args,**kwargs):etype=rset.description[0][1]ifetypenotin('Int','BigInt','Float'):return0return1@objectify_predicatedefcolumns_are_date_then_numbers(cls,req,rset=None,*args,**kwargs):etypes=rset.description[0]ifetypes[0]notin('Date','Datetime','TZDatetime'):return0foretypeinetypes[1:]:ifetypenotin('Int','BigInt','Float'):return0return1deffilterout_nulls(abscissa,plot):filtered=[]forx,yinzip(abscissa,plot):ifxisNoneoryisNone:continuefiltered.append((x,y))returnsorted(filtered)classPlotWidget(object):# XXX refactor with cubicweb.web.views.htmlwidgets.HtmlWidgetdef_initialize_stream(self,w=None):ifw:self.w=welse:self._stream=UStringIO()self.w=self._stream.writedefrender(self,*args,**kwargs):w=kwargs.pop('w',None)self._initialize_stream(w)self._render(*args,**kwargs)ifwisNone:returnself._stream.getvalue()def_render(self,*args,**kwargs):raiseNotImplementedErrorclassFlotPlotWidget(PlotWidget):"""PlotRenderer widget using Flot"""__metaclass__=class_deprecated__deprecation_warning__='[3.14] cubicweb.web.views.plots module is deprecated, use the jqplot cube instead'onload=u"""var fig = jQuery('#%(figid)s');if (fig.attr('cubicweb:type') != 'prepared-plot') {%(plotdefs)s jQuery.plot(jQuery('#%(figid)s'), [%(plotdata)s], {points: {show: true}, lines: {show: true}, grid: {hoverable: true}, /*yaxis : {tickFormatter : suffixFormatter},*/ xaxis: {mode: %(mode)s}}); jQuery('#%(figid)s').data({mode: %(mode)s, dateformat: %(dateformat)s}); jQuery('#%(figid)s').bind('plothover', onPlotHover); fig.attr('cubicweb:type','prepared-plot');}"""def__init__(self,labels,plots,timemode=False):self.labels=labelsself.plots=plots# list of list of couplesself.timemode=timemodedefdump_plot(self,plot):ifself.timemode:plot=[(datetime2ticks(x),y)forx,yinplot]returnjson_dumps(plot)def_render(self,req,width=500,height=400):ifreq.ie_browser():req.add_js('excanvas.js')req.add_js(('jquery.flot.js','cubicweb.flot.js'))figid=u'figure%s'%req.varmaker.next()plotdefs=[]plotdata=[]self.w(u'<div id="%s" style="width: %spx; height: %spx;"></div>'%(figid,width,height))foridx,(label,plot)inenumerate(zip(self.labels,self.plots)):plotid='%s_%s'%(figid,idx)plotdefs.append('var %s = %s;'%(plotid,self.dump_plot(plot)))# XXX ugly but required in order to not crash my demoplotdata.append("{label: '%s', data: %s}"%(label.replace(u'&',u''),plotid))fmt=req.property_value('ui.date-format')# XXX datetime-format# XXX TODO make plot options customizablereq.html_headers.add_onload(self.onload%{'plotdefs':'\n'.join(plotdefs),'figid':figid,'plotdata':','.join(plotdata),'mode':self.timemodeand"'time'"or'null','dateformat':'"%s"'%fmt})classPlotView(baseviews.AnyRsetView):__metaclass__=class_deprecated__deprecation_warning__='[3.14] cubicweb.web.views.plots module is deprecated, use the jqplot cube instead'__regid__='plot'title=_('generic plot')__select__=multi_columns_rset()&all_columns_are_numbers()timemode=Falsepaginable=Falsedefcall(self,width=500,height=400):# prepare datarqlst=self.cw_rset.syntax_tree()# XXX try to make it work with unionsvarnames=[var.nameforvarinrqlst.children[0].get_selected_variables()][1:]abscissa=[row[0]forrowinself.cw_rset]plots=[]nbcols=len(self.cw_rset.rows[0])forcolinxrange(1,nbcols):data=[row[col]forrowinself.cw_rset]plots.append(filterout_nulls(abscissa,data))plotwidget=FlotPlotWidget(varnames,plots,timemode=self.timemode)plotwidget.render(self._cw,width,height,w=self.w)classTimeSeriePlotView(PlotView):__select__=multi_columns_rset()&columns_are_date_then_numbers()timemode=Truetry:fromGChartWrapperimportPie,Pie3DexceptImportError:passelse:classPieChartWidget(PlotWidget):def__init__(self,labels,values,pieclass=Pie,title=None):self.labels=labelsself.values=valuesself.pieclass=pieclassself.title=titledef_render(self,width=None,height=None):piechart=self.pieclass(self.values)piechart.label(*self.labels)ifwidthisnotNone:height=heightorwidthpiechart.size(width,height)ifself.title:piechart.title(self.title)self.w(u'<img src="%s" />'%xml_escape(piechart.url))classPieChartView(baseviews.AnyRsetView):__regid__='piechart'pieclass=Piepaginable=False__select__=multi_columns_rset()&second_column_is_number()def_guess_vid(self,row):etype=self.cw_rset.description[row][0]ifself._cw.vreg.schema.eschema(etype).final:return'final'return'textincontext'defcall(self,title=None,width=None,height=None):labels=[]values=[]forrowidx,(_,value)inenumerate(self.cw_rset):ifvalueisnotNone:vid=self._guess_vid(rowidx)label='%s: %s'%(self._cw.view(vid,self.cw_rset,row=rowidx,col=0),value)labels.append(label.encode(self._cw.encoding))values.append(value)pie=PieChartWidget(labels,values,pieclass=self.pieclass,title=title)ifwidthisnotNone:height=heightorwidthpie.render(width,height,w=self.w)classPieChart3DView(PieChartView):__regid__='piechart3D'pieclass=Pie3D