stop using meta attribute from yams schema. Use instead sets defining meta relations and another defining schema types. Refactor various schema view based on this
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 19 Jun 2009 14:42:04 +0200
changeset 2126 a25859917ccc
parent 2123 3e1d2ab5f8c0
child 2127 bc86aa68cc43
stop using meta attribute from yams schema. Use instead sets defining meta relations and another defining schema types. Refactor various schema view based on this
devtools/testlib.py
entities/schemaobjs.py
entity.py
goa/dbinit.py
goa/tools/generate_schema_img.py
goa/tools/laxctl.py
schema.py
schemaviewer.py
server/__init__.py
server/schemaserial.py
web/uicfg.py
web/views/owl.py
web/views/schema.py
web/views/startup.py
--- a/devtools/testlib.py	Thu Jun 18 21:01:55 2009 +0200
+++ b/devtools/testlib.py	Fri Jun 19 14:42:04 2009 +0200
@@ -44,7 +44,7 @@
     # compute how many entities by type we need to be able to satisfy relation constraint
     relmap = {}
     for rschema in schema.relations():
-        if rschema.meta or rschema.is_final(): # skip meta relations
+        if rschema.is_final():
             continue
         for subj, obj in rschema.iter_rdefs():
             card = rschema.rproperty(subj, obj, 'cardinality')
--- a/entities/schemaobjs.py	Thu Jun 18 21:01:55 2009 +0200
+++ b/entities/schemaobjs.py	Fri Jun 19 14:42:04 2009 +0200
@@ -25,8 +25,6 @@
     def dc_long_title(self):
         stereotypes = []
         _ = self.req._
-        if self.meta:
-            stereotypes.append(_('meta'))
         if self.final:
             stereotypes.append(_('final'))
         if stereotypes:
--- a/entity.py	Thu Jun 18 21:01:55 2009 +0200
+++ b/entity.py	Fri Jun 19 14:42:04 2009 +0200
@@ -485,7 +485,7 @@
         assert self.has_eid()
         execute = self.req.execute
         for rschema in self.e_schema.subject_relations():
-            if rschema.meta or rschema.is_final():
+            if rschema.is_final() or rschema.meta:
                 continue
             # skip already defined relations
             if getattr(self, rschema.type):
--- a/goa/dbinit.py	Thu Jun 18 21:01:55 2009 +0200
+++ b/goa/dbinit.py	Fri Jun 19 14:42:04 2009 +0200
@@ -86,14 +86,13 @@
 def init_persistent_schema(ssession, schema):
     execute = ssession.unsafe_execute
     rql = ('INSERT CWEType X: X name %(name)s, X description %(descr)s,'
-           'X final FALSE, X meta %(meta)s')
+           'X final FALSE')
     eschema = schema.eschema('CWEType')
-    execute(rql, {'name': u'CWEType', 'descr': unicode(eschema.description),
-                  'meta': eschema.meta})
+    execute(rql, {'name': u'CWEType', 'descr': unicode(eschema.description)})
     for eschema in schema.entities():
         if eschema.is_final() or eschema == 'CWEType':
             continue
-        execute(rql, {'name': unicode(eschema), 'meta': eschema.meta,
+        execute(rql, {'name': unicode(eschema),
                       'descr': unicode(eschema.description)})
 
 def insert_versions(ssession, config):
--- a/goa/tools/generate_schema_img.py	Thu Jun 18 21:01:55 2009 +0200
+++ b/goa/tools/generate_schema_img.py	Fri Jun 19 14:42:04 2009 +0200
@@ -8,6 +8,7 @@
 import sys
 from os.path import dirname, abspath, join
 from yams import schema2dot
+from cubicweb.web.views.schema import SKIP_TYPES
 
 APPLROOT = abspath(join(dirname(abspath(__file__)), '..'))
 
@@ -22,9 +23,8 @@
 skip_rels = ('owned_by', 'created_by', 'identity', 'is', 'is_instance_of')
 path = join(APPLROOT, 'data', 'schema.png')
 schema2dot.schema2dot(schema, path, #size=size,
-                      skiprels=skip_rels, skipmeta=True)
+                      skiptypes=SKIP_TYPES)
 print 'generated', path
 path = join(APPLROOT, 'data', 'metaschema.png')
-schema2dot.schema2dot(schema, path, #size=size,
-                      skiprels=skip_rels, skipmeta=False)
+schema2dot.schema2dot(schema, path)
 print 'generated', path
--- a/goa/tools/laxctl.py	Thu Jun 18 21:01:55 2009 +0200
+++ b/goa/tools/laxctl.py	Fri Jun 19 14:42:04 2009 +0200
@@ -19,6 +19,8 @@
 from logilab.common.clcommands import Command, register_commands, main_run
 
 from cubicweb.common.uilib import remove_html_tags
+from cubicweb.web.views.schema import SKIP_TYPES
+
 APPLROOT = osp.abspath(osp.join(osp.dirname(osp.abspath(__file__)), '..'))
 
 
@@ -57,14 +59,12 @@
         assert not args, 'no argument expected'
         from yams import schema2dot
         schema = self.vreg.schema
-        skip_rels = ('owned_by', 'created_by', 'identity', 'is', 'is_instance_of')
         path = osp.join(APPLROOT, 'data', 'schema.png')
         schema2dot.schema2dot(schema, path, #size=size,
-                              skiprels=skip_rels, skipmeta=True)
+                              skiptypes=SKIP_TYPES)
         print 'generated', path
         path = osp.join(APPLROOT, 'data', 'metaschema.png')
-        schema2dot.schema2dot(schema, path, #size=size,
-                              skiprels=skip_rels, skipmeta=False)
+        schema2dot.schema2dot(schema, path)
         print 'generated', path
 
 
--- a/schema.py	Thu Jun 18 21:01:55 2009 +0200
+++ b/schema.py	Fri Jun 19 14:42:04 2009 +0200
@@ -6,6 +6,7 @@
 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 __docformat__ = "restructuredtext en"
+_ = unicode
 
 import re
 from logging import getLogger
@@ -30,11 +31,24 @@
 schema.use_py_datetime()
 nodes.use_py_datetime()
 
-_ = unicode
+#  set of meta-relations available for every entity types
+META_RELATIONS_TYPES = set((
+    'owned_by', 'created_by', 'is', 'is_instance_of', 'identity',
+    'eid', 'creation_date', 'modification_date', 'has_text',
+    )))
 
-BASEGROUPS = ('managers', 'users', 'guests', 'owners')
+#  set of entity and relation types used to build the schema
+SCHEMA_TYPES = set((
+    'CWEType', 'CWRType', 'CWAttribute', 'CWRelation',
+    'CWConstraint', 'CWConstraintType', 'RQLExpression',
+    'relation_type', 'from_entity', 'to_entity',
+    'constrained_by', 'cstrtype',
+    # XXX those are not really "schema" entity types
+    #     but we usually don't want them as @* targets
+    'CWProperty', 'CWPermission', 'State', 'Transition',
+    ))
 
-LOGGER = getLogger('cubicweb.schemaloader')
+_LOGGER = getLogger('cubicweb.schemaloader')
 
 # schema entities created from serialized schema have an eid rproperty
 ybo.ETYPE_PROPERTIES += ('eid',)
@@ -68,6 +82,7 @@
         etypes = ()
         if '*' in etype:
             etypes += tuple(self._wildcard_etypes(schema))
+        # XXX deprecate, too clumsy
         if '@' in etype:
             etypes += tuple(system_etypes(schema))
         return etypes
@@ -242,7 +257,7 @@
     """return system entity types only: skip final, schema and application entities
     """
     for eschema in schema.entities():
-        if eschema.is_final() or eschema.schema_entity() or not eschema.meta:
+        if eschema.is_final() or eschema.schema_entity():
             continue
         yield eschema.type
 
@@ -321,7 +336,7 @@
 
     def schema_entity(self):
         """return True if this entity type is used to build the schema"""
-        return self.type in self.schema.schema_entity_types()
+        return self.type in SCHEMA_TYPES
 
     def check_perm(self, session, action, eid=None):
         # NB: session may be a server session or a request object
@@ -358,6 +373,9 @@
             eid = getattr(rdef, 'eid', None)
         self.eid = eid
 
+    @property
+    def meta(self):
+        return self.type in META_RELATIONS_TYPES
 
     def update(self, subjschema, objschema, rdef):
         super(CubicWebRelationSchema, self).update(subjschema, objschema, rdef)
@@ -396,8 +414,8 @@
                (target == 'object' and card[1])
 
     def schema_relation(self):
-        return self.type in ('relation_type', 'from_entity', 'to_entity',
-                             'constrained_by', 'cstrtype')
+        """return True if this relation type is used to build the schema"""
+        return self.type in SCHEMA_TYPES
 
     def physical_mode(self):
         """return an appropriate mode for physical storage of this relation type:
@@ -457,14 +475,6 @@
         rschema.final = False
         rschema.set_default_groups()
 
-    def schema_entity_types(self):
-        """return the list of entity types used to build the schema"""
-        return frozenset(('CWEType', 'CWRType', 'CWAttribute', 'CWRelation',
-                          'CWConstraint', 'CWConstraintType', 'RQLExpression',
-                          # XXX those are not really "schema" entity types
-                          #     but we usually don't want them as @* targets
-                          'CWProperty', 'CWPermission', 'State', 'Transition'))
-
     def add_entity_type(self, edef):
         edef.name = edef.name.encode()
         edef.name = bw_normalize_etype(edef.name)
@@ -636,8 +646,8 @@
             raise RQLSyntaxError(expression)
         for mainvar in mainvars.split(','):
             if len(self.rqlst.defined_vars[mainvar].references()) <= 2:
-                LOGGER.warn('You did not use the %s variable in your RQL expression %s',
-                            mainvar, self)
+                _LOGGER.warn('You did not use the %s variable in your RQL '
+                             'expression %s', mainvar, self)
 
     def __str__(self):
         return self.full_rql
--- a/schemaviewer.py	Thu Jun 18 21:01:55 2009 +0200
+++ b/schemaviewer.py	Fri Jun 19 14:42:04 2009 +0200
@@ -6,11 +6,11 @@
 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 __docformat__ = "restructuredtext en"
+_ = unicode
 
 from logilab.common.ureports import Section, Title, Table, Link, Span, Text
 from yams.schema2dot import CARD_MAP
 
-_ = unicode
 I18NSTRINGS = [_('read'), _('add'), _('delete'), _('update'), _('order')]
 
 class SchemaViewer(object):
@@ -38,8 +38,7 @@
                        klass='acl')
 
 
-    def visit_schema(self, schema, display_relations=0,
-                     skiprels=(), skipmeta=True):
+    def visit_schema(self, schema, display_relations=0, skiptypes=()):
         """get a layout for a whole schema"""
         title = Title(self.req._('Schema %s') % schema.name,
                       klass='titleUnderline')
@@ -48,21 +47,15 @@
                                            klass='titleUnderline'),))
         layout.append(esection)
         eschemas = [eschema for eschema in schema.entities()
-                    if not eschema.is_final()]
-        if skipmeta:
-            eschemas = [eschema for eschema in eschemas
-                        if not eschema.meta]
+                    if not (eschema.is_final() or eschema in skiptypes)]
         for eschema in sorted(eschemas):
-            esection.append(self.visit_entityschema(eschema, skiprels))
+            esection.append(self.visit_entityschema(eschema, skiptypes))
         if display_relations:
             title = Title(self.req._('Relations'), klass='titleUnderline')
             rsection = Section(children=(title,))
             layout.append(rsection)
             relations = [rschema for rschema in schema.relations()
-                         if not (rschema.is_final() or rschema.type in skiprels)]
-            if skipmeta:
-                relations = [rschema for rschema in relations
-                             if not rschema.meta]
+                         if not (rschema.is_final() or rschema.type in skiptypes)]
             keys = [(rschema.type, rschema) for rschema in relations]
             for key, rschema in sorted(keys):
                 relstr = self.visit_relationschema(rschema)
@@ -107,17 +100,13 @@
     def stereotype(self, name):
         return Span((' <<%s>>' % name,), klass='stereotype')
 
-    def visit_entityschema(self, eschema, skiprels=()):
+    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,'&nbsp;' , id=etype)) # anchor
         title = Link(self.eschema_link_url(eschema), etype)
-        if eschema.meta:
-            stereotype = self.stereotype('meta')
-            boxchild = [Section(children=(title, ' (%s)'%eschema.display_name(self.req), stereotype), klass='title')]
-        else:
-            boxchild = [Section(children=(title, ' (%s)'%eschema.display_name(self.req)), klass='title')]
+        boxchild = [Section(children=(title, ' (%s)'% eschema.display_name(self.req)), klass='title')]
         table = Table(cols=4, rheaders=1,
                       children=self._entity_attributes_data(eschema))
         boxchild.append(Section(children=(table,), klass='body'))
@@ -129,7 +118,7 @@
         rels = []
         first = True
         for rschema, targetschemas, x in eschema.relation_definitions():
-            if rschema.type in skiprels:
+            if rschema.type in skiptypes:
                 continue
             if not (rschema.has_local_role('read') or rschema.has_perm(self.req, 'read')):
                 continue
--- a/server/__init__.py	Thu Jun 18 21:01:55 2009 +0200
+++ b/server/__init__.py	Fri Jun 19 14:42:04 2009 +0200
@@ -24,7 +24,7 @@
     a initial user)
     """
     from glob import glob
-    from cubicweb.schema import BASEGROUPS
+    from yams import BASE_GROUPS
     from cubicweb.dbapi import in_memory_cnx
     from cubicweb.server.repository import Repository
     from cubicweb.server.utils import manager_userpasswd
@@ -93,7 +93,7 @@
             login, pwd = unicode(source['db-user']), source['db-password']
     print 'inserting default user and groups'
     needisfix = []
-    for group in BASEGROUPS:
+    for group in BASE_GROUPS:
         rset = session.execute('INSERT CWGroup X: X name %(name)s',
                                {'name': unicode(group)})
         needisfix.append( (rset.rows[0][0], rset.description[0][0]) )
--- a/server/schemaserial.py	Thu Jun 18 21:01:55 2009 +0200
+++ b/server/schemaserial.py	Fri Jun 19 14:42:04 2009 +0200
@@ -114,10 +114,10 @@
     index = {}
     permsdict = deserialize_ertype_permissions(session)
     schema.reading_from_database = True
-    for eid, etype, desc, meta in session.execute('Any X, N, D, M WHERE '
-                                                  'X is CWEType, X name N, '
-                                                  'X description D, X meta M',
-                                                  build_descr=False):
+    for eid, etype, desc in session.execute('Any X, N, D WHERE '
+                                            'X is CWEType, X name N, '
+                                            'X description D',
+                                            build_descr=False):
         # base types are already in the schema, skip them
         if etype in schemamod.BASE_TYPES:
             # just set the eid
@@ -152,7 +152,7 @@
             repo.clear_caches(tocleanup)
             session.commit(False)
             etype = netype
-        etype = ybo.EntityType(name=etype, description=desc, meta=meta, eid=eid)
+        etype = ybo.EntityType(name=etype, description=desc, eid=eid)
         eschema = schema.add_entity_type(etype)
         index[eid] = eschema
         set_perms(eschema, permsdict.get(eid, {}))
@@ -167,9 +167,9 @@
             seschema = schema.eschema(stype)
             eschema._specialized_type = stype
             seschema._specialized_by.append(etype)
-    for eid, rtype, desc, meta, sym, il in session.execute(
-        'Any X,N,D,M,S,I WHERE X is CWRType, X name N, X description D, '
-        'X meta M, X symetric S, X inlined I', build_descr=False):
+    for eid, rtype, desc, sym, il in session.execute(
+        'Any X,N,D,S,I WHERE X is CWRType, X name N, X description D, '
+        'X symetric S, X inlined I', build_descr=False):
         try:
             # bw compat: fulltext_container added in 2.47
             ft_container = session.execute('Any FTC WHERE X eid %(x)s, X fulltext_container FTC',
@@ -177,7 +177,7 @@
         except:
             ft_container = None
             session.rollback(False)
-        rtype = ybo.RelationType(name=rtype, description=desc, meta=bool(meta),
+        rtype = ybo.RelationType(name=rtype, description=desc,
                                  symetric=bool(sym), inlined=bool(il),
                                  fulltext_container=ft_container, eid=eid)
         rschema = schema.add_relation_type(rtype)
@@ -326,7 +326,6 @@
         raise Exception("can't decode %s [was %s]" % (erschema.description, e))
     return {
         'name': type_,
-        'meta': erschema.meta,
         'final': erschema.is_final(),
         'description': desc,
         }
--- a/web/uicfg.py	Thu Jun 18 21:01:55 2009 +0200
+++ b/web/uicfg.py	Fri Jun 19 14:42:04 2009 +0200
@@ -154,7 +154,11 @@
 # * 'schema'
 # * 'subobject' (not displayed by default)
 
-indexview_etype_section = {'EmailAddress': 'subobject'}
+indexview_etype_section = {'EmailAddress': 'subobject',
+                           'CWUser': 'system',
+                           'CWGroup': 'system',
+                           'CWPermission': 'system',
+                           }
 
 
 # autoform.AutomaticEntityForm configuration ##################################
--- a/web/views/owl.py	Thu Jun 18 21:01:55 2009 +0200
+++ b/web/views/owl.py	Fri Jun 19 14:42:04 2009 +0200
@@ -6,14 +6,14 @@
 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 __docformat__ = "restructuredtext en"
+_ = unicode
 
 from logilab.mtconverter import TransformError, xml_escape
 
 from cubicweb.view import StartupView, EntityView
+from cubicweb.selectors import none_rset, match_view
 from cubicweb.web.action import Action
-from cubicweb.selectors import none_rset, match_view
-
-_ = unicode
+from cubicweb.web.views import schema
 
 OWL_CARD_MAP = {'1': '<rdf:type rdf:resource="&owl;FunctionalProperty"/>',
                 '?': '<owl:maxCardinality rdf:datatype="&xsd;int">1</owl:maxCardinality>',
@@ -55,8 +55,6 @@
 
 OWL_CLOSING_ROOT = u'</rdf:RDF>'
 
-DEFAULT_SKIP_RELS = frozenset(('is', 'is_instance_of', 'identity',
-                               'owned_by', 'created_by'))
 
 class OWLView(StartupView):
     """This view export in owl format schema database. It is the TBOX"""
@@ -69,36 +67,36 @@
         skipmeta = int(self.req.form.get('skipmeta', True))
         if writeprefix:
             self.w(OWL_OPENING_ROOT % {'appid': self.schema.name})
-        self.visit_schema(skipmeta=skipmeta)
+        self.visit_schema(skiptypes=skipmeta and schema.SKIP_TYPES or ())
         if writeprefix:
             self.w(OWL_CLOSING_ROOT)
 
-    def visit_schema(self, skiprels=DEFAULT_SKIP_RELS, skipmeta=True):
+    def should_display_rschema(self, rschema):
+        return not rschema in self.skiptypes and (
+            rschema.has_local_role('read') or
+            rschema.has_perm(self.req, 'read')):
+
+    def visit_schema(self, skiptypes):
         """get a layout for a whole schema"""
-        entities = sorted([eschema for eschema in self.schema.entities()
-                           if not eschema.is_final()])
-        if skipmeta:
-            entities = [eschema for eschema in entities
-                        if not eschema.meta]
+        self.skiptypes = skiptypes
+        entities = sorted(eschema for eschema in self.schema.entities()
+                          if not eschema.is_final() or eschema in skiptypes)
         self.w(u'<!-- classes definition -->')
         for eschema in entities:
-            self.visit_entityschema(eschema, skiprels)
+            self.visit_entityschema(eschema)
             self.w(u'<!-- property definition -->')
-            self.visit_property_schema(eschema, skiprels)
+            self.visit_property_schema(eschema)
             self.w(u'<!-- datatype property -->')
             self.visit_property_object_schema(eschema)
 
-    def visit_entityschema(self, eschema, skiprels=()):
+    def visit_entityschema(self, eschema):
         """get a layout for an entity OWL schema"""
         self.w(u'<owl:Class rdf:ID="%s">'% eschema)
         self.w(u'<!-- relations -->')
         for rschema, targetschemas, role in eschema.relation_definitions():
-            if rschema.type in skiprels:
-                continue
-            if not (rschema.has_local_role('read') or rschema.has_perm(self.req, 'read')):
+            if not self.should_display_rschema(rschema):
                 continue
             for oeschema in targetschemas:
-                label = rschema.type
                 if role == 'subject':
                     card = rschema.rproperty(eschema, oeschema, 'cardinality')[0]
                 else:
@@ -110,58 +108,44 @@
   <owl:onProperty rdf:resource="#%s"/>
   %s
  </owl:Restriction>
-</rdfs:subClassOf>
-''' % (label, cardtag))
+</rdfs:subClassOf>''' % (rschema, cardtag))
 
         self.w(u'<!-- attributes -->')
-
         for rschema, aschema in eschema.attribute_definitions():
-            if not (rschema.has_local_role('read') or rschema.has_perm(self.req, 'read')):
-                continue
-            aname = rschema.type
-            if aname == 'eid':
+            if not self.should_display_rschema(rschema):
                 continue
             self.w(u'''<rdfs:subClassOf>
   <owl:Restriction>
    <owl:onProperty rdf:resource="#%s"/>
    <rdf:type rdf:resource="&owl;FunctionalProperty"/>
   </owl:Restriction>
-</rdfs:subClassOf>'''
-                   % aname)
+</rdfs:subClassOf>''' % rschema)
         self.w(u'</owl:Class>')
 
-    def visit_property_schema(self, eschema, skiprels=()):
+    def visit_property_schema(self, eschema):
         """get a layout for property entity OWL schema"""
         for rschema, targetschemas, role in eschema.relation_definitions():
-            if rschema.type in skiprels:
-                continue
-            if not (rschema.has_local_role('read') or rschema.has_perm(self.req, 'read')):
+            if not self.should_display_rschema(rschema):
                 continue
             for oeschema in targetschemas:
                 label = rschema.type
                 self.w(u'''<owl:ObjectProperty rdf:ID="%s">
  <rdfs:domain rdf:resource="#%s"/>
  <rdfs:range rdf:resource="#%s"/>
-</owl:ObjectProperty>
-''' % (label, eschema, oeschema.type))
+</owl:ObjectProperty>''' % (label, eschema, oeschema.type))
 
     def visit_property_object_schema(self, eschema):
         for rschema, aschema in eschema.attribute_definitions():
-            if not (rschema.has_local_role('read') or rschema.has_perm(self.req, 'read')):
-                continue
-            aname = rschema.type
-            if aname == 'eid':
+            if not self.should_display_rschema(rschema):
                 continue
             self.w(u'''<owl:DatatypeProperty rdf:ID="%s">
   <rdfs:domain rdf:resource="#%s"/>
   <rdfs:range rdf:resource="%s"/>
-</owl:DatatypeProperty>'''
-                   % (aname, eschema, OWL_TYPE_MAP[aschema.type]))
+</owl:DatatypeProperty>''' % (aname, eschema, OWL_TYPE_MAP[aschema.type]))
 
 
 class OWLABOXView(EntityView):
     '''This view represents a part of the ABOX for a given entity.'''
-
     id = 'owlabox'
     title = _('owlabox')
     templatable = False
@@ -173,8 +157,8 @@
             self.cell_call(i, 0)
         self.w(OWL_CLOSING_ROOT)
 
-    def cell_call(self, row, col, skiprels=DEFAULT_SKIP_RELS):
-        self.wview('owlaboxitem', self.rset, row=row, col=col, skiprels=skiprels)
+    def cell_call(self, row, col):
+        self.wview('owlaboxitem', self.rset, row=row, col=col)
 
 
 class OWLABOXItemView(EntityView):
@@ -183,13 +167,13 @@
     templatable = False
     content_type = 'application/xml' # 'text/xml'
 
-    def cell_call(self, row, col, skiprels=DEFAULT_SKIP_RELS):
+    def cell_call(self, row, col):
         entity = self.complete_entity(row, col)
         eschema = entity.e_schema
         self.w(u'<%s rdf:ID="%s">' % (eschema, entity.eid))
         self.w(u'<!--attributes-->')
         for rschema, aschema in eschema.attribute_definitions():
-            if rschema.type in skiprels:
+            if rschema.meta:
                 continue
             if not (rschema.has_local_role('read') or rschema.has_perm(self.req, 'read')):
                 continue
@@ -204,7 +188,7 @@
                 pass
         self.w(u'<!--relations -->')
         for rschema, targetschemas, role in eschema.relation_definitions():
-            if rschema.type in skiprels:
+            if rschema.meta:
                 continue
             if not (rschema.has_local_role('read') or rschema.has_perm(self.req, 'read')):
                 continue
--- a/web/views/schema.py	Thu Jun 18 21:01:55 2009 +0200
+++ b/web/views/schema.py	Fri Jun 19 14:42:04 2009 +0200
@@ -7,12 +7,11 @@
 """
 __docformat__ = "restructuredtext en"
 
-from itertools import cycle
-
 from logilab.mtconverter import html_escape
 from yams import schema2dot as s2d
 
 from cubicweb.selectors import implements, yes
+from cubicweb.schema import META_RELATIONS_TYPES, SCHEMA_TYPES
 from cubicweb.schemaviewer import SchemaViewer
 from cubicweb.view import EntityView, StartupView
 from cubicweb.common import tags, uilib
@@ -20,6 +19,9 @@
 from cubicweb.web.views import TmpFileViewMixin, primary, baseviews, tabs
 from cubicweb.web.facet import AttributeFacet
 
+SKIP_TYPES = set()
+SKIP_TYPES.update(META_RELATIONS_TYPES)
+SKIP_TYPES.update(SCHEMA_TYPES)
 
 class ViewSchemaAction(action.Action):
     id = 'schema'
@@ -56,14 +58,11 @@
         if final:
             self.w(u'</em>')
 
-SKIPPED_RELS = ('is', 'is_instance_of', 'identity', 'created_by', 'owned_by',
-                'has_text',)
 
 class CWETypePrimaryView(tabs.TabsMixin, primary.PrimaryView):
     __select__ = implements('CWEType')
     title = _('in memory entity schema')
     main_related_section = False
-    skip_rels = SKIPPED_RELS
     tabs = [_('cwetype-schema-text'), _('cwetype-schema-image'), 
             _('cwetype-schema-permissions'), _('cwetype-workflow')]
     default_tab = 'cwetype-schema-text'
@@ -186,94 +185,56 @@
 
 # schema images ###############################################################
 
-class RestrictedSchemaDotPropsHandler(s2d.SchemaDotPropsHandler):
-    def __init__(self, req):
-        # FIXME: colors are arbitrary
-        self.nextcolor = cycle( ('#aa0000', '#00aa00', '#0000aa',
-                                 '#000000', '#888888') ).next
+class RestrictedSchemaVisitorMixIn(object):
+    def __init__(self, req, *args, **kwargs):
+        super(RestrictedSchemaVisitorMixIn, self).__init__(*args, **kwargs)
         self.req = req
 
-    def display_attr(self, rschema):
-        return not rschema.meta and (rschema.has_local_role('read')
-                                     or rschema.has_perm(self.req, 'read'))
+    def should_display_schema(self, schema):
+        return (super(RestrictedSchemaVisitorMixIn, self).should_display_schema(schema)
+                and rschema.has_local_role('read') or rschema.has_perm(self.req, 'read'))
 
-    # XXX remove this method once yams > 0.20 is out
-    def node_properties(self, eschema):
-        """return default DOT drawing options for an entity schema"""
-        label = ['{', eschema.type, '|']
-        label.append(r'\l'.join(rel.type for rel in eschema.subject_relations()
-                                if rel.final and self.display_attr(rel)))
-        label.append(r'\l}') # trailing \l ensure alignement of the last one
-        return {'label' : ''.join(label), 'shape' : "record",
-                'fontname' : "Courier", 'style' : "filled"}
-
-    def edge_properties(self, rschema, subjnode, objnode):
-        kwargs = super(RestrictedSchemaDotPropsHandler, self).edge_properties(rschema, subjnode, objnode)
-        # symetric rels are handled differently, let yams decide what's best
-        if not rschema.symetric:
-            kwargs['color'] = self.nextcolor()
-        kwargs['fontcolor'] = kwargs['color']
-        # dot label decoration is just awful (1 line underlining the label
-        # + 1 line going to the closest edge spline point)
-        kwargs['decorate'] = 'false'
-        return kwargs
+    def should_display_attr(self, schema):
+        return (super(RestrictedSchemaVisitorMixIn, self).should_display_attr(schema)
+                and rschema.has_local_role('read') or rschema.has_perm(self.req, 'read'))
 
 
-class RestrictedSchemaVisitorMiIn:
-    def __init__(self, req, *args, **kwargs):
-        # hack hack hack
-        assert len(self.__class__.__bases__) == 2
-        self.__parent = self.__class__.__bases__[1]
-        self.__parent.__init__(self, *args, **kwargs)
-        self.req = req
-
-    def nodes(self):
-        for etype, eschema in self.__parent.nodes(self):
-            if eschema.has_local_role('read') or eschema.has_perm(self.req, 'read'):
-                yield eschema.type, eschema
-
-    def edges(self):
-        for setype, oetype, rschema in self.__parent.edges(self):
-            if rschema.has_local_role('read') or rschema.has_perm(self.req, 'read'):
-                yield setype, oetype, rschema
-
-
-class FullSchemaVisitor(RestrictedSchemaVisitorMiIn, s2d.FullSchemaVisitor):
+class FullSchemaVisitor(RestrictedSchemaVisitorMixIn, s2d.FullSchemaVisitor):
     pass
 
-class OneHopESchemaVisitor(RestrictedSchemaVisitorMiIn, s2d.OneHopESchemaVisitor):
+class OneHopESchemaVisitor(RestrictedSchemaVisitorMixIn,
+                           s2d.OneHopESchemaVisitor):
     pass
 
-class OneHopRSchemaVisitor(RestrictedSchemaVisitorMiIn, s2d.OneHopRSchemaVisitor):
+class OneHopRSchemaVisitor(RestrictedSchemaVisitorMixIn,
+                           s2d.OneHopRSchemaVisitor):
     pass
 
 
 class SchemaImageView(TmpFileViewMixin, StartupView):
     id = 'schemagraph'
+    content_type = 'image/png'
 
-    content_type = 'image/png'
-    skip_rels = SKIPPED_RELS
     def _generate(self, tmpfile):
         """display global schema information"""
         skipmeta = not int(self.req.form.get('withmeta', 0))
-        visitor = FullSchemaVisitor(self.req, self.schema, skiprels=self.skip_rels, skipmeta=skipmeta)
-        s2d.schema2dot(outputfile=tmpfile, visitor=visitor,
-                       prophdlr=RestrictedSchemaDotPropsHandler(self.req))
+        visitor = FullSchemaVisitor(self.req, self.schema,
+                                    skiptypes=skipmeta and SKIP_TYPES or ())
+        s2d.schema2dot(outputfile=tmpfile, visitor=visitor)
 
 class CWETypeSchemaImageView(TmpFileViewMixin, EntityView):
     id = 'schemagraph'
     __select__ = implements('CWEType')
-
     content_type = 'image/png'
-    skip_rels = SKIPPED_RELS
 
     def _generate(self, tmpfile):
         """display schema information for an entity"""
         entity = self.entity(self.row, self.col)
         eschema = self.vreg.schema.eschema(entity.name)
-        visitor = OneHopESchemaVisitor(self.req, eschema, skiprels=self.skip_rels)
-        s2d.schema2dot(outputfile=tmpfile, visitor=visitor,
-                       prophdlr=RestrictedSchemaDotPropsHandler(self.req))
+        skipmeta = not int(self.req.form.get('withmeta', 0))
+        visitor = OneHopESchemaVisitor(self.req, eschema,
+                                       skiptypes=skipmeta and SKIP_TYPES or ())
+        s2d.schema2dot(outputfile=tmpfile, visitor=visitor)
 
 class CWRTypeSchemaImageView(CWETypeSchemaImageView):
     __select__ = implements('CWRType')
@@ -283,8 +244,7 @@
         entity = self.entity(self.row, self.col)
         rschema = self.vreg.schema.rschema(entity.name)
         visitor = OneHopRSchemaVisitor(self.req, rschema)
-        s2d.schema2dot(outputfile=tmpfile, visitor=visitor,
-                       prophdlr=RestrictedSchemaDotPropsHandler(self.req))
+        s2d.schema2dot(outputfile=tmpfile, visitor=visitor)
 
 ### facets
 
--- a/web/views/startup.py	Thu Jun 18 21:01:55 2009 +0200
+++ b/web/views/startup.py	Fri Jun 19 14:42:04 2009 +0200
@@ -16,8 +16,7 @@
 from cubicweb.selectors import match_user_groups, implements
 from cubicweb.common.uilib import ureport_as_html
 from cubicweb.web import ajax_replace_url, uicfg, httpcache
-from cubicweb.web.views import tabs
-from cubicweb.web.views.management import SecurityViewMixIn
+from cubicweb.web.views import tabs, management, schema
 
 class ManageView(StartupView):
     id = 'manage'
@@ -31,8 +30,6 @@
                 uicfg.indexview_etype_section.setdefault(eschema, 'schema')
             elif eschema.is_subobject(strict=True):
                 uicfg.indexview_etype_section.setdefault(eschema, 'subobject')
-            elif eschema.meta:
-                uicfg.indexview_etype_section.setdefault(eschema, 'system')
             else:
                 uicfg.indexview_etype_section.setdefault(eschema, 'application')
 
@@ -205,7 +202,7 @@
         self.wview('editable-table', rset, displayfilter=True)
 
 
-class ManagerSchemaPermissionsView(StartupView, SecurityViewMixIn):
+class ManagerSchemaPermissionsView(StartupView, management.SecurityViewMixIn):
     id = 'schema_security'
     __select__ = StartupView.__select__ & match_user_groups('managers')
 
@@ -221,7 +218,7 @@
                    if not eschema.is_final()]
         if not formparams['withmeta']:
             entities = [eschema for eschema in entities
-                        if not eschema.meta]
+                        if not eschema.schema_entity()]
         # compute relations
         relations = []
         if display_relations:
@@ -229,7 +226,7 @@
                          if not (rschema.is_final() or rschema.type in skiprels)]
             if not formparams['withmeta']:
                 relations = [rschema for rschema in relations
-                             if not rschema.meta]
+                             if not rschema.schema_relation()]
         # index
         self.w(u'<div id="schema_security"><a id="index" href="index"/>')
         self.w(u'<h2 class="schema">%s</h2>' % _('index').capitalize())
@@ -260,11 +257,11 @@
             self.w(u'<a id="%s" href="%s"/>' %  (eschema.type, eschema.type))
             self.w(u'<h3 class="schema">%s (%s) ' % (eschema.type, _(eschema.type)))
             url = html_escape(self.build_url('schema', **formparams) + '#index')
-            self.w(u'<a href="%s"><img src="%s" alt="%s"/></a>' % (url,  self.req.external_resource('UP_ICON'), _('up')))
+            self.w(u'<a href="%s"><img src="%s" alt="%s"/></a>' % (
+                url,  self.req.external_resource('UP_ICON'), _('up')))
             self.w(u'</h3>')
             self.w(u'<div style="margin: 0px 1.5em">')
             self.schema_definition(eschema, link=False)
-
             # display entity attributes only if they have some permissions modified
             modified_attrs = []
             for attr, etype in  eschema.attribute_definitions():
@@ -277,10 +274,7 @@
                 for attr in  modified_attrs:
                     self.w(u'<h4 class="schema">%s (%s)</h4> ' % (attr.type, _(attr.type)))
                     self.schema_definition(attr, link=False)
-                self.w(u'</div>')
-            else:
-                self.w(u'</div>')
-
+            self.w(u'</div>')
 
     def display_relations(self, relations, formparams):
         _ = self.req._
@@ -290,16 +284,19 @@
             self.w(u'<a id="%s" href="%s"/>' %  (rschema.type, rschema.type))
             self.w(u'<h3 class="schema">%s (%s) ' % (rschema.type, _(rschema.type)))
             url = html_escape(self.build_url('schema', **formparams) + '#index')
-            self.w(u'<a href="%s"><img src="%s" alt="%s"/></a>' % (url,  self.req.external_resource('UP_ICON'), _('up')))
+            self.w(u'<a href="%s"><img src="%s" alt="%s"/></a>' % (
+                url,  self.req.external_resource('UP_ICON'), _('up')))
             self.w(u'</h3>')
             self.w(u'<div style="margin: 0px 1.5em">')
             subjects = [str(subj) for subj in rschema.subjects()]
-            self.w(u'<div><strong>%s</strong> %s (%s)</div>' % (_('subject_plural:'),
-                                                ', '.join( [str(subj) for subj in rschema.subjects()]),
-                                                ', '.join( [_(str(subj)) for subj in rschema.subjects()])))
-            self.w(u'<div><strong>%s</strong> %s (%s)</div>' % (_('object_plural:'),
-                                                ', '.join( [str(obj) for obj in rschema.objects()]),
-                                                ', '.join( [_(str(obj)) for obj in rschema.objects()])))
+            self.w(u'<div><strong>%s</strong> %s (%s)</div>' % (
+                _('subject_plural:'),
+                ', '.join(str(subj) for subj in rschema.subjects()),
+                ', '.join(_(str(subj)) for subj in rschema.subjects())))
+            self.w(u'<div><strong>%s</strong> %s (%s)</div>' % (
+                _('object_plural:'),
+                ', '.join(str(obj) for obj in rschema.objects()),
+                ', '.join(_(str(obj)) for obj in rschema.objects())))
             self.schema_definition(rschema, link=False)
             self.w(u'</div>')
 
@@ -309,13 +306,13 @@
 
     def call(self):
         from cubicweb.schemaviewer import SchemaViewer
-        skipmeta = int(self.req.form.get('skipmeta', True))
-        schema = self.schema
+        if int(self.req.form.get('skipmeta', True)):
+            skip = schema.SKIP_TYPES
+        else:
+            skip = ()
         viewer = SchemaViewer(self.req)
-        layout = viewer.visit_schema(schema, display_relations=True,
-                                     skiprels=('is', 'is_instance_of', 'identity',
-                                               'owned_by', 'created_by'),
-                                     skipmeta=skipmeta)
+        layout = viewer.visit_schema(self.schema, display_relations=True,
+                                     skiptypes=skip)
         self.w(ureport_as_html(layout))