password input may be used with non eidparam fields...
importosfromlogilab.commonimportflattenfromcubicweb.vregistryimportobjectify_selectorfromcubicweb.web.viewsimportbaseviews@objectify_selectordefplot_selector(cls,req,rset,*args,**kwargs):"""accept result set with at least one line and two columns of result all columns after second must be of numerical types"""ifrsetisNone:return0ifnotlen(rset):return0iflen(rset.rows[0])<2:return0foretypeinrset.description[0]:ifetypenotin('Int','Float'):return0return1try:importmatplotlibimportsysif'matplotlib.backends'notinsys.modules:matplotlib.use('Agg')frompylabimportfigureexceptImportError:passelse:classPlotView(baseviews.AnyRsetView):id='plot'title=_('generic plot')binary=Truecontent_type='image/png'_plot_count=0__select__=plot_selector()defcall(self,width=None,height=None):# compute dimensionsifwidthisNone:if'width'inself.req.form:width=int(self.req.form['width'])else:width=500ifheightisNone:if'height'inself.req.form:height=int(self.req.form['height'])else:height=400dpi=100.# compute dataabscisses=[row[0]forrowinself.rset]courbes=[]nbcols=len(self.rset.rows[0])forcolinxrange(1,nbcols):courbe=[row[col]forrowinself.rset]courbes.append(courbe)ifnotcourbes:raiseException('no data')# plot datafig=figure(figsize=(width/dpi,height/dpi),dpi=dpi)ax=fig.add_subplot(111)colors='brgybrgy'try:float(abscisses[0])xlabels=NoneexceptValueError:xlabels=abscissesabscisses=range(len(xlabels))foridx,courbeinenumerate(courbes):ax.plot(abscisses,courbe,'%sv-'%colors[idx],label=self.rset.description[0][idx+1])ax.autoscale_view()alldata=flatten(courbes)m,M=min(alldataor[0]),max(alldataor[1])ifmisNone:m=0ifMisNone:M=0margin=float(M-m)/10ax.set_ylim(m-margin,M+margin)ax.grid(True)ax.legend(loc='best')ifxlabelsisnotNone:ax.set_xticks(abscisses)ax.set_xticklabels(xlabels)try:fig.autofmt_xdate()exceptAttributeError:# XXX too old version of matplotlib. Ignore safely.pass# save plotfilename=self.build_figname()fig.savefig(filename,dpi=100)img=open(filename,'rb')self.w(img.read())img.close()os.remove(filename)defbuild_figname(self):self.__class__._plot_count+=1return'/tmp/burndown_chart_%s_%d.png'%(self.config.appid,self.__class__._plot_count)