# HG changeset patch # User Pierre-Yves David # Date 1271944245 -7200 # Node ID b74eed7e8b3737ddfa61ab17d961396d8c41899e # Parent e0feefb87de5624779e9bec51e2963cb67b198fb Add a basic script to compare the db_schema to the fs_schema. Allow SchemaViewer to be used without a request object Most use of self.req have been hidden in method that fallback on a simple behaviour when no req are provided. Several element have been sorted to ease comparison. diff -r e0feefb87de5 -r b74eed7e8b37 doc/book/en/development/devweb/views/index.rst --- a/doc/book/en/development/devweb/views/index.rst Tue Apr 20 18:34:37 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -The View system -=============== - -This chapter aims to describe the concept of a `view` used all along -the development of a web application and how it has been implemented -in |cubicweb|. - - -.. toctree:: - :maxdepth: 3 - - views - basetemplates - primary - baseviews - startup - boxes - table - xmlrss - autoform -.. editforms - -.. toctree:: - :maxdepth: 3 - - urlpublish - breadcrumbs -.. wdoc -.. embedding -.. idownloadable - diff -r e0feefb87de5 -r b74eed7e8b37 misc/cmp_schema.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/cmp_schema.py Thu Apr 22 15:50:45 2010 +0200 @@ -0,0 +1,24 @@ +"""This module compare the Schema on the file system to the one in the database""" + +from cStringIO import StringIO +from cubicweb.web.schemaviewer import SchemaViewer +from logilab.common.ureports import TextWriter +import difflib + +viewer = SchemaViewer() +layout_db = viewer.visit_schema(schema, display_relations=True) +layout_fs = viewer.visit_schema(fsschema, display_relations=True) +writer = TextWriter() +stream_db = StringIO() +stream_fs = StringIO() +writer.format(layout_db, stream=stream_db) +writer.format(layout_fs, stream=stream_fs) + +stream_db.seek(0) +stream_fs.seek(0) +db = stream_db.getvalue().splitlines() +fs = stream_fs.getvalue().splitlines() +open('db_schema.txt', 'w').write(stream_db.getvalue()) +open('fs_schema.txt', 'w').write(stream_fs.getvalue()) +#for diff in difflib.ndiff(fs, db): +# print diff diff -r e0feefb87de5 -r b74eed7e8b37 schema.py --- a/schema.py Tue Apr 20 18:34:37 2010 +0200 +++ b/schema.py Thu Apr 22 15:50:45 2010 +0200 @@ -161,7 +161,7 @@ mainvars.append('U') if not mainvars: raise Exception('unable to guess selection variables') - return ','.join(mainvars) + return ','.join(sorted(mainvars)) def split_expression(rqlstring): for expr in rqlstring.split(','): 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)