diff -r e0feefb87de5 -r b74eed7e8b37 web/schemaviewer.py --- a/web/schemaviewer.py Tue Apr 20 18:34:37 2010 +0200 +++ b/web/schemaviewer.py Thu Apr 22 15:50:45 2010 +0200 @@ -12,6 +12,9 @@ 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')] @@ -21,41 +24,71 @@ def __init__(self, req=None, encoding=None): self.req = req if req is not None: - self.req.add_css('cubicweb.schema.css') - if not encoding: + 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): + """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 sch.may_have_permission('read', 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.req._('Schema %s') % schema.name, + title = Title(self._('Schema %s') % schema.name, klass='titleUnderline') layout = Section(children=(title,)) - esection = Section(children=(Title(self.req._('Entities'), + 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): + for eschema in sorted(eschemas, key=TYPE_GETTER): esection.append(self.visit_entityschema(eschema, skiptypes)) if display_relations: - title = Title(self.req._('Relations'), klass='titleUnderline') + title = Title(self._('Relations'), klass='titleUnderline') rsection = Section(children=(title,)) layout.append(rsection) - relations = [rschema for rschema in schema.relations() + 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): + 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.req._ + _ = self._ data = [_('attribute'), _('type'), _('default'), _('constraints')] - for rschema, aschema in eschema.attribute_definitions(): + 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 rdef.may_have_permission('read', self.req): + if not self.may_read(rdef): continue aname = rschema.type if aname == 'eid': @@ -75,11 +108,6 @@ data.append(', '.join(str(constr) for constr in constraints)) return data - def eschema_link_url(self, eschema): - return self.req.build_url('cwetype/%s' % eschema) - - def rschema_link_url(self, rschema): - return self.req.build_url('cwrtype/%s' % rschema) def stereotype(self, name): return Span((' <<%s>>' % name,), klass='stereotype') @@ -89,7 +117,7 @@ etype = eschema.type layout = Section(children=' ', klass='clear') layout.append(Link(etype,' ' , id=etype)) # anchor - title = Link(self.eschema_link_url(eschema), etype) + title = self.format_eschema(eschema) boxchild = [Section(children=(title,), klass='title')] data = [] data.append(Section(children=boxchild, klass='box')) @@ -98,13 +126,16 @@ t_vars = [] rels = [] first = True - for rschema, targetschemas, role in eschema.relation_definitions(): + + 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 - rschemaurl = self.rschema_link_url(rschema) - for oeschema in targetschemas: + for oeschema in sorted(targetschemas, key=TYPE_GETTER): rdef = rschema.role_rdef(eschema, oeschema, role) - if not rdef.may_have_permission('read', self.req): + if not self.may_read(rdef): continue label = rschema.type if role == 'subject': @@ -114,8 +145,8 @@ cards = cards[::-1] label = '%s %s %s' % (CARD_MAP[cards[1]], label, CARD_MAP[cards[0]]) - rlink = Link(rschemaurl, label) - elink = Link(self.eschema_link_url(oeschema), oeschema.type) + 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')) @@ -130,9 +161,9 @@ def visit_relationschema(self, rschema, title=True): """get a layout for a relation schema""" - _ = self.req._ + _ = self._ if title: - title = Link(self.rschema_link_url(rschema), rschema.type) + title = self.format_rschema(rschema) stereotypes = [] if rschema.meta: stereotypes.append('meta') @@ -140,7 +171,7 @@ stereotypes.append('symmetric') if rschema.inlined: stereotypes.append('inlined') - title = Section(children=(title, ' (%s)'%rschema.display_name(self.req)), klass='title') + title = Section(children=(title,), klass='title') if stereotypes: title.append(self.stereotype(','.join(stereotypes))) layout = Section(children=(title,), klass='schema') @@ -158,15 +189,15 @@ data += [_(prop) for prop in properties] cols = len(data) done = set() - for subjtype, objtypes in rschema.associations(): + 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(Link(self.eschema_link_url(schema[subjtype]), subjtype)) - data.append(Link(self.eschema_link_url(schema[objtype]), objtype)) + 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) @@ -174,7 +205,14 @@ val = '' elif prop == 'constraints': val = ', '.join([c.restriction for c in val]) + elif isinstance(val, dict): + for key, value in val.iteritems(): + 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, basestring): val = _(val)