[multi-sources-removal] Drop pyrorql and zmqrql sources
After a few years experementing "true" multi-sources, we're now
moving to "copy-based" source à la datafeed.
As pyro and zmq sources have no more known customers and the related
code is in the way of future refactoring of cubicweb's core, we decided
to drop support for those sources without backward compatibility.
If you're still using a zmqrql or pyrorql source and you want to upgrade,
ask support to move it to datafeed using a pre-3.19 version first.
Related to #2919300 (first step)
# copyright 2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.# contact http://www.logilab.fr -- mailto:contact@logilab.fr## This program 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.## 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 Lesser General Public License for more# details.## You should have received a copy of the GNU Lesser General Public License along# with this program. If not, see <http://www.gnu.org/licenses/>."""Instrumentation utilities"""importostry:importpygraphvizexceptImportError:pygraphviz=Nonefromcubicweb.cwvregimportCWRegistryStorefromcubicweb.devtools.devctlimportDevConfigurationALL_COLORS=["00FF00","0000FF","FFFF00","FF00FF","00FFFF","000000","800000","008000","000080","808000","800080","008080","808080","C00000","00C000","0000C0","C0C000","C000C0","00C0C0","C0C0C0","400000","004000","000040","404000","400040","004040","404040","200000","002000","000020","202000","200020","002020","202020","600000","006000","000060","606000","600060","006060","606060","A00000","00A000","0000A0","A0A000","A000A0","00A0A0","A0A0A0","E00000","00E000","0000E0","E0E000","E000E0","00E0E0","E0E0E0",]_COLORS={}defget_color(key):try:return_COLORS[key]exceptKeyError:_COLORS[key]='#'+ALL_COLORS[len(_COLORS)%len(ALL_COLORS)]return_COLORS[key]defwarn(msg,*args):print'WARNING: %s'%(msg%args)definfo(msg):print'INFO: '+msgclassPropagationAnalyzer(object):"""Abstract propagation analyzer, providing utility function to extract entities involved in propagation from a schema, as well as propagation rules from hooks (provided they use intrumentalized sets, see :class:`CubeTracerSet`). Concrete classes should at least define `prop_rel` class attribute and implements the `is_root` method. See `localperms` or `nosylist` cubes for example usage (`ccplugin` module). """prop_rel=None# name of the propagation relationdefinit(self,cube):"""Initialize analyze for the given cube, returning the (already loaded) vregistry and a set of entities which we're interested in. """config=DevConfiguration(cube)schema=config.load_schema()vreg=CWRegistryStore(config)vreg.set_schema(schema)# set_schema triggers objects registrationseschemas=set(eschemaforeschemainschema.entities()ifself.should_include(eschema))returnvreg,eschemasdefis_root(self,eschema):"""Return `True` if given entity schema is a root of the graph"""raiseNotImplementedError()defshould_include(self,eschema):"""Return `True` if given entity schema should be included by the graph. """ifself.prop_relineschema.subjrelsorself.is_root(eschema):returnTruereturnFalsedefprop_edges(self,s_rels,o_rels,eschemas):"""Return a set of edges where propagation has been detected. Each edge is defined by a 4-uple (from node, to node, rtype, package) where `rtype` is the relation type bringing from <from node> to <to node> and `package` is the cube adding the rule to the propagation control set (see see :class:`CubeTracerSet`). """schema=iter(eschemas).next().schemaprop_edges=set()forrtypeins_rels:found=Falseforsubj,objinschema.rschema(rtype).rdefs:ifsubjineschemasandobjineschemas:found=Trueprop_edges.add((subj,obj,rtype,s_rels.value_cube[rtype]))ifnotfound:warn('no rdef match for %s',rtype)forrtypeino_rels:found=Falseforsubj,objinschema.rschema(rtype).rdefs:ifsubjineschemasandobjineschemas:found=Trueprop_edges.add((obj,subj,rtype,o_rels.value_cube[rtype]))ifnotfound:warn('no rdef match for %s',rtype)returnprop_edgesdefdetect_problems(self,eschemas,edges):"""Given the set of analyzed entity schemas and edges between them, return a set of entity schemas where a problem has been detected. """problematic=set()foreschemaineschemas:ifself.has_problem(eschema,edges):problematic.add(eschema)not_problematic=set(eschemas).difference(problematic)ifnot_problematic:info('nothing problematic in: %s'%', '.join(e.typeforeinnot_problematic))returnproblematicdefhas_problem(self,eschema,edges):"""Return `True` if the given schema is considered problematic, considering base propagation rules. """root=self.is_root(eschema)has_prop_rel=self.prop_relineschema.subjrels# root but no propagation relationifrootandnothas_prop_rel:warn('%s is root but miss %s',eschema,self.prop_rel)returnTrue# propagated but without propagation relation / not propagated but# with propagation relationifnothas_prop_reland \any(edgeforedgeinedgesifedge[1]==eschema):warn("%s miss %s but is reached by propagation",eschema,self.prop_rel)returnTrueelifhas_prop_relandnotroot:rdef=eschema.rdef(self.prop_rel,takefirst=True)edges=[edgeforedgeinedgesifedge[1]==eschema]ifnotedges:warn("%s has %s but isn't reached by ""propagation",eschema,self.prop_rel)returnTrue# require_permission relation / propagation rule not added by# the same cubeelifnotany(edgeforedgeinedgesifedge[-1]==rdef.package):warn('%s has %s relation / propagation rule'' not added by the same cube (%s / %s)',eschema,self.prop_rel,rdef.package,edges[0][-1])returnTruereturnFalsedefinit_graph(self,eschemas,edges,problematic):"""Initialize and return graph, adding given nodes (entity schemas) and edges between them. Require pygraphviz installed. """ifpygraphvizisNone:raiseRuntimeError('pygraphviz is not installed')graph=pygraphviz.AGraph(strict=False,directed=True)foreschemaineschemas:ifeschemainproblematic:params={'color':'#ff0000','fontcolor':'#ff0000'}else:params={}#'color': get_color(eschema.package)}graph.add_node(eschema.type,**params)forsubj,obj,rtype,packageinedges:graph.add_edge(str(subj),str(obj),label=rtype,color=get_color(package))returngraphdefadd_colors_legend(self,graph):"""Add a legend of used colors to the graph."""forpackage,colorinsorted(_COLORS.iteritems()):graph.add_node(package,color=color,fontcolor=color,shape='record')classCubeTracerSet(object):"""Dumb set implementation whose purpose is to keep track of which cube is being loaded when something is added to the set. Results will be found in the `value_cube` attribute dictionary. See `localperms` or `nosylist` cubes for example usage (`hooks` module). """def__init__(self,vreg,wrapped):self.vreg=vregself.wrapped=wrappedself.value_cube={}defadd(self,value):self.wrapped.add(value)cube=self.vreg.currently_loading_cubeifvalueinself.value_cube:warn('%s is propagated by cube %s and cube %s',value,self.value_cube[value],cube)else:self.value_cube[value]=cubedef__iter__(self):returniter(self.wrapped)def__ior__(self,other):forvalueinother:self.add(value)returnselfdef__ror__(self,other):other|=self.wrappedreturnother