--- a/web/schemaviewer.py Mon Jan 04 18:40:30 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,245 +0,0 @@
-# copyright 2003-2011 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/>.
-"""an helper class to display CubicWeb schema using ureports"""
-
-__docformat__ = "restructuredtext en"
-from cubicweb import _
-
-from six import string_types
-
-from logilab.common.ureports import Section, Title, Table, Link, Span, Text
-
-from yams.schema2dot import CARD_MAP
-from yams.schema import RelationDefinitionSchema
-from operator import attrgetter
-
-TYPE_GETTER = attrgetter('type')
-
-I18NSTRINGS = [_('read'), _('add'), _('delete'), _('update'), _('order')]
-
-
-class SchemaViewer(object):
- """return a ureport layout for some part of a schema"""
- def __init__(self, req=None, encoding=None):
- self.req = req
- if req is not None:
- req.add_css('cubicweb.schema.css')
- if encoding is None:
- encoding = req.encoding
- self._ = req._
- else:
- encoding = 'ascii'
- self._ = unicode
- self.encoding = encoding
-
- # no self.req managements
-
- def may_read(self, rdef, action='read'):
- """Return true if request user may read the given schema.
- Always return True when no request is provided.
- """
- if self.req is None:
- return True
- return rdef.may_have_permission(action, self.req)
-
- def format_eschema(self, eschema):
- text = eschema.type
- if self.req is None:
- return Text(text)
- return Link(self.req.build_url('cwetype/%s' % eschema), text)
-
- def format_rschema(self, rschema, label=None):
- if label is None:
- label = rschema.type
- if self.req is None:
- return Text(label)
- return Link(self.req.build_url('cwrtype/%s' % rschema), label)
-
- # end of no self.req managements
-
- def visit_schema(self, schema, display_relations=0, skiptypes=()):
- """get a layout for a whole schema"""
- title = Title(self._('Schema %s') % schema.name,
- klass='titleUnderline')
- layout = Section(children=(title,))
- esection = Section(children=(Title(self._('Entities'),
- klass='titleUnderline'),))
- layout.append(esection)
- eschemas = [eschema for eschema in schema.entities()
- if not (eschema.final or eschema in skiptypes)]
- for eschema in sorted(eschemas, key=TYPE_GETTER):
- esection.append(self.visit_entityschema(eschema, skiptypes))
- if display_relations:
- title = Title(self._('Relations'), klass='titleUnderline')
- rsection = Section(children=(title,))
- layout.append(rsection)
- relations = [rschema for rschema in sorted(schema.relations(), key=TYPE_GETTER)
- if not (rschema.final or rschema.type in skiptypes)]
- keys = [(rschema.type, rschema) for rschema in relations]
- for key, rschema in sorted(keys, cmp=(lambda x, y: cmp(x[1], y[1]))):
- relstr = self.visit_relationschema(rschema)
- rsection.append(relstr)
- return layout
-
- def _entity_attributes_data(self, eschema):
- _ = self._
- data = [_('attribute'), _('type'), _('default'), _('constraints')]
- attributes = sorted(eschema.attribute_definitions(), cmp=(lambda x, y: cmp(x[0].type, y[0].type)))
- for rschema, aschema in attributes:
- rdef = eschema.rdef(rschema)
- if not self.may_read(rdef):
- continue
- aname = rschema.type
- if aname == 'eid':
- continue
- data.append('%s (%s)' % (aname, _(aname)))
- data.append(_(aschema.type))
- defaultval = eschema.default(aname)
- if defaultval is not None:
- default = self.to_string(defaultval)
- elif rdef.cardinality[0] == '1':
- default = _('required field')
- else:
- default = ''
- data.append(default)
- constraints = rschema.rproperty(eschema.type, aschema.type,
- 'constraints')
- data.append(', '.join(str(constr) for constr in constraints))
- return data
-
-
- def stereotype(self, name):
- return Span((' <<%s>>' % name,), klass='stereotype')
-
- def visit_entityschema(self, eschema, skiptypes=()):
- """get a layout for an entity schema"""
- etype = eschema.type
- layout = Section(children=' ', klass='clear')
- layout.append(Link(etype,' ' , id=etype)) # anchor
- title = self.format_eschema(eschema)
- boxchild = [Section(children=(title,), klass='title')]
- data = []
- data.append(Section(children=boxchild, klass='box'))
- data.append(Section(children='', klass='vl'))
- data.append(Section(children='', klass='hl'))
- t_vars = []
- rels = []
- first = True
-
- rel_defs = sorted(eschema.relation_definitions(),
- cmp=(lambda x, y: cmp((x[0].type, x[0].cardinality),
- (y[0].type, y[0].cardinality))))
- for rschema, targetschemas, role in rel_defs:
- if rschema.type in skiptypes:
- continue
- for oeschema in sorted(targetschemas, key=TYPE_GETTER):
- rdef = rschema.role_rdef(eschema, oeschema, role)
- if not self.may_read(rdef):
- continue
- label = rschema.type
- if role == 'subject':
- cards = rschema.rdef(eschema, oeschema).cardinality
- else:
- cards = rschema.rdef(oeschema, eschema).cardinality
- cards = cards[::-1]
- label = '%s %s %s' % (CARD_MAP[cards[1]], label,
- CARD_MAP[cards[0]])
- rlink = self.format_rschema(rschema, label)
- elink = self.format_eschema(oeschema)
- if first:
- t_vars.append(Section(children=(elink,), klass='firstvar'))
- rels.append(Section(children=(rlink,), klass='firstrel'))
- first = False
- else:
- t_vars.append(Section(children=(elink,), klass='var'))
- rels.append(Section(children=(rlink,), klass='rel'))
- data.append(Section(children=rels, klass='rels'))
- data.append(Section(children=t_vars, klass='vars'))
- layout.append(Section(children=data, klass='entityAttributes'))
- return layout
-
- def visit_relationschema(self, rschema, title=True):
- """get a layout for a relation schema"""
- _ = self._
- if title:
- title = self.format_rschema(rschema)
- stereotypes = []
- if rschema.meta:
- stereotypes.append('meta')
- if rschema.symmetric:
- stereotypes.append('symmetric')
- if rschema.inlined:
- stereotypes.append('inlined')
- title = Section(children=(title,), klass='title')
- if stereotypes:
- title.append(self.stereotype(','.join(stereotypes)))
- layout = Section(children=(title,), klass='schema')
- else:
- layout = Section(klass='schema')
- data = [_('from'), _('to')]
- schema = rschema.schema
- rschema_objects = rschema.objects()
- if rschema_objects:
- # might be empty
- properties = [p for p in RelationDefinitionSchema.rproperty_defs(rschema_objects[0])
- if not p in ('cardinality', 'composite', 'eid')]
- else:
- properties = []
- data += [_(prop) for prop in properties]
- cols = len(data)
- done = set()
- for subjtype, objtypes in sorted(rschema.associations()):
- for objtype in objtypes:
- if (subjtype, objtype) in done:
- continue
- done.add((subjtype, objtype))
- if rschema.symmetric:
- done.add((objtype, subjtype))
- data.append(self.format_eschema(schema[subjtype]))
- data.append(self.format_eschema(schema[objtype]))
- rdef = rschema.rdef(subjtype, objtype)
- for prop in properties:
- val = getattr(rdef, prop)
- if val is None:
- val = ''
- elif prop == 'constraints':
- val = ', '.join([c.expression for c in val])
- elif isinstance(val, dict):
- for key, value in val.items():
- if isinstance(value, (list, tuple)):
- val[key] = ', '.join(sorted( str(v) for v in value))
- val = str(val)
-
- elif isinstance(val, (list, tuple)):
- val = sorted(val)
- val = ', '.join(str(v) for v in val)
- elif val and isinstance(val, string_types):
- val = _(val)
- else:
- val = str(val)
- data.append(Text(val))
- table = Table(cols=cols, rheaders=1, children=data, klass='listing')
- layout.append(Section(children=(table,), klass='relationDefinition'))
- layout.append(Section(children='', klass='clear'))
- return layout
-
- def to_string(self, value):
- """used to converte arbitrary values to encoded string"""
- if isinstance(value, unicode):
- return value.encode(self.encoding, 'replace')
- return str(value)