--- a/.hgtags Thu Jan 15 10:13:25 2009 +0100
+++ b/.hgtags Wed Jun 03 19:42:23 2009 +0200
@@ -12,3 +12,7 @@
18d3e56c1de4a6597ab36536964bc66b5550cf98 cubicweb-debian-version-3_0_2-1
0cb027c056f939ec3580ea1cc0aeda9f9884f0fa cubicweb-version-3_0_3
a736bae56d4a703a26933fb9875fb9caab216c6b cubicweb-debian-version-3_0_3-1
+2e400b8dfc25ae30db602f64601e30e210b3fade cubicweb-version-3_0_4
+fc222bc99929d395c1c2235c40d3bb6f247b4ba9 cubicweb-debian-version-3_0_4-1
+7ad527099393ef56f27af313392022bb8ed73082 cubicweb-version-3_0_9
+a8e9e53b245d53838a07aa8c76d1bed352692a9f cubicweb-debian-version-3_0_9-1
--- a/__pkginfo__.py Thu Jan 15 10:13:25 2009 +0100
+++ b/__pkginfo__.py Wed Jun 03 19:42:23 2009 +0200
@@ -6,11 +6,11 @@
distname = "cubicweb"
modname = "cubicweb"
-numversion = (3, 0, 3)
+numversion = (3, 0, 10)
version = '.'.join(str(num) for num in numversion)
-license = 'LCL'
-copyright = '''Copyright (c) 2003-2008 LOGILAB S.A. (Paris, FRANCE).
+license = 'GPL'
+copyright = '''Copyright (c) 2003-2009 LOGILAB S.A. (Paris, FRANCE).
http://www.logilab.fr/ -- mailto:contact@logilab.fr'''
author = "Logilab"
@@ -27,11 +27,12 @@
* a bunch of other management tools
"""
-web = ''
-ftp = ''
-pyversions = ['2.4']
+web = 'http://www.cubicweb.org'
+ftp = 'ftp://ftp.logilab.org/pub/cubicweb'
+pyversions = ['2.4', '2.5']
+import sys
from os import listdir, environ
from os.path import join, isdir
import glob
@@ -60,7 +61,8 @@
# --home install
pydir = 'python'
else:
- pydir = join('python2.4', 'site-packages')
+ python_version = '.'.join(str(num) for num in sys.version_info[0:2])
+ pydir = join('python' + python_version, 'site-packages')
try:
data_files = [
@@ -90,7 +92,6 @@
[join('share', 'cubicweb', 'cubes', 'shared', 'i18n'),
[join(i18n_dir, fname) for fname in listdir(i18n_dir)]],
# skeleton
-
]
except OSError:
# we are in an installed directory, don't care about this
--- a/common/appobject.py Thu Jan 15 10:13:25 2009 +0100
+++ b/common/appobject.py Wed Jun 03 19:42:23 2009 +0200
@@ -1,7 +1,7 @@
"""Base class for dynamically loaded objects manipulated in the web interface
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -12,6 +12,8 @@
from simplejson import dumps
from logilab.common.deprecation import obsolete
+
+from rql.nodes import VariableRef, SubQuery
from rql.stmts import Union, Select
from cubicweb import Unauthorized
--- a/common/entity.py Thu Jan 15 10:13:25 2009 +0100
+++ b/common/entity.py Wed Jun 03 19:42:23 2009 +0200
@@ -1,7 +1,7 @@
"""Base class for entity objects manipulated in clients
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -391,6 +391,10 @@
res['source'] = self.req.source_defs()[res['source']]
return res
+ def clear_local_perm_cache(self, action):
+ for rqlexpr in self.e_schema.get_rqlexprs(action):
+ self.req.local_perm_cache.pop((rqlexpr.eid, (('x', self.eid),)), None)
+
def check_perm(self, action):
self.e_schema.check_perm(self.req, action, self.eid)
@@ -998,6 +1002,7 @@
_done.add(self.eid)
containers = tuple(self.e_schema.fulltext_containers())
if containers:
+ yielded = False
for rschema, target in containers:
if target == 'object':
targets = getattr(self, rschema.type)
@@ -1008,6 +1013,9 @@
continue
for container in entity.fti_containers(_done):
yield container
+ yielded = True
+ if not yielded:
+ yield self
else:
yield self
--- a/common/migration.py Thu Jan 15 10:13:25 2009 +0100
+++ b/common/migration.py Wed Jun 03 19:42:23 2009 +0200
@@ -312,12 +312,18 @@
"""a configuration option's type has changed"""
self._option_changes.append(('typechanged', optname, oldtype, newvalue))
- def cmd_add_cube(self, cube):
+ def cmd_add_cubes(self, cubes):
+ """modify the list of used cubes in the in-memory config
+ returns newly inserted cubes, including dependencies
+ """
+ if isinstance(cubes, basestring):
+ cubes = (cubes,)
origcubes = self.config.cubes()
- newcubes = [p for p in self.config.expand_cubes([cube])
+ newcubes = [p for p in self.config.expand_cubes(cubes)
if not p in origcubes]
if newcubes:
- assert cube in newcubes
+ for cube in cubes:
+ assert cube in newcubes
self.config.add_cubes(newcubes)
return newcubes
@@ -346,7 +352,7 @@
if optdescr[0] == 'added':
optdict = self.config.get_option_def(optdescr[1])
if optdict.get('default') is REQUIRED:
- self.config.input_option(option, optdict)
+ self.config.input_option(optdescr[1], optdict)
self.config.generate_config(open(newconfig, 'w'))
show_diffs(configfile, newconfig)
if exists(newconfig):
--- a/common/mixins.py Thu Jan 15 10:13:25 2009 +0100
+++ b/common/mixins.py Wed Jun 03 19:42:23 2009 +0200
@@ -145,7 +145,6 @@
return self.iterchildren()
def is_leaf(self):
- print '*' * 80
return len(self.children()) == 0
def is_root(self):
@@ -165,7 +164,11 @@
@property
def state(self):
- return self.in_state[0].name
+ try:
+ return self.in_state[0].name
+ except IndexError:
+ self.warning('entity %s has no state', self)
+ return None
@property
def displayable_state(self):
--- a/common/selectors.py Thu Jan 15 10:13:25 2009 +0100
+++ b/common/selectors.py Wed Jun 03 19:42:23 2009 +0200
@@ -20,12 +20,12 @@
above by::
# in Python2.5
- from cubicweb.selectors import traced_selection
+ from cubicweb.common.selectors import traced_selection
with traced_selection():
self.view('calendar', myrset)
# in Python2.4
- from cubicweb import selectors
+ from cubicweb.common import selectors
selectors.TRACED_OIDS = ('calendar',)
self.view('calendar', myrset)
selectors.TRACED_OIDS = ()
@@ -50,7 +50,6 @@
from cubicweb.cwconfig import CubicWebConfiguration
from cubicweb.schema import split_expression
-
# helpers for debugging selectors
SELECTOR_LOGGER = logging.getLogger('cubicweb.selectors')
TRACED_OIDS = ()
@@ -64,6 +63,7 @@
if TRACED_OIDS == 'all' or cls.id in TRACED_OIDS:
SELECTOR_LOGGER.warning('selector %s returned %s for %s', selector.__name__, ret, cls)
return ret
+ traced.__name__ = selector.__name__
return traced
class traced_selection(object):
@@ -110,12 +110,12 @@
norset_selector = deprecated_function(none_rset)
@lltrace
-def rset(cls, req, rset, *args, **kwargs):
+def any_rset(cls, req, rset, *args, **kwargs):
"""accept result set, whatever the number of result"""
if rset is not None:
return 1
return 0
-rset_selector = deprecated_function(rset)
+rset_selector = deprecated_function(any_rset)
@lltrace
def nonempty_rset(cls, req, rset, *args, **kwargs):
@@ -161,13 +161,20 @@
def paginated_rset(cls, req, rset, *args, **kwargs):
"""accept result sets with more rows than the page size
"""
- if rset is None or len(rset) <= req.property_value('navigation.page-size'):
+ page_size = kwargs.get('page_size')
+ if page_size is None:
+ page_size = req.form.get('page_size')
+ if page_size is None:
+ page_size = req.property_value('navigation.page-size')
+ else:
+ page_size = int(page_size)
+ if rset is None or len(rset) <= page_size:
return 0
return 1
largerset_selector = deprecated_function(paginated_rset)
@lltrace
-def sorted_rset(cls, req, rset, row=None, col=None):
+def sorted_rset(cls, req, rset, row=None, col=None, **kwargs):
"""accept sorted result set"""
rqlst = rset.syntax_tree()
if len(rqlst.children) > 1 or not rqlst.children[0].orderby:
@@ -222,7 +229,7 @@
@lltrace
def authenticated_user(cls, req, *args, **kwargs):
"""accept if user is authenticated"""
- return not anonymous_selector(cls, req, *args, **kwargs)
+ return not anonymous_user(cls, req, *args, **kwargs)
not_anonymous_selector = deprecated_function(authenticated_user)
@lltrace
@@ -499,7 +506,7 @@
propval = req.property_value('%s.%s.context' % (cls.__registry__, cls.id))
if not propval:
propval = cls.context
- if context is not None and propval is not None and context != propval:
+ if context is not None and propval and context != propval:
return 0
return 1
contextprop_selector = deprecated_function(match_context_prop)
@@ -529,28 +536,36 @@
# compound selectors ##########################################################
non_final_entity = chainall(nonempty_rset, _non_final_entity)
+non_final_entity.__name__ = 'non_final_entity'
nfentity_selector = deprecated_function(non_final_entity)
implement_interface = chainall(non_final_entity, _implement_interface)
+implement_interface.__name__ = 'implement_interface'
interface_selector = deprecated_function(implement_interface)
accept = chainall(non_final_entity, accept_rset)
+accept.__name__ = 'accept'
accept_selector = deprecated_function(accept)
-accept_one = chainall(one_line_rset, accept_selector)
+accept_one = chainall(one_line_rset, accept)
+accept_one.__name__ = 'accept_one'
accept_one_selector = deprecated_function(accept_one)
rql_condition = chainall(non_final_entity, one_line_rset, _rql_condition)
+rql_condition.__name__ = 'rql_condition'
rqlcondition_selector = deprecated_function(rql_condition)
searchstate_accept = chainall(nonempty_rset, match_search_state, accept)
+searchstate_accept.__name__ = 'searchstate_accept'
searchstate_accept_selector = deprecated_function(searchstate_accept)
searchstate_accept_one = chainall(one_line_rset, match_search_state,
accept, _rql_condition)
+searchstate_accept_one.__name__ = 'searchstate_accept_one'
searchstate_accept_one_selector = deprecated_function(searchstate_accept_one)
searchstate_accept_one_but_etype = chainall(searchstate_accept_one, but_etype)
+searchstate_accept_one_but_etype.__name__ = 'searchstate_accept_one_but_etype'
searchstate_accept_one_but_etype_selector = deprecated_function(
searchstate_accept_one_but_etype)
--- a/common/test/unittest_entity.py Thu Jan 15 10:13:25 2009 +0100
+++ b/common/test/unittest_entity.py Wed Jun 03 19:42:23 2009 +0200
@@ -250,8 +250,7 @@
self.assertListEquals(rbc(e.relations_by_category('generic')),
[('primary_email', 'subject'),
('evaluee', 'subject'),
- ('for_user', 'object'),
- ('bookmarked_by', 'object')])
+ ('for_user', 'object')])
# owned_by is defined both as subject and object relations on EUser
self.assertListEquals(rbc(e.relations_by_category('generated')),
[('last_login_time', 'subject'),
@@ -263,7 +262,8 @@
('owned_by', 'subject'),
('created_by', 'object'),
('wf_info_for', 'object'),
- ('owned_by', 'object')])
+ ('owned_by', 'object'),
+ ('bookmarked_by', 'object')])
e = self.etype_instance('Personne')
self.assertListEquals(rbc(e.relations_by_category('primary')),
[('nom', 'subject'), ('eid', 'subject')])
--- a/common/uilib.py Thu Jan 15 10:13:25 2009 +0100
+++ b/common/uilib.py Wed Jun 03 19:42:23 2009 +0200
@@ -4,7 +4,7 @@
contains some functions designed to help implementation of cubicweb user interface
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -213,6 +213,21 @@
# HTML generation helper functions ############################################
+def simple_sgml_tag(tag, content=None, **attrs):
+ """generation of a simple sgml tag (eg without children tags) easier
+
+ content and attributes will be escaped
+ """
+ value = u'<%s' % tag
+ if attrs:
+ value += u' ' + u' '.join(u'%s="%s"' % (attr, html_escape(unicode(value)))
+ for attr, value in attrs.items())
+ if content:
+ value += u'>%s</%s>' % (html_escape(unicode(content)), tag)
+ else:
+ value += u'/>'
+ return value
+
def tooltipize(text, tooltip, url=None):
"""make an HTML tooltip"""
url = url or '#'
--- a/common/view.py Thu Jan 15 10:13:25 2009 +0100
+++ b/common/view.py Wed Jun 03 19:42:23 2009 +0200
@@ -2,7 +2,7 @@
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -28,9 +28,9 @@
<!ATTLIST html xmlns:cubicweb CDATA #FIXED \'http://www.logilab.org/2008/cubicweb\' >
<!ENTITY % coreattrs
- "id ID #IMPLIED
- class CDATA #IMPLIED
- style CDATA #IMPLIED
+ "id ID #IMPLIED
+ class CDATA #IMPLIED
+ style CDATA #IMPLIED
title CDATA #IMPLIED
cubicweb:sortvalue CDATA #IMPLIED
@@ -53,12 +53,14 @@
cubicweb:vid CDATA #IMPLIED
cubicweb:rql CDATA #IMPLIED
cubicweb:actualrql CDATA #IMPLIED
- cubicweb:rooteid CDATA #IMPLIED
+ cubicweb:rooteid CDATA #IMPLIED
cubicweb:dataurl CDATA #IMPLIED
- cubicweb:size CDATA #IMPLIED
+ cubicweb:size CDATA #IMPLIED
cubicweb:tlunit CDATA #IMPLIED
cubicweb:loadurl CDATA #IMPLIED
cubicweb:uselabel CDATA #IMPLIED
+ cubicweb:facetargs CDATA #IMPLIED
+ cubicweb:facetName CDATA #IMPLIED
"> ] '''
TRANSITIONAL_DOCTYPE = u'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" %s>\n'
@@ -71,7 +73,7 @@
A view is instantiated to render a [part of a] result set. View
subclasses may be parametred using the following class attributes:
-
+
* `templatable` indicates if the view may be embeded in a main
template or if it has to be rendered standalone (i.e. XML for
instance)
@@ -85,14 +87,14 @@
time to a write function to use.
"""
__registry__ = 'views'
-
+
templatable = True
need_navigation = True
# content_type = 'application/xhtml+xml' # text/xhtml'
binary = False
add_to_breadcrumbs = True
category = 'view'
-
+
def __init__(self, req, rset):
super(View, self).__init__(req, rset)
self.w = None
@@ -102,7 +104,7 @@
if self.req.xhtml_browser():
return 'application/xhtml+xml'
return 'text/html'
-
+
def set_stream(self, w=None):
if self.w is not None:
return
@@ -118,14 +120,14 @@
return stream
# main view interface #####################################################
-
+
def dispatch(self, w=None, **context):
"""called to render a view object for a result set.
This method is a dispatched to an actual method selected
according to optional row and col parameters, which are locating
a particular row or cell in the result set:
-
+
* if row [and col] are specified, `cell_call` is called
* if none of them is supplied, the view is considered to apply on
the whole result set (which may be None in this case), `call` is
@@ -147,7 +149,7 @@
# should default .call() method add a <div classs="section"> around each
# rset item
add_div_section = True
-
+
def call(self, **kwargs):
"""the view is called for an entire result set, by default loop
other rows of the result set and call the same view on the
@@ -169,10 +171,10 @@
def cell_call(self, row, col, **kwargs):
"""the view is called for a particular result set cell"""
raise NotImplementedError, self
-
+
def linkable(self):
"""return True if the view may be linked in a menu
-
+
by default views without title are not meant to be displayed
"""
if not getattr(self, 'title', None):
@@ -181,7 +183,7 @@
def is_primary(self):
return self.id == 'primary'
-
+
def url(self):
"""return the url associated with this view. Should not be
necessary for non linkable views, but a default implementation
@@ -197,7 +199,7 @@
self.req.set_content_type(self.content_type)
# view utilities ##########################################################
-
+
def view(self, __vid, rset, __fallback_vid=None, **kwargs):
"""shortcut to self.vreg.render method avoiding to pass self.req"""
try:
@@ -207,7 +209,7 @@
raise
view = self.vreg.select_view(__fallback_vid, self.req, rset, **kwargs)
return view.dispatch(**kwargs)
-
+
def wview(self, __vid, rset, __fallback_vid=None, **kwargs):
"""shortcut to self.view method automatically passing self.w as argument
"""
@@ -234,7 +236,7 @@
label = label or self.req._(action.title)
return u'<a href="%s">%s</a>' % (html_escape(action.url()), label)
return u''
-
+
def html_headers(self):
"""return a list of html headers (eg something to be inserted between
<head> and </head> of the returned page
@@ -242,7 +244,7 @@
by default return a meta tag to disable robot indexation of the page
"""
return [NOINDEX]
-
+
def page_title(self):
"""returns a title according to the result set - used for the
title in the HTML header
@@ -292,7 +294,7 @@
""" return the url of the entity creation form for a given entity type"""
return self.req.build_url('add/%s'%etype, **kwargs)
-
+
# concrete views base classes #################################################
class EntityView(View):
@@ -301,7 +303,7 @@
__registerer__ = accepts_registerer
__selectors__ = (accept,)
category = 'entityview'
-
+
def field(self, label, value, row=True, show_label=True, w=None, tr=True):
""" read-only field """
if w is None:
@@ -316,7 +318,7 @@
if row:
w(u'</div>')
-
+
class StartupView(View):
"""base class for views which doesn't need a particular result set
to be displayed (so they can always be displayed !)
@@ -325,7 +327,7 @@
__selectors__ = (match_user_group, none_rset)
require_groups = ()
category = 'startupview'
-
+
def url(self):
"""return the url associated with this view. We can omit rql here"""
return self.build_url('view', vid=self.id)
@@ -345,9 +347,9 @@
"""
__registerer__ = accepts_registerer
__selectors__ = (chainfirst(none_rset, accept),)
-
+
default_rql = None
-
+
def __init__(self, req, rset):
super(EntityStartupView, self).__init__(req, rset)
if rset is None:
@@ -357,7 +359,7 @@
def startup_rql(self):
"""return some rql to be executedif the result set is None"""
return self.default_rql
-
+
def call(self, **kwargs):
"""override call to execute rql returned by the .startup_rql
method if necessary
@@ -376,14 +378,14 @@
return self.build_url(vid=self.id)
return super(EntityStartupView, self).url()
-
+
class AnyRsetView(View):
"""base class for views applying on any non empty result sets"""
__registerer__ = priority_registerer
__selectors__ = (nonempty_rset,)
-
+
category = 'anyrsetview'
-
+
def columns_labels(self, tr=True):
if tr:
translate = display_name
@@ -400,7 +402,7 @@
label = translate(self.req, attr)
labels.append(label)
return labels
-
+
class EmptyRsetView(View):
"""base class for views applying on any empty result sets"""
@@ -419,7 +421,7 @@
__selectors__ = (match_user_group,)
require_groups = ()
-
+
def template(self, oid, **kwargs):
"""shortcut to self.registry.render method on the templates registry"""
w = kwargs.pop('w', self.w)
--- a/cwconfig.py Thu Jan 15 10:13:25 2009 +0100
+++ b/cwconfig.py Wed Jun 03 19:42:23 2009 +0200
@@ -148,6 +148,8 @@
if os.environ.get('APYCOT_ROOT'):
mode = 'test'
CUBES_DIR = '%(APYCOT_ROOT)s/local/share/cubicweb/cubes/' % os.environ
+ # create __init__ file
+ file(join(CUBES_DIR, '__init__.py'), 'w').close()
elif exists(join(CW_SOFTWARE_ROOT, '.hg')):
mode = 'dev'
CUBES_DIR = join(CW_SOFTWARE_ROOT, '../cubes')
--- a/debian/changelog Thu Jan 15 10:13:25 2009 +0100
+++ b/debian/changelog Wed Jun 03 19:42:23 2009 +0200
@@ -1,3 +1,22 @@
+cubicweb (3.0.10-1) unstable; urgency=low
+
+ * merge cubicweb-core package into cubicweb-common
+ * simplify debian/rules
+
+ -- Julien Jehannet <julien.jehannet@logilab.fr> Thu, 19 Feb 2009 16:24:09 +0100
+
+cubicweb (3.0.9-1) unstable; urgency=low
+
+ * new upstream (interim) release
+
+ -- Aurélien Campéas <aurelien.campeas@logilab.fr> Tue, 10 Feb 2009 14:05:12 +0100
+
+cubicweb (3.0.4-1) unstable; urgency=low
+
+ * new upstream release
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr> Tue, 27 Jan 2009 16:05:12 +0100
+
cubicweb (3.0.3-1) DISTRIBUTION; urgency=low
* new upstream release
--- a/debian/compat Thu Jan 15 10:13:25 2009 +0100
+++ b/debian/compat Wed Jun 03 19:42:23 2009 +0200
@@ -1,1 +1,1 @@
-5
+7
--- a/debian/control Thu Jan 15 10:13:25 2009 +0100
+++ b/debian/control Wed Jun 03 19:42:23 2009 +0200
@@ -2,16 +2,19 @@
Section: web
Priority: optional
Maintainer: Logilab Packaging Team <contact@logilab.fr>
-Uploaders: Sylvain Thenault <sylvain.thenault@logilab.fr>
-Build-Depends: debhelper (>= 5.0.37.1), python (>=2.4), python-dev (>=2.4), python-central (>= 0.5)
+Uploaders: Sylvain Thenault <sylvain.thenault@logilab.fr>,
+ Julien Jehannet <julien.jehannet@logilab.fr>
+Build-Depends: debhelper (>= 7), python-dev (>=2.4), python-central (>= 0.5)
Standards-Version: 3.8.0
+Homepage: http://www.cubicweb.org
XS-Python-Version: >= 2.4, << 2.6
+
Package: cubicweb
Architecture: all
XB-Python-Version: ${python:Versions}
Depends: ${python:Depends}, cubicweb-server (= ${source:Version}), cubicweb-twisted (= ${source:Version}), cubicweb-client (= ${source:Version})
-XBS-Recommends: (postgresql, postgresql-plpython, postgresql-contrib) | mysql | sqlite3
+XB-Recommends: (postgresql, postgresql-plpython, postgresql-contrib) | mysql | sqlite3
Recommends: postgresql | mysql | sqlite3
Description: the complete CubicWeb framework
CubicWeb is a semantic web application framework.
@@ -72,8 +75,10 @@
Package: cubicweb-common
Architecture: all
XB-Python-Version: ${python:Versions}
-Depends: ${python:Depends}, cubicweb-core (= ${source:Version}), python-logilab-mtconverter (>= 0.4.0), python-simpletal (>= 4.0), graphviz, gettext, python-lxml
+Depends: ${python:Depends}, python-logilab-mtconverter (>= 0.4.0), python-simpletal (>= 4.0), graphviz, gettext, python-lxml, python-logilab-common (>= 0.37.2), python-yams (>= 0.20.2), python-rql (>= 0.20.2)
Recommends: python-psyco
+Conflicts: cubicweb-core
+Replaces: cubicweb-core
Description: common library for the CubicWeb framework
CubicWeb is a semantic web application framework.
.
@@ -84,7 +89,7 @@
Package: cubicweb-ctl
Architecture: all
XB-Python-Version: ${python:Versions}
-Depends: ${python:Depends}, cubicweb-core (= ${source:Version})
+Depends: ${python:Depends}, cubicweb-common (= ${source:Version})
Description: tool to manage the CubicWeb framework
CubicWeb is a semantic web application framework.
.
@@ -104,17 +109,6 @@
pyro to connect to a repository server.
-Package: cubicweb-core
-Architecture: all
-XB-Python-Version: ${python:Versions}
-Depends: ${python:Depends}, python-logilab-common (>= 0.37.2), python-yams (>= 0.20.2), python-rql (>= 0.20.2)
-Description: core library for the CubicWeb framework
- CubicWeb is a semantic web application framework.
- .
- This package provides the core part of the library used by anyone having
- to do some cubicweb programming in Python.
-
-
Package: cubicweb-dev
Architecture: all
XB-Python-Version: ${python:Versions}
--- a/debian/cubicweb-client.dirs Thu Jan 15 10:13:25 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-usr/lib/python2.4/site-packages/cubicweb/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-client.install.in Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,1 @@
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/hercule.py usr/lib/PY_VERSION/site-packages/cubicweb
--- a/debian/cubicweb-common.dirs Thu Jan 15 10:13:25 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-usr/lib/python2.4/site-packages/cubicweb
-usr/lib/python2.4/site-packages/cubicweb/common
-usr/share/cubicweb/cubes/shared
-usr/share/doc/cubicweb-common
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-common.install.in Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,17 @@
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/common/ usr/lib/PY_VERSION/site-packages/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/entities/ usr/lib/PY_VERSION/site-packages/cubicweb
+debian/tmp/usr/share/cubicweb/cubes/shared/i18n usr/share/cubicweb/cubes/shared/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/rset.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/gettext.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/toolsutils.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/cwvreg.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/_exceptions.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/schemaviewer.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/dbapi.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/cwconfig.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/__init__.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/md5crypt.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/schema.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/interfaces.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/vregistry.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/__pkginfo__.py usr/share/pyshared/cubicweb
--- a/debian/cubicweb-core.dirs Thu Jan 15 10:13:25 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-usr/lib/python2.4/site-packages/cubicweb
-usr/share/doc/cubicweb-core
--- a/debian/cubicweb-ctl.cubicweb.init Thu Jan 15 10:13:25 2009 +0100
+++ b/debian/cubicweb-ctl.cubicweb.init Wed Jun 03 19:42:23 2009 +0200
@@ -11,5 +11,22 @@
# Short-Description: Start cubicweb application at boot time
### END INIT INFO
+# FIXME Seems to be inadequate here
+# FIXME If related to pyro, try instead:
+# export PYRO_STORAGE="/tmp"
cd /tmp
-/usr/bin/cubicweb-ctl $1 --force
+
+# FIXME Work-around about the following lintian error
+# E: cubicweb-ctl: init.d-script-does-not-implement-required-option /etc/init.d/cubicweb start
+#
+# Check if we are sure to not want the start-stop-daemon machinery here
+# Refer to Debian Policy Manual section 9.3.2 (Writing the scripts) for details.
+
+case "$1" in
+ "force-reload")
+ /usr/bin/cubicweb-ctl reload --force
+ ;;
+ "*|restart")
+ /usr/bin/cubicweb-ctl $1 --force
+ ;;
+esac
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-ctl.install.in Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,3 @@
+debian/tmp/usr/bin/cubicweb-ctl usr/bin/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/cwctl.py usr/lib/PY_VERSION/site-packages/cubicweb
+debian/cubicweb-ctl.bash_completion etc/bash_completion.d/cubicweb-ctl
--- a/debian/cubicweb-ctl.postinst Thu Jan 15 10:13:25 2009 +0100
+++ b/debian/cubicweb-ctl.postinst Wed Jun 03 19:42:23 2009 +0200
@@ -2,7 +2,7 @@
case "$1" in
configure|abort-upgrade|abort-remove|abort-deconfigure)
- update-rc.d cubicweb defaults >/dev/null
+ update-rc.d cubicweb defaults 99 >/dev/null
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
--- a/debian/cubicweb-dev.dirs Thu Jan 15 10:13:25 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-usr/lib/python2.4/site-packages/cubicweb
-usr/lib/python2.4/site-packages/cubicweb/common
-usr/lib/python2.4/site-packages/cubicweb/web
-usr/lib/python2.4/site-packages/cubicweb/server
-usr/lib/python2.4/site-packages/cubicweb/sobjects
-usr/lib/python2.4/site-packages/cubicweb/entities
-usr/share/doc/cubicweb-dev
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-dev.install.in Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,7 @@
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/devtools/ usr/lib/PY_VERSION/site-packages/cubicweb/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/skeleton/ usr/lib/PY_VERSION/site-packages/cubicweb/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/test usr/lib/PY_VERSION/site-packages/cubicweb/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/common/test usr/lib/PY_VERSION/site-packages/cubicweb/common/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/server/test usr/lib/PY_VERSION/site-packages/cubicweb/server/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/sobjects/test usr/lib/PY_VERSION/site-packages/cubicweb/sobjects/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/web/test usr/lib/PY_VERSION/site-packages/cubicweb/web/
--- a/debian/cubicweb-documentation.dirs Thu Jan 15 10:13:25 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-usr/share/doc/cubicweb-documentation/
-usr/share/doc/cubicweb-documentation/devmanual_fr
-usr/share/doc-base/
--- a/debian/cubicweb-documentation.install Thu Jan 15 10:13:25 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-debian/cubicweb-doc usr/share/doc-base/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-documentation.install.in Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,2 @@
+doc/book usr/share/doc/cubicweb-documentation
+debian/cubicweb-doc usr/share/doc-base/cubicweb-doc
--- a/debian/cubicweb-server.dirs Thu Jan 15 10:13:25 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-usr/lib/python2.4/site-packages/cubicweb/
-usr/share/cubicweb
-usr/share/doc/cubicweb-server
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-server.install.in Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,4 @@
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/server/ usr/lib/PY_VERSION/site-packages/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/sobjects/ usr/lib/PY_VERSION/site-packages/cubicweb
+debian/tmp/usr/share/cubicweb/schemas/ usr/share/cubicweb/
+debian/tmp/usr/share/cubicweb/migration/ usr/share/cubicweb/
--- a/debian/cubicweb-twisted.dirs Thu Jan 15 10:13:25 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-usr/lib/python2.4/site-packages
-usr/lib/python2.4/site-packages/cubicweb
-usr/share/doc/cubicweb-twisted
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-twisted.install.in Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,1 @@
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/etwist/ usr/lib/PY_VERSION/site-packages/cubicweb/
--- a/debian/cubicweb-web.dirs Thu Jan 15 10:13:25 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-usr/lib/python2.4/site-packages/
-usr/lib/python2.4/site-packages/cubicweb
-usr/share/cubicweb/cubes/shared
-usr/share/doc/cubicweb-web
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-web.install.in Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,3 @@
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/web usr/lib/PY_VERSION/site-packages/cubicweb
+debian/tmp/usr/share/cubicweb/cubes/shared/data usr/share/cubicweb/cubes/shared
+debian/tmp/usr/share/cubicweb/cubes/shared/wdoc usr/share/cubicweb/cubes/shared
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/cubicweb-web.lintian-overrides Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,1 @@
+cubicweb-web: embedded-javascript-library usr/share/cubicweb/cubes/shared/data/jquery.js
--- a/debian/rules Thu Jan 15 10:13:25 2009 +0100
+++ b/debian/rules Wed Jun 03 19:42:23 2009 +0200
@@ -4,12 +4,16 @@
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
+
+PY_VERSION:=$(shell pyversions -d)
+
build: build-stamp
build-stamp:
dh_testdir
# XXX doesn't work if logilab-doctools, logilab-xml are not in build depends
# and I can't get pbuilder find them in its chroot :(
- #cd doc && make
+ # cd doc && make
+ # FIXME cleanup and use sphinx-build as build-depends ?
python setup.py build
touch build-stamp
@@ -18,78 +22,42 @@
dh_testroot
rm -f build-stamp configure-stamp
rm -rf build
- rm -rf debian/cubicweb-*/
- find . -name "*.pyc" | xargs rm -f
+ #rm -rf debian/cubicweb-*/
+ find . -name "*.pyc" -delete
+ rm -f $(basename $(wildcard debian/*.in))
dh_clean
-install: build
+install: build $(basename $(wildcard debian/*.in))
dh_testdir
dh_testroot
- dh_clean -k
+ dh_clean
dh_installdirs
- ########## core package #############################################
- # put :
- # * all the python library and data in cubicweb-core
- # * scripts in cubicweb-server
- #
- # pick from each latter to construct each package
- python setup.py -q install_lib --no-compile --install-dir=debian/cubicweb-core/usr/lib/python2.4/site-packages/
- python setup.py -q install_data --install-dir=debian/cubicweb-core/usr/
- python setup.py -q install_scripts --install-dir=debian/cubicweb-server/usr/bin/
- ########## common package #############################################
- mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/common/ debian/cubicweb-common/usr/lib/python2.4/site-packages/cubicweb
- mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/entities/ debian/cubicweb-common/usr/lib/python2.4/site-packages/cubicweb
- # data
- mv debian/cubicweb-core/usr/share/cubicweb/cubes/shared/i18n debian/cubicweb-common/usr/share/cubicweb/cubes/shared/
+
+ #python setup.py install_lib --no-compile --install-dir=debian/cubicweb-common/usr/lib/python2.4/site-packages/
+ python setup.py -q install --no-compile --prefix=debian/tmp/usr
+
+ # Put all the python library and data in cubicweb-common
+ # and scripts in cubicweb-server
+ dh_install -vi
+ dh_lintian
+
+ # Remove unittests directory (should be available in cubicweb-dev only)
+ rm -rf debian/cubicweb-server/usr/lib/${PY_VERSION}/site-packages/cubicweb/server/test
+ rm -rf debian/cubicweb-server/usr/lib/${PY_VERSION}/site-packages/cubicweb/sobjects/test
+ rm -rf debian/cubicweb-web/usr/lib/${PY_VERSION}/site-packages/cubicweb/web/test
+ rm -rf debian/cubicweb-common/usr/lib/${PY_VERSION}/site-packages/cubicweb/common/test
+
+ # cubes directory must be managed as a valid python module
+ ls -l debian/cubicweb-common/usr/share/cubicweb/cubes
touch debian/cubicweb-common/usr/share/cubicweb/cubes/__init__.py
- ########## server package #############################################
- # library
- mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/server/ debian/cubicweb-server/usr/lib/python2.4/site-packages/cubicweb
- mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/sobjects/ debian/cubicweb-server/usr/lib/python2.4/site-packages/cubicweb
- # data
- mv debian/cubicweb-core/usr/share/cubicweb/schemas/ debian/cubicweb-server/usr/share/cubicweb/
- mv debian/cubicweb-core/usr/share/cubicweb/migration/ debian/cubicweb-server/usr/share/cubicweb/
- ########## twisted package ############################################
- # library
- mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/etwist/ debian/cubicweb-twisted/usr/lib/python2.4/site-packages/cubicweb/
- ########## web package ################################################
- # library
- mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/web/ debian/cubicweb-web/usr/lib/python2.4/site-packages/cubicweb/
- # data / web documentation
- mv debian/cubicweb-core/usr/share/cubicweb/cubes/shared/data debian/cubicweb-web/usr/share/cubicweb/cubes/shared/
- mv debian/cubicweb-core/usr/share/cubicweb/cubes/shared/wdoc debian/cubicweb-web/usr/share/cubicweb/cubes/shared/
- ########## ctl package ################################################
- # scripts
- mv debian/cubicweb-server/usr/bin/cubicweb-ctl debian/cubicweb-ctl/usr/bin/
- mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/cwctl.py debian/cubicweb-ctl/usr/lib/python2.4/site-packages/cubicweb
- mv debian/cubicweb-ctl.bash_completion debian/cubicweb-ctl/etc/bash_completion.d/cubicweb-ctl
- ########## client package #############################################
- # library
- mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/hercule.py debian/cubicweb-client/usr/lib/python2.4/site-packages/cubicweb
- ########## dev package ################################################
- # devtools package
- mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/devtools/ debian/cubicweb-dev/usr/lib/python2.4/site-packages/cubicweb/
- mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/skeleton/ debian/cubicweb-dev/usr/lib/python2.4/site-packages/cubicweb/
- # tests directories
- mv debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/test debian/cubicweb-dev/usr/lib/python2.4/site-packages/cubicweb/
- mv debian/cubicweb-common/usr/lib/python2.4/site-packages/cubicweb/common/test debian/cubicweb-dev/usr/lib/python2.4/site-packages/cubicweb/common/
- mv debian/cubicweb-server/usr/lib/python2.4/site-packages/cubicweb/server/test debian/cubicweb-dev/usr/lib/python2.4/site-packages/cubicweb/server/
- mv debian/cubicweb-server/usr/lib/python2.4/site-packages/cubicweb/sobjects/test debian/cubicweb-dev/usr/lib/python2.4/site-packages/cubicweb/sobjects/
- mv debian/cubicweb-web/usr/lib/python2.4/site-packages/cubicweb/web/test debian/cubicweb-dev/usr/lib/python2.4/site-packages/cubicweb/web/
- ########## documentation package ######################################
- cp -r doc/book debian/cubicweb-documentation/usr/share/doc/cubicweb-documentation/
- ########## core package ###############################################
- # small cleanup
- rm -rf debian/cubicweb-core/usr/share/cubicweb/
- # undistributed for now
- rm -rf debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/goa
- rm -rf debian/cubicweb-core/usr/lib/python2.4/site-packages/cubicweb/wsgi
+
+%: %.in
+ sed "s/PY_VERSION/${PY_VERSION}/g" < $< > $@
# Build architecture-independent files here.
binary-indep: build install
dh_testdir
dh_testroot -i
- dh_install -i
dh_pycentral -i
dh_installinit -i -n --name cubicweb -u"defaults 99"
dh_installlogrotate -i
--- a/devtools/fill.py Thu Jan 15 10:13:25 2009 +0100
+++ b/devtools/fill.py Wed Jun 03 19:42:23 2009 +0200
@@ -136,6 +136,9 @@
def generate_integer(self, attrname, index):
"""generates a consistent value for 'attrname' if it's an integer"""
+ choosed = self.generate_choice(attrname, index)
+ if choosed is not None:
+ return choosed
minvalue, maxvalue = get_bounds(self.e_schema, attrname)
if maxvalue is not None and maxvalue <= 0 and minvalue is None:
minvalue = maxvalue - index # i.e. randint(-index, 0)
--- a/devtools/repotest.py Thu Jan 15 10:13:25 2009 +0100
+++ b/devtools/repotest.py Wed Jun 03 19:42:23 2009 +0200
@@ -3,7 +3,7 @@
This module contains functions to initialize a new repository.
:organization: Logilab
-:copyright: 2003-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -249,7 +249,8 @@
_orig_select_principal = rqlannotation._select_principal
def _select_principal(scope, relations):
- return _orig_select_principal(scope, sorted(relations, key=lambda x: x.r_type))
+ return _orig_select_principal(scope, relations,
+ _sort=lambda rels: sorted(rels, key=lambda x: x.r_type))
try:
from cubicweb.server.msplanner import PartPlanInformation
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/devtools/test/data/bootstrap_cubes Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,1 @@
+person, comment
--- a/devtools/test/data/bootstrap_packages Thu Jan 15 10:13:25 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-eperson, ecomment
--- a/devtools/testlib.py Thu Jan 15 10:13:25 2009 +0100
+++ b/devtools/testlib.py Wed Jun 03 19:42:23 2009 +0200
@@ -78,6 +78,8 @@
return center - before <= line_no <= center + after
## base webtest class #########################################################
+VALMAP = {None: None, 'dtd': DTDValidator, 'xml': SaxOnlyValidator}
+
class WebTest(EnvBasedTC):
"""base class for web tests"""
__abstract__ = True
@@ -93,35 +95,28 @@
# SaxOnlyValidator : guarantees XML is well formed
# None : do not try to validate anything
# validators used must be imported from from.devtools.htmlparser
- validators = {
- # maps vid : validator name
- 'hcal' : SaxOnlyValidator,
- 'rss' : SaxOnlyValidator,
- 'rssitem' : None,
- 'xml' : SaxOnlyValidator,
- 'xmlitem' : None,
- 'xbel' : SaxOnlyValidator,
- 'xbelitem' : None,
- 'vcard' : None,
- 'fulltext': None,
- 'fullthreadtext': None,
- 'fullthreadtext_descending': None,
- 'text' : None,
- 'treeitemview': None,
- 'textincontext' : None,
- 'textoutofcontext' : None,
- 'combobox' : None,
- 'csvexport' : None,
- 'ecsvexport' : None,
+ content_type_validators = {
+ # maps MIME type : validator name
+ #
+ # do not set html validators here, we need HTMLValidator for html
+ # snippets
+ #'text/html': DTDValidator,
+ #'application/xhtml+xml': DTDValidator,
+ 'application/xml': SaxOnlyValidator,
+ 'text/xml': SaxOnlyValidator,
+ 'text/plain': None,
+ 'text/comma-separated-values': None,
+ 'text/x-vcard': None,
+ 'text/calendar': None,
+ 'application/json': None,
+ 'image/png': None,
}
- valmap = {None: None, 'dtd': DTDValidator, 'xml': SaxOnlyValidator}
- no_auto_populate = ()
- ignored_relations = ()
+ # maps vid : validator name (override content_type_validators)
+ vid_validators = dict((vid, VALMAP[valkey])
+ for vid, valkey in VIEW_VALIDATORS.iteritems())
- def __init__(self, *args, **kwargs):
- EnvBasedTC.__init__(self, *args, **kwargs)
- for view, valkey in VIEW_VALIDATORS.iteritems():
- self.validators[view] = self.valmap[valkey]
+ no_auto_populate = ()
+ ignored_relations = ()
def custom_populate(self, how_many, cursor):
pass
@@ -163,21 +158,24 @@
self.commit()
@nocoverage
- def _check_html(self, output, vid, template='main'):
+ def _check_html(self, output, view, template='main'):
"""raises an exception if the HTML is invalid"""
- if template is None:
- default_validator = HTMLValidator
- else:
- default_validator = DTDValidator
- validatorclass = self.validators.get(vid, default_validator)
+ try:
+ validatorclass = self.vid_validators[view.id]
+ except KeyError:
+ if template is None:
+ default_validator = HTMLValidator
+ else:
+ default_validator = DTDValidator
+ validatorclass = self.content_type_validators.get(view.content_type,
+ default_validator)
if validatorclass is None:
return None
validator = validatorclass()
- output = output.strip()
- return validator.parse_string(output)
+ return validator.parse_string(output.strip())
- def view(self, vid, rset, req=None, template='main', htmlcheck=True, **kwargs):
+ def view(self, vid, rset, req=None, template='main', **kwargs):
"""This method tests the view `vid` on `rset` using `template`
If no error occured while rendering the view, the HTML is analyzed
@@ -194,8 +192,6 @@
# print
req.form['vid'] = vid
view = self.vreg.select_view(vid, req, rset, **kwargs)
- if view.content_type not in ('application/xml', 'application/xhtml+xml', 'text/html'):
- htmlcheck = False
# set explicit test description
if rset is not None:
self.set_description("testing %s, mod=%s (%s)" % (vid, view.__module__, rset.printable_rql()))
@@ -207,15 +203,18 @@
elif template == 'main':
_select_view_and_rset = TheMainTemplate._select_view_and_rset
# patch TheMainTemplate.process_rql to avoid recomputing resultset
- TheMainTemplate._select_view_and_rset = lambda *a, **k: (view, rset)
+ def __select_view_and_rset(self, view=view, rset=rset):
+ self.rset = rset
+ return view, rset
+ TheMainTemplate._select_view_and_rset = __select_view_and_rset
try:
- return self._test_view(viewfunc, vid, htmlcheck, template, **kwargs)
+ return self._test_view(viewfunc, view, template, **kwargs)
finally:
if template == 'main':
TheMainTemplate._select_view_and_rset = _select_view_and_rset
- def _test_view(self, viewfunc, vid, htmlcheck=True, template='main', **kwargs):
+ def _test_view(self, viewfunc, view, template='main', **kwargs):
"""this method does the actual call to the view
If no error occured while rendering the view, the HTML is analyzed
@@ -227,10 +226,7 @@
output = None
try:
output = viewfunc(**kwargs)
- if htmlcheck:
- return self._check_html(output, vid, template)
- else:
- return output
+ return self._check_html(output, view, template)
except (SystemExit, KeyboardInterrupt):
raise
except:
@@ -238,19 +234,16 @@
# is not an AssertionError
klass, exc, tcbk = sys.exc_info()
try:
- msg = '[%s in %s] %s' % (klass, vid, exc)
+ msg = '[%s in %s] %s' % (klass, view.id, exc)
except:
- msg = '[%s in %s] undisplayable exception' % (klass, vid)
+ msg = '[%s in %s] undisplayable exception' % (klass, view.id)
if output is not None:
position = getattr(exc, "position", (0,))[0]
if position:
# define filter
-
-
output = output.splitlines()
width = int(log(len(output), 10)) + 1
line_template = " %" + ("%i" % width) + "i: %s"
-
# XXX no need to iterate the whole file except to get
# the line number
output = '\n'.join(line_template % (idx + 1, line)
@@ -259,10 +252,13 @@
msg+= '\nfor output:\n%s' % output
raise AssertionError, msg, tcbk
-
+
+ def to_test_etypes(self):
+ return unprotected_entities(self.schema, strict=True)
+
def iter_automatic_rsets(self):
"""generates basic resultsets for each entity type"""
- etypes = unprotected_entities(self.schema, strict=True)
+ etypes = self.to_test_etypes()
for etype in etypes:
yield self.execute('Any X WHERE X is %s' % etype)
@@ -281,23 +277,26 @@
"""returns the list of views that can be applied on `rset`"""
req = rset.req
only_once_vids = ('primary', 'secondary', 'text')
- skipped = ('restriction', 'cell')
req.data['ex'] = ValueError("whatever")
for vid, views in self.vreg.registry('views').items():
if vid[0] == '_':
continue
- try:
- view = self.vreg.select(views, req, rset)
- if view.id in skipped:
- continue
- if view.category == 'startupview':
+ if rset.rowcount > 1 and vid in only_once_vids:
+ continue
+ views = [view for view in views
+ if view.category != 'startupview'
+ and not issubclass(view, NotificationView)]
+ if views:
+ try:
+ view = self.vreg.select(views, req, rset)
+ if view.linkable():
+ yield view
+ else:
+ not_selected(self.vreg, view)
+ # else the view is expected to be used as subview and should
+ # not be tested directly
+ except NoSelectableObject:
continue
- if rset.rowcount > 1 and view.id in only_once_vids:
- continue
- if not isinstance(view, NotificationView):
- yield view
- except NoSelectableObject:
- continue
def list_actions_for(self, rset):
"""returns the list of actions that can be applied on `rset`"""
@@ -305,27 +304,25 @@
for action in self.vreg.possible_objects('actions', req, rset):
yield action
-
def list_boxes_for(self, rset):
"""returns the list of boxes that can be applied on `rset`"""
req = rset.req
for box in self.vreg.possible_objects('boxes', req, rset):
yield box
-
def list_startup_views(self):
"""returns the list of startup views"""
req = self.request()
for view in self.vreg.possible_views(req, None):
- if view.category != 'startupview':
- continue
- yield view.id
-
+ if view.category == 'startupview':
+ yield view.id
+ else:
+ not_selected(self.vreg, view)
+
def _test_everything_for(self, rset):
"""this method tries to find everything that can be tested
for `rset` and yields a callable test (as needed in generative tests)
"""
- rqlst = parse(rset.rql)
propdefs = self.vreg['propertydefs']
# make all components visible
for k, v in propdefs.items():
@@ -335,7 +332,7 @@
backup_rset = rset._prepare_copy(rset.rows, rset.description)
yield InnerTest(self._testname(rset, view.id, 'view'),
self.view, view.id, rset,
- rset.req.reset_headers(), 'main', not view.binary)
+ rset.req.reset_headers(), 'main')
# We have to do this because some views modify the
# resultset's syntax tree
rset = backup_rset
@@ -348,8 +345,6 @@
for box in self.list_boxes_for(rset):
yield InnerTest(self._testname(rset, box.id, 'box'), box.dispatch)
-
-
@staticmethod
def _testname(rset, objid, objtype):
return '%s_%s_%s' % ('_'.join(rset.column_types(0)), objid, objtype)
@@ -390,4 +385,36 @@
rset2 = rset.limit(limit=1, offset=row)
yield rset2
+def not_selected(vreg, vobject):
+ try:
+ vreg._selected[vobject.__class__] -= 1
+ except (KeyError, AttributeError):
+ pass
+def vreg_instrumentize(testclass):
+ from cubicweb.devtools.apptest import TestEnvironment
+ env = testclass._env = TestEnvironment('data', configcls=testclass.configcls,
+ requestcls=testclass.requestcls)
+ vreg = env.vreg
+ vreg._selected = {}
+ orig_select = vreg.__class__.select
+ def instr_select(self, *args, **kwargs):
+ selected = orig_select(self, *args, **kwargs)
+ try:
+ self._selected[selected.__class__] += 1
+ except KeyError:
+ self._selected[selected.__class__] = 1
+ except AttributeError:
+ pass # occurs on vreg used to restore database
+ return selected
+ vreg.__class__.select = instr_select
+
+def print_untested_objects(testclass, skipregs=('hooks', 'etypes')):
+ vreg = testclass._env.vreg
+ for registry, vobjectsdict in vreg.items():
+ if registry in skipregs:
+ continue
+ for vobjects in vobjectsdict.values():
+ for vobject in vobjects:
+ if not vreg._selected.get(vobject):
+ print 'not tested', registry, vobject
--- a/doc/book/en/A03a-concepts.en.txt Thu Jan 15 10:13:25 2009 +0100
+++ b/doc/book/en/A03a-concepts.en.txt Wed Jun 03 19:42:23 2009 +0200
@@ -11,7 +11,7 @@
.. image:: images/archi_globale.en.png
-`CubicWeb` framework is a server/client application framework. Those two
+`CubicWeb` framework is a server/client application framework. Those two
parties communicates through RQL (`CubicWeb` query language implementation)
and ResultSet (which will be explained in :ref:`TermsVocabulary`).
@@ -44,7 +44,7 @@
stored in the database at the time an instance is created. `CubicWeb`
provides a certain number of system entities included automatically as
it is necessary for the core of `CubicWeb` and a library of
- cubes (which defined application entities) that can be explicitely
+ cubes (which defined application entities) that can be explicitely
included if necessary.
*entity type*
@@ -69,7 +69,7 @@
*relation definition*
A relation definition is a 3-uple (subject entity type, relation type, object
entity type), with an associated set of property such as cardinality, constraints...
-
+
*repository*
This is the RQL server side of `CubicWeb`. Be carefull not to get
confused with a Mercurial repository or a debian repository.
@@ -77,7 +77,7 @@
*source*
A data source is a container of data (SGBD, LDAP directory, `Google
App Engine`'s datastore ...) integrated in the
- `CubicWeb` repository. This repository has at least one source, `system` which
+ `CubicWeb` repository. This repository has at least one source, `system` which
contains the schema of the application, plain-text index and others
vital informations for the system.
@@ -86,7 +86,7 @@
- ``repository`` : repository only, accessible for clients using Pyro
- ``twisted`` : web interface only, access the repository using Pyro
- - ``all-in-one`` : web interface and repository in a single process.
+ - ``all-in-one`` : web interface and repository in a single process.
The repository could be or not accessible using Pyro.
*cube*
@@ -94,7 +94,7 @@
to provide a specific functionnality or a complete `CubicWeb` application
potentially using other cubes. The available cubes are located in the file
system at `/path/to/forest/cubicweb/cubes` for a Mercurial forest installation,
- for a debian packages installation they will be located in
+ for a debian packages installation they will be located in
`/usr/share/cubicweb/cubes`.
Larger applications can be built faster by importing cubes,
adding entities and relationships and overriding the
@@ -102,7 +102,7 @@
cubes.
*instance*
- An instance is a specific installation of one or multiple cubes. All the required
+ An instance is a specific installation of one or multiple cubes. All the required
configuration files necessary for the well being of your web application
are grouped in an instance. This will refer to the cube(s) your application
is based on.
@@ -112,7 +112,7 @@
*application*
The term application is sometime used to talk about an instance
- and sometimes to talk of a cube depending on the context.
+ and sometimes to talk of a cube depending on the context.
So we would like to avoid using this term and try to use *cube* and
*instance* instead.
@@ -127,7 +127,7 @@
*query language*
A full-blown query language named RQL is used to formulate requests
- to the database or any sources such as LDAP or `Google App Engine`'s
+ to the database or any sources such as LDAP or `Google App Engine`'s
datastore.
*views*
@@ -147,7 +147,7 @@
This query language is inspired by SQL but is highest level, its implementation
generates SQL.
-
+
.. _`Python Remote Object`: http://pyro.sourceforge.net/
.. _`yams`: http://www.logilab.org/project/yams/
@@ -194,14 +194,14 @@
~~~~~~~~~~~~~~
The Python API developped to interface with RQL is inspired from the standard db-api,
-with a Connection object having the methods cursor, rollback and commit essentially.
+with a Connection object having the methods cursor, rollback and commit essentially.
The most important method is the `execute` method of a cursor :
`execute(rqlstring, args=None, eid_key=None, build_descr=True)`
:rqlstring: the RQL query to execute (unicode)
:args: if the query contains substitutions, a dictionnary containing the values to use
-:eid_key:
+:eid_key:
an implementation detail of the RQL queries cache implies that if a substitution
is used to introduce an eid *susceptible to raise the ambiguities in the query
type resolution*, then we have to specify the correponding key in the dictionnary
@@ -210,14 +210,14 @@
The `Connection` object owns the methods `commit` and `rollback`. You *should
never need to use them* during the development of the web interface based on
-the `CubicWeb` framework as it determines the end of the transaction depending
+the `CubicWeb` framework as it determines the end of the transaction depending
on the query execution success.
.. note::
While executing updates queries (SET, INSERT, DELETE), if a query generates
an error related to security, a rollback is automatically done on the current
transaction.
-
+
The `Request` class (`cubicweb.web`)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -243,7 +243,7 @@
key or the value `default` if the key is not defined
* `set_session_data(key, value)`, assign a value to a key
* `del_session_data(key)`, suppress the value associated to a key
-
+
:Cookies handling:
* `get_cookie()`, returns a dictionnary containing the value of the header
@@ -290,7 +290,7 @@
`__registry__`) and its identifier (attribute `id`). Usually we do not have
to take care of the register, only the identifier `id`.
-We can find a certain number of attributes and methods defined in this class
+We can find a certain number of attributes and methods defined in this class
and common to all the application objects.
At the recording, the following attributes are dynamically added to
@@ -333,7 +333,7 @@
also call the method `complete()` on the entity before returning it
:Data formatting:
- * `format_date(date, date_format=None, time=False)` returns a string for a
+ * `format_date(date, date_format=None, time=False)` returns a string for a
mx date time according to application's configuration
* `format_time(time)` returns a string for a mx date time according to
application's configuration
@@ -342,8 +342,8 @@
* `external_resource(rid, default=_MARKER)`, access to a value defined in the
configuration file `external_resource`
-
- * `tal_render(template, variables)`, renders a precompiled page template with
+
+ * `tal_render(template, variables)`, renders a precompiled page template with
variables in the given dictionary as context
.. note::
@@ -357,7 +357,7 @@
PrimaryView.f(self, arg1)
You'd better write: ::
-
+
class Truc(PrimaryView):
def f(self, arg1):
super(Truc, self).f(arg1)
@@ -374,7 +374,7 @@
in order to provide a specific feature or even a complete application using
others cubes.
-You can decide to write your own set of cubes if you wish to re-use the
+You can decide to write your own set of cubes if you wish to re-use the
entity types you develop. Lots of cubes are available from the `CubicWeb
Forge`_ under a free software license.
@@ -388,12 +388,12 @@
A cube is structured as follows:
::
-
+
mycube/
|
|-- data/
| |-- cubes.mycube.css
- | |-- cubes.mycube.js
+ | |-- cubes.mycube.js
| `-- external_resources
|
|-- debian/
@@ -437,12 +437,12 @@
|
`-- views.py
-
+
We can use subpackages instead of python modules for ``views.py``, ``entities.py``,
``schema.py`` or ``hooks.py``. For example, we could have:
::
-
+
mycube/
|
|-- entities.py
@@ -451,7 +451,7 @@
|-- forms.py
|-- primary.py
`-- widgets.py
-
+
where :
@@ -472,13 +472,13 @@
* file ``__pkginfo__.py`` provides component meta-data, especially the distribution
and the current version (server side and web interface) or sub-cubes used by
the cube.
-
-
+
+
At least you should have:
* the file ``__pkginfo__.py``
* the schema definition
- XXX false, we may want to have cubes which are only adding a service,
+ XXX false, we may want to have cubes which are only adding a service,
no persistent data (eg embeding for instance)
--- a/doc/book/en/B0011-schema-stdlib.en.txt Thu Jan 15 10:13:25 2009 +0100
+++ b/doc/book/en/B0011-schema-stdlib.en.txt Wed Jun 03 19:42:23 2009 +0200
@@ -37,34 +37,54 @@
An application is based on several basic cubes. In the set of available
basic cubes we can find for example :
-* `comment`, provides an entity type for `Comment` allowing us to comment others
- site's entities
-
-* `mailinglist`, provides an entity type for `Mailinglist` which groups informations
- in a discussion list
+* addressbook_: PhoneNumber and PostalAddress
-* `file`, provides entity types for `File` et `Image` used to represent
- files (text or binary) with additionnal informations such as MIME type or
- encoding.
-
-* `link`, provides an entity type for hypertext link (`Link`)
+* basket_: Basket (like a shopping cart)
-* `blog`, provides an entity type weblog (`Blog`)
-
-* `person`, provides an entity type for a person (`Person`)
+* blog_: Blog (a *very* basic blog)
-* `addressbook`, provides an entity type used to represent phone
- numbers (`PhoneNumber`) and mailing address (`PostalAddress`)
-
-* `classtags`, categorization system based on tags (`Tag`)
+* comment_: Comment (to attach comment threads to entities)
-* `classfolders`, categorization system based on folders hierarchy in order
- to create navigation sections (`Folder`)
-
-* `email`, archiving management for emails (`Email`, `Emailpart`,
+* email_: archiving management for emails (`Email`, `Emailpart`,
`Emailthread`)
-* `basket`, basket management (`Basket`) allowing to group entities
+* event_: Event (define events, display them in calendars)
+
+* file_: File (to allow users to upload and store binary or text files)
+
+* folder_: Folder (to organize things but grouping them in folders)
+
+* keyword_: Keyword (to define classification schemes)
+
+* link_: Link (to collect links to web resources)
+
+* mailinglist_: MailingList (to reference a mailing-list and the URLs
+ for its archives and its admin interface)
+
+* person_: Person (easily mixed with addressbook)
+
+* tag_: Tag (to tag anything)
+
+* task_: Task (something to be done between start and stop date)
+
+* zone_: Zone (to define places within larger places, for example a
+ city in a state in a country)
+
+.. _addressbook: http://www.cubicweb.org/project/cubicweb-addressbook
+.. _basket: http://www.cubicweb.org/project/cubicweb-basket
+.. _blog: http://www.cubicweb.org/project/cubicweb-blog
+.. _comment: http://www.cubicweb.org/project/cubicweb-comment
+.. _email: http://www.cubicweb.org/project/cubicweb-email
+.. _event: http://www.cubicweb.org/project/cubicweb-event
+.. _file: http://www.cubicweb.org/project/cubicweb-file
+.. _folder: http://www.cubicweb.org/project/cubicweb-folder
+.. _keyword: http://www.cubicweb.org/project/cubicweb-keyword
+.. _link: http://www.cubicweb.org/project/cubicweb-link
+.. _mailinglist: http://www.cubicweb.org/project/cubicweb-mailinglist
+.. _person: http://www.cubicweb.org/project/cubicweb-person
+.. _tag: http://www.cubicweb.org/project/cubicweb-tag
+.. _task: http://www.cubicweb.org/project/cubicweb-task
+.. _zone: http://www.cubicweb.org/project/cubicweb-zone
To declare the use of a component, once installed, add the name of the component
to the variable `__use__` in the file `__pkginfo__.py` of your own component.
--- a/doc/book/en/B0020-define-workflows.en.txt Thu Jan 15 10:13:25 2009 +0100
+++ b/doc/book/en/B0020-define-workflows.en.txt Wed Jun 03 19:42:23 2009 +0200
@@ -155,4 +155,3 @@
defined by the workflow. This transition, as defined in the workflow,
will only being displayed for the users belonging to the group
moderators of managers.
-
--- a/doc/book/en/B0031-define-entities.en.txt Thu Jan 15 10:13:25 2009 +0100
+++ b/doc/book/en/B0031-define-entities.en.txt Wed Jun 03 19:42:23 2009 +0200
@@ -55,13 +55,21 @@
It is possible to manage attributes/relations in the simple or multiple
editing form thanks to the following *rtags*:
-* `primary`, indicates that an attribute or a relation has to be inserted
- in the simple or multiple editing forms. In the case of a relation,
- the related entity editing form will be included in the editing form.
+* `primary`, indicates that an attribute or a relation has to be
+ inserted **in the simple or multiple editing forms**. In the case of
+ a relation, the related entity editing form will be included in the
+ editing form and represented as a combobox. Each item of the
+ combobox is a link to an existing entity.
-* `secondary`, indicates that an attribute or a relation has to be inserted
- in the simple editing form only. In the case of a relation, the related
- entity editing form sill be included in the editing form.
+* `secondary`, indicates that an attribute or a relation has to be
+ inserted **in the simple editing form only**. In the case of a
+ relation, the related entity editing form will be included in the
+ editing form and represented as a combobox. Each item of the combobox
+ is a link to an existing entity.
+
+* `inlineview`, includes the target entity's form in the editing form
+ of the current entity. It allows to create the target entity in the
+ same time as the current entity.
* `generic`, indicates that a relation has to be inserted in the simple
editing form, in the generic box of relation creation.
--- a/doc/book/en/B1030-form-management.en.txt Thu Jan 15 10:13:25 2009 +0100
+++ b/doc/book/en/B1030-form-management.en.txt Wed Jun 03 19:42:23 2009 +0200
@@ -13,7 +13,7 @@
The form generated by default does not fit your needs? You are not
required to re-do all by hands! :)
-* rtags primary, secondary, generated, generic,
+* rtags primary, secondary, generated, generic,
`Entity.relation_category(rtype, x='subject')`
* inline_view (now a rtag?)
* widget specification
@@ -36,8 +36,8 @@
starting by `eid:` and also having a parameter `__type` associated
(also *qualified* by eid)
-2. For all the attributes and the relations of an entity to edit:
-
+2. For all the attributes and the relations of an entity to edit:
+
1. search for a parameter `edits-<relation name>` or `edito-<relation name>`
qualified in the case of a relation where the entity is object
2. if found, the value returned is considered as the initial value
@@ -50,24 +50,24 @@
1. if a qualified parameter `__linkto` is specified, its value has to be
a string (or a list of string) such as: ::
-
+
<relation type>:<eids>:<target>
-
+
where <target> is either `subject` or `object` and each eid could be
separated from the others by a `_`. Target specifies if the *edited entity*
is subject or object of the relation and each relation specified will
be inserted.
2. if a qualified parameter `__clone_eid` is specified for an entity, the
- relations of the specified entity passed as value of this parameter are
+ relations of the specified entity passed as value of this parameter are
copied on the edited entity.
3. if a qualified parameter `__delete` is specified, its value must be
a string or a list of string such as follows: ::
-
+
<ssubjects eids>:<relation type>:<objects eids>
- where each eid subject or object can be seperated from the other
+ where each eid subject or object can be seperated from the other
by `_`. Each relation specified will be deleted.
4. if a qualified parameter `__insert` is specified, its value should
@@ -84,14 +84,14 @@
.. note::
-
+
* If the parameter `__action_delete` is found, all the entities specified
as to be edited will be deleted.
-
+
* If the parameter`__action_cancel` is found, no action is completed.
- * If the parameter `__action_apply` is found, the editing is applied
- normally but the redirection is done on the form
+ * If the parameter `__action_apply` is found, the editing is applied
+ normally but the redirection is done on the form
(see :ref:`RedirectionControl`).
* The parameter `__method` is also supported as for the main template
@@ -120,7 +120,7 @@
* `__redirectparams`: forms parameters to add to the path
-* `__redirectrql`: redirection RQL request
+* `__redirectrql`: redirection RQL request
* `__redirectvid`: redirection view identifier
@@ -132,6 +132,6 @@
* `__form_id`: initial view form identifier, used if `__action_apply` is
found
-In general we use either `__redirectpath` and `__redirectparams` or
+In general we use either `__redirectpath` and `__redirectparams` or
`__redirectrql` and `__redirectvid`.
--- a/doc/book/en/B1060-templates.en.txt Thu Jan 15 10:13:25 2009 +0100
+++ b/doc/book/en/B1060-templates.en.txt Wed Jun 03 19:42:23 2009 +0200
@@ -196,11 +196,9 @@
the case we want to create new CSS style, the best is to define it a in a new
CSS located under ``myapp/data/``.
-If you want to modify an existing CSS styling property, you will have to use
-``!important`` declaration to override the existing property. The application
-apply a higher priority on the default CSS and you can not change that.
-Customized CSS will not be read first.
+.. [TRANSLATE ME FROM FRENCH]
+.. 03-XX-external_resources.fr.txt
[TODO]
Add login menu in left column
--- a/doc/book/en/C011-installation.en.txt Thu Jan 15 10:13:25 2009 +0100
+++ b/doc/book/en/C011-installation.en.txt Wed Jun 03 19:42:23 2009 +0200
@@ -67,9 +67,9 @@
Then you can install:
-* `pyro` if you wish the repository is accessible through Pyro
+* `pyro` if you wish the repository to be accessible through Pyro
or if the client and the server are not running on the same machine
- (in suche case the packages will have to be isntalled on both
+ (in which case the packages will have to be installed on both
machines)
* `python-ldap` if you plan to use a LDAP source on the server
@@ -80,8 +80,8 @@
-------------------------
If you installed `CubicWeb` by cloning the Mercurial forest, then you
-will need to update the environment variable PYTHONPATH to add to it
-the path to the forest ``cubicweb``.
+will need to update the environment variable PYTHONPATH by adding
+the path to the forest ``cubicweb``:
Add the following lines to either `.bashrc` or `.bash_profile` to configure
your development environment ::
@@ -117,16 +117,13 @@
createuser -s username
- Initialize the password of the superuser you juste created with
+ Initialize the password of the superuser you just created with
``su - postgres`` and ``psql``.
This password will be asked to you later on where you will create an
instance with `cubicweb-ctl create`
-[XXX]
-Est-ce que ces etapes sont vraiment necessaires?
-sand : lors de l'installation de ma bdd cela n'a pas ete fait
-et il semble que tout aille bien. Doit etre verifie avec les experts.
+.. [XXX] Est-ce que ces etapes sont vraiment necessaires? sand : lors de l'installation de ma bdd cela n'a pas ete fait et il semble que tout aille bien. Doit etre verifie avec les experts.
* installation of plain-text index extension ::
@@ -140,7 +137,7 @@
Pyro configuration
------------------
-If you use Pyro, it is required to have a name server Pyro runing on your
+If you use Pyro, it is required to have a name server Pyro running on your
network (by default it is identified by a broadcast request).
To do so, you need to :
@@ -151,6 +148,6 @@
`pyro-nsd start`
* edit the file ``/etc/default/pyro-nsd`` so that the name server pyro
- will be launched automatically when the macine fire up
+ will be launched automatically when the machine fire up
--- a/doc/book/en/C012-create-instance.en.txt Thu Jan 15 10:13:25 2009 +0100
+++ b/doc/book/en/C012-create-instance.en.txt Wed Jun 03 19:42:23 2009 +0200
@@ -24,11 +24,11 @@
A cube defines entities, their views, their schemas and workflows
in an independant directory located in ``/path/to/forest/cubicweb/cubes/``
-for a Mercurila installation or in ``/usr/share/cubicweb/cubes`` for
-a debian packages installation.
+for a Mercurial installation or in ``/usr/share/cubicweb/cubes`` for
+a debian package installation.
When an instance is created, you list one or more cubes that your instance
-will use. Use a cube means having the entities defined in your cube's schema
+will use. Using a cube means having the entities defined in your cube's schema
available in your instance as well as their views and workflows.
.. note::
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/Z010-beginners.en.txt Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,12 @@
+.. -*- coding: utf-8 -*-
+
+.. _QuickInstall:
+
+===========================================
+Quick Installation of a `CubicWeb` instance
+===========================================
+
+.. include:: C011-installation.en.txt
+.. include:: Z012-create-instance.en.txt
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/Z012-create-instance.en.txt Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,79 @@
+.. -*- coding: utf-8 -*-
+
+Creation of your first instance
+===============================
+
+What is an instance?
+--------------------
+
+A `CubicWeb` instance is a container that
+refers to cubes and configuration parameters for your web application.
+Each instance is stored as a directory in ``~/etc/cubicweb.d`` which enables
+us to run your application.
+
+What is a cube?
+---------------
+
+Cubes represent data and basic building bricks of your web applications :
+blogs, person, date, addressbook and a lot more.
+
+.. XXX They related to each other by a 'Schema' which is also the PostGres representation.
+
+Each cube defines entities, their views, their schemas and workflows
+in an independant directory located in ``/path/to/forest/cubicweb/cubes/``
+for a Mercurial installation or in ``/usr/share/cubicweb/cubes`` for
+a debian package installation. For example, the 'blog' cube defines the entities
+blogs and blogentries.
+
+When an `CubicWeb` instance is created, you list the cubes that you want to use.
+Using a cube means having the entities defined in your cube's schema
+available in your instance as well as their views and workflows.
+
+
+Creating a basic `CubicWeb` Instance
+------------------------------------
+
+We can create an instance to view our
+application in a web browser. ::
+
+ cubicweb-ctl create blog myblog
+
+.. XXX or ::
+
+.. XXX cubicweb-ctl create forge myforge
+
+
+.. note::
+ The commands used below are more detailled in the section dedicated to
+ :ref:`cubicweb-ctl`.
+
+A series of questions will be prompted to you, the default answer is usually
+sufficient. You can allways modify the parameters later by editing
+configuration files. When a user/psswd is requested to access the database
+please use the login you create at the time you configured the database
+(:ref:`ConfigurationPostgres`).
+
+It is important to distinguish here the user used to access the database and
+the user used to login to the cubicweb application. When a `CubicWeb` application
+starts, it uses the login/psswd for the database to get the schema and handle
+low level transaction. But, when ``cubicweb-ctl create`` asks for
+a manager login/psswd of `CubicWeb`, it refers to an application user
+to administrate your web application.
+The configuration files are stored in *~/etc/cubicweb.d/myblog/*.
+
+To launch the web application, you just type ::
+
+ cubicweb-ctl start myblog
+
+You can see how it looks by
+visiting the URL `http://localhost:8080`.
+To login, please use the cubicweb administrator login/psswd you
+defined when you created the instance.
+
+To shutdown the instance ::
+
+ cubicweb-ctl stop myinstance
+
+.. XXX something like `cubicweb-ctl live-server intra` would be nice
+
+
--- a/doc/book/en/index.txt Thu Jan 15 10:13:25 2009 +0100
+++ b/doc/book/en/index.txt Wed Jun 03 19:42:23 2009 +0200
@@ -29,7 +29,9 @@
The hacker will join development at the forge_.
-The impatient will move right away to :ref:`MiseEnPlaceEnv`.
+The impatient will go strait away to :ref:`QuickInstall`.
+
+The impatient developper will move right away to :ref:`MiseEnPlaceEnv`.
.. _Logilab: http://www.logilab.fr/
.. _forge: http://www.cubicweb.org/project/
--- a/doc/book/en/makefile Thu Jan 15 10:13:25 2009 +0100
+++ b/doc/book/en/makefile Wed Jun 03 19:42:23 2009 +0200
@@ -43,7 +43,7 @@
#apydoc:
# epydoc --html -o epydoc/ -n ../server/*.py ../core/*.py ../common/*.py ../server/*/*.py ../modpython/*/*.py ../common/*/*.py
apidoc:
- epydoc --html -o apidoc -n "cubicweb" --exclude=setup --exclude=__pkginfo__ ../
+ epydoc --html -o apidoc -n "cubicweb" --exclude=setup --exclude=__pkginfo__ ../../../
# run sphinx ###
html:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/fr/03-XX-external_resources.fr.txt Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,135 @@
+.. -*- coding: utf-8 -*-
+
+
+Les ressources externes
+=======================
+
+Les ressources externes à une application regroupent l'ensemble des fichiers qui seront chargés dans l'entête des pages XHTML générées.
+Elles sont donc constituées principalement des feuilles de styles, des scripts javascripts et de certaines ressources graphiques comme l'icône favicon par exemple.
+
+
+Liste des feuilles de styles utilisées par défaut
+-------------------------------------------------
+
+Les fichiers par défaut se trouve dans les sources du framework. En voici le tableau récapitulatif:
+
++--------------------------------------+----------------------------------------------------+-----------------------------------+
+| Fichiers | Utilisation | Vues ou widget concernés |
++======================================+====================================================+===================================+
+| web/data/cubicweb.acl.css | formulaires pour le contrôle aux accès | editgroups, security |
+| web/data/cubicweb.calendar.css | calendriers | onemonthcal, oneweekcal |
+| web/data/cubicweb.calendar_popup.css | popup calendriers | DateWidget |
+| web/data/cubicweb.css | gabarit principal de l'application | |
+| web/data/cubicweb.facets.css | surcharge du `MIT Simile Exhibit Web Widgets`_ | filter_box |
+| web/data/cubicweb.form.css | formulaires | creation, inline-creation, copya, |
+| | | inline-edition, edition, muledit |
+| web/data/cubicweb.html_tree.css | style pour les widgets d'arborescence | |
+| web/data/cubicweb.ie.css | dédié aux comportements de Internet Explorer | |
+| web/data/cubicweb.iprogress.css | style pour les widgets d'avancement | |
+| web/data/cubicweb.login.css | page et popup d'authentification | logform |
+| web/data/cubicweb.mailform.css | style utilisé dans les formulaires d'envoi de mail | |
+| web/data/cubicweb.preferences.css | style pour la page des préférences utilisateurs | systemepropertiesform |
+| web/data/cubicweb.print.css | style dédié à l'impression | |
+| web/data/cubicweb.schema.css | style dédié au schéma de l'application | |
+| web/data/cubicweb.suggest.css | surcharge utilisée pour les suggestions | |
+| web/data/cubicweb.tablesorter.css | surcharge pour le tri dans les tableau | |
+| web/data/cubicweb.tableview.css | surcharge pour le tri sélectif | |
+| web/data/cubicweb.timetable.css | style pour le widget Timetable | timetable |
+| web/data/jquery.autocomplete.css | surcharge pour le widget `jQuery autocompleter`_ | |
+| web/data/jquery.treeview.css | surcharge pour le widget `jQuery treeview`_ | |
+| web/data/pygments.css | style pour la coloration des blocs de code | |
+| web/data/timeline-bundle.css | surcharge du `MIT Simile Timeline Web Widgets`_ | TimelineWidget |
+| web/data/ui.tabs.css | surcharge pour le widget Tabs de `jQuery UI`_ | |
++--------------------------------------+----------------------------------------------------+-----------------------------------+
+
+.. _MIT Simile Exhibit Web Widgets: http://code.google.com/p/simile-widgets/wiki/Exhibit
+.. _MIT Simile Timeline Web Widgets: http://code.google.com/p/simile-widgets/wiki/Timeline
+.. _jQuery autocompleter: http://www.dyve.net/jquery/?autocomplete
+.. _jQuery treeview: http://plugins.jquery.com/project/treeview
+.. _jQuery UI: http://docs.jquery.com/UI
+
+D'une manière générale, si vous réutiliser un nom de fichier existant, vous écrasez le contenu du fichier d'origine.
+
+
+Changer les feuilles de styles
+------------------------------
+
+Configuration statique
+~~~~~~~~~~~~~~~~~~~~~~
+Dans les sources de votre nouveau cube, vous devez éditer le fichier *data/external_resources* et définir la variable de configuration:
+
+ # CSS stylesheets to include in HTML headers
+ # uncomment the line below to use template specific stylesheet
+ STYLESHEETS = DATADIR/cubicweb.css
+
+Les styles sont définis dans le fichier external_resources par 3 variables:
+
+- la variable STYLESHEETS est défine pour tous les types de médias
+- la variable STYLESHEETS_PRINT sont les styles applicables pour l'impression
+- la variable IE_STYLESHEETS s'appliquent uniquement aux versions d'Internet Explorer
+
+En copiant le fichier d'origine **cubicweb.css**, il est alors possible de modifier le gabarit de base du framework CubicWeb.
+Il est également possible de réutiliser le fichier d'origine.
+
+En créant un nouveau fichier **cubes.(le_nom_du_cube).css** dans le répertoire **data/** et en ajoutant une directive css @import, il est possible de réutiliser les styles définis par défaut:
+
+ @import url("cubicweb.css");
+
+
+Chargement dynamique de feuilles de style dans vos vues
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Il est possible de charger des css spécifiques pour une vue par l'utilisation de la méthode add_css():
+
+ self.req.add_css('mon_cube.css')
+
+
+Les ressources graphiques de base
+---------------------------------
+
+Vous pouvez changer certaines ressources graphiques comme:
+
+- le logo du site:
+
+ # path to the logo (relative to the application main script, seen as a
+ # directory, hence .. when you are not using an absolute path)
+ LOGO = DATADIR/logo.png
+
+- la 'favicon' du site:
+
+ FAVICON = DATADIR/favicon.ico
+
+- le logo des flux RSS:
+
+ RSS_LOGO = DATADIR/rss.png
+
+- l'icône permettant l'appel au widget 'calendrier':
+
+ CALENDAR_ICON = DATADIR/calendar.png
+
+- l'icône utilisée pour la validation d'une recherche:
+
+ SEARCH_GO = DATADIR/go.png
+
+- l'icône d'aide en ligne:
+
+ HELP = DATADIR/help.png
+
+
+Ajouter vos scripts javascripts
+-------------------------------
+
+Configuration statique
+~~~~~~~~~~~~~~~~~~~~~~
+Vous devez surcharger la variable JAVASCRIPTS dans le fichier *data/external_resources* de votre cube.
+
+Chargement dynamique de script javascript dans vos vues
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Il est possible de charger vos scripts par la méthode add_js():
+
+ self.req.add_js('mon_script.js')
+
+
+Problèmes connus
+----------------
+
+Il est important de noter que la méthode de chargement dynamique ne marche pas avec les widgets Ajax. Vos fichiers devront déjà être au préalable avoir été chargés.
--- a/doc/book/fr/makefile Thu Jan 15 10:13:25 2009 +0100
+++ b/doc/book/fr/makefile Wed Jun 03 19:42:23 2009 +0200
@@ -43,7 +43,7 @@
#apydoc:
# epydoc --html -o epydoc/ -n ../server/*.py ../core/*.py ../common/*.py ../server/*/*.py ../modpython/*/*.py ../common/*/*.py
apidoc:
- epydoc --html -o apidoc -n "cubicweb" --exclude=setup --exclude=__pkginfo__ ../
+ epydoc --html -o apidoc -n "cubicweb" --exclude=setup --exclude=__pkginfo__ ../../../
# run sphinx ###
html:
--- a/entities/__init__.py Thu Jan 15 10:13:25 2009 +0100
+++ b/entities/__init__.py Wed Jun 03 19:42:23 2009 +0200
@@ -1,7 +1,7 @@
"""base application's entities class implementation: `AnyEntity`
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
--- a/entities/authobjs.py Thu Jan 15 10:13:25 2009 +0100
+++ b/entities/authobjs.py Wed Jun 03 19:42:23 2009 +0200
@@ -1,3 +1,10 @@
+"""entity classes user and group entities
+
+:organization: Logilab
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+__docformat__ = "restructuredtext en"
from logilab.common.decorators import cached
from cubicweb import Unauthorized
@@ -26,6 +33,7 @@
'in_group' : 'primary',
('owned_by', '*', 'object') : ('generated', 'link'),
('created_by','*','object') : ('generated', 'link'),
+ ('bookmarked_by', '*', 'object'): ('generated', 'create'),
}
# used by repository to check if the user can log in or not
@@ -85,6 +93,13 @@
"""
return self.matching_groups(group) == 1
+ def is_anonymous(self):
+ """ checks if user is an anonymous user"""
+ #FIXME on the web-side anonymous user is detected according
+ # to config['anonymous-user'], we don't have this info on
+ # the server side.
+ return self.groups == frozenset(('guests', ))
+
def owns(self, eid):
if hasattr(self.req, 'unsafe_execute'):
# use unsafe_execute on the repository side, in case
--- a/entities/lib.py Thu Jan 15 10:13:25 2009 +0100
+++ b/entities/lib.py Wed Jun 03 19:42:23 2009 +0200
@@ -1,7 +1,7 @@
"""entity classes for optional library entities
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
--- a/goa/__init__.py Thu Jan 15 10:13:25 2009 +0100
+++ b/goa/__init__.py Wed Jun 03 19:42:23 2009 +0200
@@ -28,7 +28,7 @@
regular python datetime object
"""
if yamstype is None:
- yamstype = guess_yamstype_from_date(datetimeobj)
+ yamstype = guess_yamstype_for_date(datetimeobj)
assert yamstype is not None
if yamstype == 'Datetime':
# don't use date, db model doesn't actually support it, only datetime
--- a/goa/appobjects/components.py Thu Jan 15 10:13:25 2009 +0100
+++ b/goa/appobjects/components.py Wed Jun 03 19:42:23 2009 +0200
@@ -15,7 +15,7 @@
from cubicweb.schema import display_name
from cubicweb.common.view import StartupView, EntityView
from cubicweb.common.selectors import (one_line_rset, match_search_state,
- accept_selector)
+ accept)
from cubicweb.web import Redirect
from cubicweb.web.views import vid_from_rset
from cubicweb.goa.db import rset_from_objs
@@ -31,7 +31,7 @@
"""
id = 'search-associate'
- __selectors__ = (one_line_rset, match_search_state, accept_selector)
+ __selectors__ = (one_line_rset, match_search_state, accept)
accepts = ('Any',)
search_states = ('linksearch',)
--- a/goa/db.py Thu Jan 15 10:13:25 2009 +0100
+++ b/goa/db.py Wed Jun 03 19:42:23 2009 +0200
@@ -391,7 +391,7 @@
@classmethod
def kind(cls):
- return self.id
+ return cls.id
@classmethod
def properties(cls):
--- a/goa/overrides/rqlannotation.py Thu Jan 15 10:13:25 2009 +0100
+++ b/goa/overrides/rqlannotation.py Wed Jun 03 19:42:23 2009 +0200
@@ -1,4 +1,4 @@
-def set_qdata(union, noinvariant):
+def set_qdata(getrschema, union, noinvariant):
pass
class SQLGenAnnotator(object):
--- a/goa/test/unittest_editcontroller.py Thu Jan 15 10:13:25 2009 +0100
+++ b/goa/test/unittest_editcontroller.py Wed Jun 03 19:42:23 2009 +0200
@@ -17,7 +17,7 @@
config.global_set_option('use-google-auth', False)
config.global_set_option('schema-type', 'yams')
config.global_set_option('included-cubes', ())
- config.global_set_option('included-yams-cubes', ('eblog',))
+ config.global_set_option('included-yams-cubes', ('blog',))
MODEL_CLASSES = ()
from cubicweb.web.views import editcontroller
--- a/goa/testlib.py Thu Jan 15 10:13:25 2009 +0100
+++ b/goa/testlib.py Wed Jun 03 19:42:23 2009 +0200
@@ -7,7 +7,7 @@
# additional monkey patches necessary in regular cubicweb environment
from cubicweb.server import rqlannotation
from cubicweb.goa.overrides import rqlannotation as goarqlannotation
-rqlannotation.sqlgen_annotate = goarqlannotation.sqlgen_annotate
+rqlannotation.SQLGenAnnotator = goarqlannotation.SQLGenAnnotator
rqlannotation.set_qdata = goarqlannotation.set_qdata
try:
@@ -58,7 +58,7 @@
_DS_TEMPL_FILE = 'tmpdb-template'
def load_schema_hook(self, loader):
- loader.import_yams_template_schema('data')
+ loader.import_yams_cube_schema('data')
@property
def DS_FILE(self):
--- a/goa/tools/i18n.py Thu Jan 15 10:13:25 2009 +0100
+++ b/goa/tools/i18n.py Wed Jun 03 19:42:23 2009 +0200
@@ -221,7 +221,7 @@
os.chdir(appdirectory)
potfiles = []
if osp.exists(osp.join('i18n', 'entities.pot')):
- potfiles = potfiles.append( osp.join('i18n', scfile) )
+ potfiles = potfiles.append( osp.join('i18n', 'entities.pot') )
print '******** extract schema messages'
schemapot = osp.join(tempdir, 'schema.pot')
potfiles.append(schemapot)
--- a/i18n/en.po Thu Jan 15 10:13:25 2009 +0100
+++ b/i18n/en.po Wed Jun 03 19:42:23 2009 +0200
@@ -376,6 +376,9 @@
msgid "Problem occured"
msgstr ""
+msgid "Project linked data"
+msgstr ""
+
msgid "RQLExpression"
msgstr "RQL expression"
@@ -717,6 +720,9 @@
msgid "add"
msgstr ""
+msgid "add Bookmark bookmarked_by EUser object"
+msgstr "bookmark"
+
msgid "add EEType add_permission RQLExpression subject"
msgstr "rql expression for the add permission"
@@ -1311,6 +1317,9 @@
msgid "created_by_object"
msgstr "has created"
+msgid "creating Bookmark (Bookmark bookmarked_by EUser %(linkto)s)"
+msgstr "creating bookmark for %(linkto)s"
+
msgid "creating EConstraint (EFRDef %(linkto)s constrained_by EConstraint)"
msgstr "creating constraint for attribute %(linkto)s"
@@ -1668,12 +1677,18 @@
msgid "february"
msgstr ""
+msgid "file tree view"
+msgstr ""
+
msgid "final"
msgstr ""
msgid "firstname"
msgstr ""
+msgid "foaf"
+msgstr ""
+
msgid "follow"
msgstr ""
@@ -1997,6 +2012,9 @@
msgid "list"
msgstr ""
+msgid "loading"
+msgstr ""
+
msgid "log in"
msgstr ""
@@ -2025,6 +2043,9 @@
msgid "manage bookmarks"
msgstr ""
+msgid "manage permissions"
+msgstr ""
+
msgid "manage security"
msgstr ""
@@ -2137,6 +2158,9 @@
msgid "not authorized"
msgstr ""
+msgid "not selected"
+msgstr ""
+
msgid "not specified"
msgstr ""
@@ -2173,6 +2197,15 @@
msgid "ordernum"
msgstr "order"
+msgid "owl (tbox+abox)"
+msgstr ""
+
+msgid "owlabox"
+msgstr ""
+
+msgid "owlaboxlight"
+msgstr ""
+
msgid "owned_by"
msgstr "owned by"
@@ -2416,6 +2449,9 @@
msgid "select this entity"
msgstr ""
+msgid "selected"
+msgstr ""
+
msgid "semantic description of this attribute"
msgstr ""
@@ -2541,6 +2577,9 @@
msgid "task progression"
msgstr ""
+msgid "tbox"
+msgstr ""
+
msgid "text"
msgstr ""
@@ -2617,6 +2656,9 @@
msgid "transition_of_object"
msgstr "use transitions"
+msgid "tree view"
+msgstr ""
+
msgid "tuesday"
msgstr ""
--- a/i18n/es.po Thu Jan 15 10:13:25 2009 +0100
+++ b/i18n/es.po Wed Jun 03 19:42:23 2009 +0200
@@ -381,6 +381,9 @@
msgid "Problem occured"
msgstr "Ha ocurrido un error"
+msgid "Project linked data"
+msgstr ""
+
msgid "RQLExpression"
msgstr "Expresión RQL"
@@ -738,6 +741,9 @@
msgid "add"
msgstr "agregar"
+msgid "add Bookmark bookmarked_by EUser object"
+msgstr ""
+
msgid "add EEType add_permission RQLExpression subject"
msgstr "Definir una expresión RQL de agregación"
@@ -1359,6 +1365,9 @@
msgid "created_by_object"
msgstr "ha creado"
+msgid "creating Bookmark (Bookmark bookmarked_by EUser %(linkto)s)"
+msgstr ""
+
msgid "creating EConstraint (EFRDef %(linkto)s constrained_by EConstraint)"
msgstr "creación condicionada por el atributo %(linkto)s"
@@ -1745,12 +1754,18 @@
msgid "february"
msgstr "febrero"
+msgid "file tree view"
+msgstr ""
+
msgid "final"
msgstr "final"
msgid "firstname"
msgstr "nombre"
+msgid "foaf"
+msgstr ""
+
msgid "follow"
msgstr "seguir la liga"
@@ -2090,6 +2105,9 @@
msgid "list"
msgstr "liste"
+msgid "loading"
+msgstr ""
+
msgid "log in"
msgstr "s'identifier"
@@ -2118,6 +2136,9 @@
msgid "manage bookmarks"
msgstr "gÈrer les signets"
+msgid "manage permissions"
+msgstr ""
+
msgid "manage security"
msgstr "gestion de la sÈcuritÈ"
@@ -2232,6 +2253,9 @@
msgid "not authorized"
msgstr "non autorisÈ"
+msgid "not selected"
+msgstr ""
+
msgid "not specified"
msgstr "non spÈcifiÈ"
@@ -2268,6 +2292,15 @@
msgid "ordernum"
msgstr "ordre"
+msgid "owl (tbox+abox)"
+msgstr ""
+
+msgid "owlabox"
+msgstr ""
+
+msgid "owlaboxlight"
+msgstr ""
+
msgid "owned_by"
msgstr "appartient ‡"
@@ -2521,6 +2554,9 @@
msgid "select this entity"
msgstr "sÈlectionner cette entitÈ"
+msgid "selected"
+msgstr ""
+
msgid "semantic description of this attribute"
msgstr "description sÈmantique de cet attribut"
@@ -2649,6 +2685,9 @@
msgid "task progression"
msgstr "avancement de la t‚che"
+msgid "tbox"
+msgstr ""
+
msgid "text"
msgstr "text"
@@ -2726,6 +2765,9 @@
msgid "transition_of_object"
msgstr "a pour transition"
+msgid "tree view"
+msgstr ""
+
msgid "tuesday"
msgstr "mardi"
--- a/i18n/fr.po Thu Jan 15 10:13:25 2009 +0100
+++ b/i18n/fr.po Wed Jun 03 19:42:23 2009 +0200
@@ -381,6 +381,9 @@
msgid "Problem occured"
msgstr "Une erreur est survenue"
+msgid "Project linked data"
+msgstr ""
+
msgid "RQLExpression"
msgstr "Expression RQL"
@@ -740,6 +743,9 @@
msgid "add"
msgstr "ajouter"
+msgid "add Bookmark bookmarked_by EUser object"
+msgstr "signet"
+
msgid "add EEType add_permission RQLExpression subject"
msgstr "définir une expression RQL d'ajout"
@@ -1197,7 +1203,7 @@
msgstr "la barre de requête rql, dans l'en-tête de page"
msgid "components_rss_feed_url"
-msgstr ""
+msgstr "syndication rss"
msgid "components_rss_feed_url_description"
msgstr ""
@@ -1361,14 +1367,17 @@
msgid "created_by_object"
msgstr "a créé"
+msgid "creating Bookmark (Bookmark bookmarked_by EUser %(linkto)s)"
+msgstr "création d'un signet pour %(linkto)s"
+
msgid "creating EConstraint (EFRDef %(linkto)s constrained_by EConstraint)"
-msgstr "création contrainte pour l'attribut %(linkto)s"
+msgstr "création d'une contrainte pour l'attribut %(linkto)s"
msgid "creating EConstraint (ENFRDef %(linkto)s constrained_by EConstraint)"
-msgstr "création contrainte pour la relation %(linkto)s"
+msgstr "création d'une contrainte pour la relation %(linkto)s"
msgid "creating EFRDef (EFRDef relation_type ERType %(linkto)s)"
-msgstr "création attribut %(linkto)s"
+msgstr "création d'un attribut %(linkto)s"
msgid "creating ENFRDef (ENFRDef relation_type ERType %(linkto)s)"
msgstr "création relation %(linkto)s"
@@ -1744,12 +1753,18 @@
msgid "february"
msgstr "février"
+msgid "file tree view"
+msgstr "arborescence (fichiers)"
+
msgid "final"
msgstr "final"
msgid "firstname"
msgstr "prénom"
+msgid "foaf"
+msgstr "foaf"
+
msgid "follow"
msgstr "suivre le lien"
@@ -2091,6 +2106,9 @@
msgid "list"
msgstr "liste"
+msgid "loading"
+msgstr "chargement"
+
msgid "log in"
msgstr "s'identifier"
@@ -2119,6 +2137,9 @@
msgid "manage bookmarks"
msgstr "gérer les signets"
+msgid "manage permissions"
+msgstr "gestion des permissions"
+
msgid "manage security"
msgstr "gestion de la sécurité"
@@ -2233,6 +2254,9 @@
msgid "not authorized"
msgstr "non autorisé"
+msgid "not selected"
+msgstr "non sélectionné"
+
msgid "not specified"
msgstr "non spécifié"
@@ -2269,6 +2293,15 @@
msgid "ordernum"
msgstr "ordre"
+msgid "owl (tbox+abox)"
+msgstr ""
+
+msgid "owlabox"
+msgstr ""
+
+msgid "owlaboxlight"
+msgstr ""
+
msgid "owned_by"
msgstr "appartient à "
@@ -2522,6 +2555,9 @@
msgid "select this entity"
msgstr "sélectionner cette entité"
+msgid "selected"
+msgstr "sélectionné"
+
msgid "semantic description of this attribute"
msgstr "description sémantique de cet attribut"
@@ -2650,6 +2686,9 @@
msgid "task progression"
msgstr "avancement de la tâche"
+msgid "tbox"
+msgstr ""
+
msgid "text"
msgstr "text"
@@ -2727,6 +2766,9 @@
msgid "transition_of_object"
msgstr "a pour transition"
+msgid "tree view"
+msgstr "arborescence"
+
msgid "tuesday"
msgstr "mardi"
--- a/interfaces.py Thu Jan 15 10:13:25 2009 +0100
+++ b/interfaces.py Wed Jun 03 19:42:23 2009 +0200
@@ -238,3 +238,7 @@
def rss_feed_url(self):
"""return an url which layout sub-entities item
"""
+class ISIOC(Interface):
+ """interface for entities with sioc views"""
+
+
--- a/rset.py Thu Jan 15 10:13:25 2009 +0100
+++ b/rset.py Wed Jun 03 19:42:23 2009 +0200
@@ -1,7 +1,7 @@
"""The `ResultSet` class which is returned as result of a rql query
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -60,11 +60,15 @@
def __repr__(self):
if not self.rows:
return '<empty resultset for %r>' % self.rql
+ rows = self.rows
+ if len(rows) > 10:
+ rows = rows[:10] + ['...']
if not self.description:
- return '<resultset %r: %s>' % (self.rql, '\n'.join(str(r) for r in self.rows))
- return '<resultset %r: %s>' % (self.rql,
- '\n'.join('%s (%s)' % (r, d)
- for r, d in zip(self.rows, self.description)))
+ return '<resultset %r (%s rows): %s>' % (self.rql, len(self.rows),
+ '\n'.join(str(r) for r in rows))
+ return '<resultset %r (%s rows): %s>' % (self.rql, len(self.rows),
+ '\n'.join('%s (%s)' % (r, d)
+ for r, d in zip(rows, self.description)))
@cached
def possible_actions(self):
@@ -464,7 +468,8 @@
rqlst = self.syntax_tree()
etype = self.description[row][col]
if self.vreg.schema.eschema(etype).is_final():
- # final type, find a better (ambiguous) one
+ # final type, find a better one to locate the correct subquery
+ # (ambiguous if possible)
for i in xrange(len(rqlst.children[0].selection)):
if i == col:
continue
@@ -476,18 +481,17 @@
locate_query_col = i
if len(self.column_types(i)) > 1:
break
- # UNION query, find the subquery from which this entity has been
- # found
+ # UNION query, find the subquery from which this entity has been found
select = rqlst.locate_subquery(locate_query_col, etype, self.args)
try:
myvar = select.selection[col].variable
except AttributeError:
- # no .selection attribute is available
+ # not a variable
return None, None
rel = myvar.main_relation()
if rel is not None:
index = rel.children[0].variable.selected_index()
- if index is not None:
+ if index is not None and self.rows[row][index]:
return self.get_entity(row, index), rel.r_type
return None, None
--- a/schema.py Thu Jan 15 10:13:25 2009 +0100
+++ b/schema.py Wed Jun 03 19:42:23 2009 +0200
@@ -1,7 +1,7 @@
"""classes to define schemas for CubicWeb
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
--- a/server/__init__.py Thu Jan 15 10:13:25 2009 +0100
+++ b/server/__init__.py Wed Jun 03 19:42:23 2009 +0200
@@ -113,6 +113,8 @@
for eid, etype in needisfix:
handler.session.unsafe_execute('SET X is E WHERE X eid %(x)s, E name %(name)s',
{'x': eid, 'name': etype}, 'x')
+ handler.session.unsafe_execute('SET X is_instance_of E WHERE X eid %(x)s, E name %(name)s',
+ {'x': eid, 'name': etype}, 'x')
# insert versions
handler.cmd_add_entity('EProperty', pkey=u'system.version.cubicweb',
value=unicode(config.cubicweb_version()))
--- a/server/hooks.py Thu Jan 15 10:13:25 2009 +0100
+++ b/server/hooks.py Wed Jun 03 19:42:23 2009 +0200
@@ -2,7 +2,7 @@
entities...
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
--- a/server/migractions.py Thu Jan 15 10:13:25 2009 +0100
+++ b/server/migractions.py Wed Jun 03 19:42:23 2009 +0200
@@ -11,7 +11,7 @@
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -264,13 +264,15 @@
self.commit()
def cmd_add_cube(self, cube, update_database=True):
+ self.cmd_add_cubes( (cube,), update_database)
+
+ def cmd_add_cubes(self, cubes, update_database=True):
"""update_database is telling if the database schema should be updated
or if only the relevant eproperty should be inserted (for the case where
a cube has been extracted from an existing application, so the
cube schema is already in there)
"""
- newcubes = super(ServerMigrationHelper, self).cmd_add_cube(
- cube)
+ newcubes = super(ServerMigrationHelper, self).cmd_add_cubes(cubes)
if not newcubes:
return
for pack in newcubes:
@@ -279,22 +281,22 @@
if not update_database:
self.commit()
return
- self.new_schema = self.config.load_schema()
+ with_new_cubes = self.config.load_schema()
new = set()
# execute pre-create files
for pack in reversed(newcubes):
self.exec_event_script('precreate', self.config.cube_dir(pack))
# add new entity and relation types
- for rschema in self.new_schema.relations():
+ for rschema in with_new_cubes.relations():
if not rschema in self.repo.schema:
self.cmd_add_relation_type(rschema.type)
new.add(rschema.type)
- for eschema in self.new_schema.entities():
+ for eschema in with_new_cubes.entities():
if not eschema in self.repo.schema:
self.cmd_add_entity_type(eschema.type)
new.add(eschema.type)
# check if attributes has been added to existing entities
- for rschema in self.new_schema.relations():
+ for rschema in with_new_cubes.relations():
existingschema = self.repo.schema.rschema(rschema.type)
for (fromtype, totype) in rschema.iter_rdefs():
if existingschema.has_rdef(fromtype, totype):
@@ -679,11 +681,11 @@
espschema = eschema.specializes()
if repospschema and not espschema:
self.rqlexec('DELETE X specializes Y WHERE X is EEType, X name %(x)s',
- {'x': str(repoechema)})
+ {'x': str(repoeschema)})
elif not repospschema and espschema:
self.rqlexec('SET X specializes Y WHERE X is EEType, X name %(x)s, '
'Y is EEType, Y name %(y)s',
- {'x': str(repoechema), 'y': str(epschema)})
+ {'x': str(repoeschema), 'y': str(espschema)})
self.rqlexecall(ss.updateeschema2rql(eschema),
ask_confirm=self.verbosity >= 2)
for rschema, targettypes, x in eschema.relation_definitions(True):
--- a/server/msplanner.py Thu Jan 15 10:13:25 2009 +0100
+++ b/server/msplanner.py Wed Jun 03 19:42:23 2009 +0200
@@ -288,17 +288,21 @@
flag = 0
for v in crossvars:
if isinstance(v, Constant):
- self._sourcesvars[ssource][v] = set(self._solindices)
+ allsols = set(self._solindices)
+ try:
+ self._sourcesvars[ssource][v] = allsols
+ except KeyError:
+ self._sourcesvars[ssource] = {v: allsols}
if len(vsources[v]) == 1:
if iter(vsources[v]).next()[0].uri == 'system':
flag = 1
for ov in crossvars:
- if ov is not v and ov._q_invariant:
+ if ov is not v and (isinstance(ov, Constant) or ov._q_invariant):
ssset = frozenset((ssource,))
self._remove_sources(ov, vsources[ov] - ssset)
else:
for ov in crossvars:
- if ov is not v and ov._q_invariant:
+ if ov is not v and (isinstance(ov, Constant) or ov._q_invariant):
needsplit = False
break
else:
@@ -661,7 +665,7 @@
if not var.scope is self.rqlst:
if isinstance(var, Variable):
return var, sourcevars.pop(var)
- secondchoice = var, sourcevars.pop(var)
+ secondchoice = var
else:
# priority to variable outer scope
for var in sourcevars:
@@ -995,7 +999,9 @@
step = AggrStep(plan, selection, select, atemptable, temptable)
step.children = steps
elif len(steps) > 1:
- if select.need_intersect:
+ if select.need_intersect or any(select.need_intersect
+ for step in steps
+ for select in step.union.children):
if temptable:
step = IntersectFetchStep(plan)
else:
--- a/server/mssteps.py Thu Jan 15 10:13:25 2009 +0100
+++ b/server/mssteps.py Wed Jun 03 19:42:23 2009 +0200
@@ -6,7 +6,7 @@
for now)
:organization: Logilab
-:copyright: 2003-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -274,9 +274,9 @@
result &= frozenset(step.execute())
result = list(result)
if self.offset:
- result = result[offset:]
+ result = result[self.offset:]
if self.limit:
- result = result[:limit]
+ result = result[:self.limit]
return result
--- a/server/querier.py Thu Jan 15 10:13:25 2009 +0100
+++ b/server/querier.py Wed Jun 03 19:42:23 2009 +0200
@@ -196,7 +196,7 @@
self._insert_security(union, noinvariant)
self.rqlhelper.simplify(union)
self.sqlannotate(union)
- set_qdata(union, noinvariant)
+ set_qdata(self.schema.rschema, union, noinvariant)
if union.has_text_query:
self.cache_key = None
--- a/server/repository.py Thu Jan 15 10:13:25 2009 +0100
+++ b/server/repository.py Wed Jun 03 19:42:23 2009 +0200
@@ -11,7 +11,7 @@
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -490,7 +490,7 @@
session = self.internal_session()
try:
if session.execute('EUser X WHERE X login %(login)s', {'login': login}):
- return
+ return False
# we have to create the user
user = self.vreg.etype_class('EUser')(session, None)
if isinstance(password, unicode):
@@ -505,6 +505,7 @@
session.commit()
finally:
session.close()
+ return True
def connect(self, login, password, cnxprops=None):
"""open a connection for a given user
@@ -791,7 +792,7 @@
# since the current session user may not have required permissions to
# do necessary stuff and we don't want to commit user session.
#
- # More other, even if session is already an internal session but is
+ # Moreover, even if session is already an internal session but is
# processing a commit, we have to use another one
if not session.is_internal_session:
session = self.internal_session()
@@ -803,6 +804,7 @@
entity = source.before_entity_insertion(session, lid, etype, eid)
if source.should_call_hooks:
self.hm.call_hooks('before_add_entity', etype, session, entity)
+ # XXX call add_info with complete=False ?
self.add_info(session, entity, source, lid)
source.after_entity_insertion(session, lid, entity)
if source.should_call_hooks:
--- a/server/rqlannotation.py Thu Jan 15 10:13:25 2009 +0100
+++ b/server/rqlannotation.py Wed Jun 03 19:42:23 2009 +0200
@@ -20,7 +20,7 @@
#if server.DEBUG:
# print '-------- sql annotate', repr(rqlst)
getrschema = annotator.schema.rschema
- has_text_query = need_intersect = False
+ has_text_query = False
need_distinct = rqlst.distinct
for rel in rqlst.iget_nodes(Relation):
if rel.neged(strict=True):
@@ -29,13 +29,6 @@
else:
rschema = getrschema(rel.r_type)
if not rschema.is_final():
- # if one of the relation's variable is ambiguous, an intersection
- # will be necessary
- for vref in rel.get_nodes(VariableRef):
- var = vref.variable
- if not var.stinfo['selected'] and len(var.stinfo['possibletypes']) > 1:
- need_intersect = True
- break
if rschema.inlined:
try:
var = rel.children[1].children[0].variable
@@ -147,23 +140,23 @@
except CantSelectPrincipal:
stinfo['invariant'] = False
rqlst.need_distinct = need_distinct
- rqlst.need_intersect = need_intersect
return has_text_query
class CantSelectPrincipal(Exception): pass
-def _select_principal(sqlscope, relations):
+def _select_principal(sqlscope, relations, _sort=lambda x:x):
"""given a list of rqlst relations, select one which will be used to
represent an invariant variable (e.g. using on extremity of the relation
instead of the variable's type table
"""
+ # _sort argument is there for test
diffscope_rels = {}
has_same_scope_rel = False
ored_rels = set()
diffscope_rels = set()
- for rel in relations:
+ for rel in _sort(relations):
# note: only eid and has_text among all final relations may be there
if rel.r_type in ('eid', 'identity'):
has_same_scope_rel = rel.sqlscope is sqlscope
@@ -183,18 +176,17 @@
if isinstance(common_parent(rel1, rel2), Or):
ored_rels.discard(rel1)
ored_rels.discard(rel2)
- for rel in ored_rels:
+ for rel in _sort(ored_rels):
if rel.sqlscope is sqlscope:
return rel
diffscope_rels.add(rel)
# if DISTINCT query, can use variable from a different scope as principal
# since introduced duplicates will be removed
if sqlscope.stmt.distinct and diffscope_rels:
- return iter(diffscope_rels).next()
+ return iter(_sort(diffscope_rels)).next()
# XXX could use a relation for a different scope if it can't generate
# duplicates, so we would have to check cardinality
- raise CantSelectPrincipal()
-
+ raise CantSelectPrincipal()
def _select_main_var(relations):
"""given a list of rqlst relations, select one which will be used as main
@@ -207,12 +199,12 @@
return principal
-def set_qdata(union, noinvariant):
+def set_qdata(getrschema, union, noinvariant):
"""recursive function to set querier data on variables in the syntax tree
"""
for select in union.children:
for subquery in select.with_:
- set_qdata(subquery.query, noinvariant)
+ set_qdata(getrschema, subquery.query, noinvariant)
for var in select.defined_vars.itervalues():
if var.stinfo['invariant']:
if var in noinvariant and not var.stinfo['principal'].r_type == 'has_text':
@@ -221,6 +213,23 @@
var._q_invariant = True
else:
var._q_invariant = False
+ for rel in select.iget_nodes(Relation):
+ if rel.neged(strict=True) and not rel.is_types_restriction():
+ rschema = getrschema(rel.r_type)
+ if not rschema.is_final():
+ # if one of the relation's variable is ambiguous but not
+ # invariant, an intersection will be necessary
+ for vref in rel.get_nodes(VariableRef):
+ var = vref.variable
+ if (not var._q_invariant and var.valuable_references() == 1
+ and len(var.stinfo['possibletypes']) > 1):
+ select.need_intersect = True
+ break
+ else:
+ continue
+ break
+ else:
+ select.need_intersect = False
class SQLGenAnnotator(object):
--- a/server/securityhooks.py Thu Jan 15 10:13:25 2009 +0100
+++ b/server/securityhooks.py Wed Jun 03 19:42:23 2009 +0200
@@ -2,7 +2,7 @@
the user connected to a session
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -54,6 +54,7 @@
entity.check_perm('update')
check_entity_attributes(session, entity)
except Unauthorized:
+ entity.clear_local_perm_cache('update')
CheckEntityPermissionOp(session, entity=entity, action='update')
def before_del_entity(session, eid):
--- a/server/session.py Thu Jan 15 10:13:25 2009 +0100
+++ b/server/session.py Wed Jun 03 19:42:23 2009 +0200
@@ -21,6 +21,18 @@
from cubicweb.common.utils import make_uid
from cubicweb.server.rqlrewrite import RQLRewriter
+_ETYPE_PYOBJ_MAP = { bool: 'Boolean',
+ int: 'Int',
+ long: 'Int',
+ float: 'Float',
+ Decimal: 'Decimal',
+ unicode: 'String',
+ NoneType: None,
+ Binary: 'Bytes',
+ DateTimeType: 'Datetime',
+ DateTimeDeltaType: 'Interval',
+ }
+
def etype_from_pyobj(value):
"""guess yams type from python value"""
# note:
@@ -28,17 +40,7 @@
# * use type(value) and not value.__class__ since mx instances have no
# __class__ attribute
# * XXX Date, Time
- return {bool: 'Boolean',
- int: 'Int',
- long: 'Int',
- float: 'Float',
- Decimal: 'Decimal',
- unicode: 'String',
- NoneType: None,
- Binary: 'Bytes',
- DateTimeType: 'Datetime',
- DateTimeDeltaType: 'Interval',
- }[type(value)]
+ return _ETYPE_PYOBJ_MAP[type(value)]
def is_final(rqlst, variable, args):
# try to find if this is a final var or not
@@ -58,35 +60,8 @@
description.append(term.get_type(solution, args))
return description
-#XXX rql <= 0.18.3 bw compat
from rql import stmts
-if not hasattr(stmts.Union, 'get_variable_variables'):
- def _union_get_variable_variables(self):
- """return the set of variable names which take different type according to
- the solution
- """
- change = set()
- values = {}
- for select in self.children:
- change.update(select.get_variable_variables(values))
- return change
- stmts.Union.get_variable_variables = _union_get_variable_variables
-
- def _select_get_variable_variables(self, _values=None):
- """return the set of variable names which take different type according to
- the solution
- """
- change = set()
- if _values is None:
- _values = {}
- for solution in self.solutions:
- for vname, etype in solution.iteritems():
- if not vname in _values:
- _values[vname] = etype
- elif _values[vname] != etype:
- change.add(vname)
- return change
- stmts.Select.get_variable_variables = _select_get_variable_variables
+assert hasattr(stmts.Union, 'get_variable_variables'), "You need RQL > 0.18.3"
class Session(RequestSessionMixIn):
"""tie session id, user, connections pool and other session data all
--- a/server/sources/native.py Thu Jan 15 10:13:25 2009 +0100
+++ b/server/sources/native.py Wed Jun 03 19:42:23 2009 +0200
@@ -188,7 +188,7 @@
rqlst.restricted_vars = ()
rqlst.children[0].solutions = self._sols
self.repo.querier.sqlgen_annotate(rqlst)
- set_qdata(rqlst, ())
+ set_qdata(self.schema.rschema, rqlst, ())
return rqlst
def set_schema(self, schema):
--- a/server/sources/pyrorql.py Thu Jan 15 10:13:25 2009 +0100
+++ b/server/sources/pyrorql.py Wed Jun 03 19:42:23 2009 +0200
@@ -159,7 +159,8 @@
external repository
"""
self.info('synchronizing pyro source %s', self.uri)
- extrepo = self.get_connection()._repo
+ cnx = self.get_connection()
+ extrepo = cnx._repo
etypes = self.support_entities.keys()
if mtime is None:
mtime = self.last_update_time()
@@ -170,11 +171,13 @@
try:
for etype, extid in modified:
try:
- eid = self.extid2eid(extid, etype, session)
- rset = session.eid_rset(eid, etype)
- entity = rset.get_entity(0, 0)
- entity.complete(entity.e_schema.indexable_attributes())
- repo.index_entity(session, entity)
+ exturi = cnx.describe(extid)[1]
+ if exturi == 'system' or not exturi in repo.sources_by_uri:
+ eid = self.extid2eid(extid, etype, session)
+ rset = session.eid_rset(eid, etype)
+ entity = rset.get_entity(0, 0)
+ entity.complete(entity.e_schema.indexable_attributes())
+ repo.index_entity(session, entity)
except:
self.exception('while updating %s with external id %s of source %s',
etype, extid, self.uri)
@@ -277,18 +280,28 @@
descr = rset.description
if rset:
needtranslation = []
+ rows = rset.rows
for i, etype in enumerate(descr[0]):
if (etype is None or not self.schema.eschema(etype).is_final() or
getattr(union.locate_subquery(i, etype, args).selection[i], 'uidtype', None)):
needtranslation.append(i)
if needtranslation:
- for rowindex, row in enumerate(rset):
+ cnx = session.pool.connection(self.uri)
+ for rowindex in xrange(rset.rowcount - 1, -1, -1):
+ row = rows[rowindex]
for colindex in needtranslation:
if row[colindex] is not None: # optional variable
etype = descr[rowindex][colindex]
- eid = self.extid2eid(row[colindex], etype, session)
- row[colindex] = eid
- results = rset.rows
+ exttype, exturi, extid = cnx.describe(row[colindex])
+ if exturi == 'system' or not exturi in self.repo.sources_by_uri:
+ eid = self.extid2eid(row[colindex], etype, session)
+ row[colindex] = eid
+ else:
+ # skip this row
+ del rows[rowindex]
+ del descr[rowindex]
+ break
+ results = rows
else:
results = []
if server.DEBUG:
--- a/server/sources/rql2sql.py Thu Jan 15 10:13:25 2009 +0100
+++ b/server/sources/rql2sql.py Wed Jun 03 19:42:23 2009 +0200
@@ -488,7 +488,8 @@
sql.insert(1, 'FROM (SELECT 1) AS _T')
sqls.append('\n'.join(sql))
if select.need_intersect:
- if distinct:
+ # XXX use getattr for lgc bw compat, remove once 0.37.3 is out
+ if distinct or not getattr(self.dbms_helper, 'intersect_all_support', True):
return '\nINTERSECT\n'.join(sqls)
else:
return '\nINTERSECT ALL\n'.join(sqls)
--- a/server/test/data/sources_multi Thu Jan 15 10:13:25 2009 +0100
+++ b/server/test/data/sources_multi Wed Jun 03 19:42:23 2009 +0200
@@ -15,6 +15,13 @@
cubicweb-password = gingkow
mapping-file = extern_mapping.py
+[extern-multi]
+adapter = pyrorql
+pyro-ns-id = extern-multi
+cubicweb-user = admin
+cubicweb-password = gingkow
+mapping-file = extern_mapping.py
+
[admin]
login = admin
password = gingkow
--- a/server/test/unittest_migractions.py Thu Jan 15 10:13:25 2009 +0100
+++ b/server/test/unittest_migractions.py Wed Jun 03 19:42:23 2009 +0200
@@ -134,7 +134,7 @@
self.assertEquals([str(rs) for rs in self.schema['Folder2'].object_relations()],
['filed_under2', 'identity'])
self.assertEquals(sorted(str(e) for e in self.schema['filed_under2'].subjects()),
- ['Affaire', 'Card', 'Division', 'ECache', 'Email', 'EmailThread', 'File',
+ ['Affaire', 'Card', 'Division', 'Email', 'EmailThread', 'File',
'Folder2', 'Image', 'Note', 'Personne', 'Societe', 'SubDivision'])
self.assertEquals(self.schema['filed_under2'].objects(), ('Folder2',))
eschema = self.schema.eschema('Folder2')
@@ -161,7 +161,7 @@
self.mh.cmd_add_relation_type('filed_under2')
self.failUnless('filed_under2' in self.schema)
self.assertEquals(sorted(str(e) for e in self.schema['filed_under2'].subjects()),
- ['Affaire', 'Card', 'Division', 'ECache', 'Email', 'EmailThread', 'File',
+ ['Affaire', 'Card', 'Division', 'Email', 'EmailThread', 'File',
'Folder2', 'Image', 'Note', 'Personne', 'Societe', 'SubDivision'])
self.assertEquals(self.schema['filed_under2'].objects(), ('Folder2',))
@@ -364,23 +364,36 @@
def test_add_remove_cube(self):
cubes = set(self.config.cubes())
schema = self.repo.schema
+ self.assertEquals(sorted(schema['see_also']._rproperties.keys()),
+ sorted([('EmailThread', 'EmailThread'), ('Folder', 'Folder'),
+ ('Bookmark', 'Bookmark'), ('Bookmark', 'Note'),
+ ('Note', 'Note'), ('Note', 'Bookmark')]))
try:
- self.mh.cmd_remove_cube('email')
- # file was there because it's an email dependancy, should have been removed
- cubes.remove('email')
- cubes.remove('file')
- self.assertEquals(set(self.config.cubes()), cubes)
- for ertype in ('Email', 'EmailThread', 'EmailPart', 'File', 'Image',
- 'sender', 'in_thread', 'reply_to', 'data_format'):
- self.failIf(ertype in schema, ertype)
- self.assertEquals(sorted(schema['see_also']._rproperties.keys()),
- [('Folder', 'Folder')])
- self.assertEquals(schema['see_also'].subjects(), ('Folder',))
- self.assertEquals(schema['see_also'].objects(), ('Folder',))
- self.assertEquals(self.execute('Any X WHERE X pkey "system.version.email"').rowcount, 0)
- self.assertEquals(self.execute('Any X WHERE X pkey "system.version.file"').rowcount, 0)
- self.failIf('email' in self.config.cubes())
- self.failIf('file' in self.config.cubes())
+ try:
+ self.mh.cmd_remove_cube('email')
+ # file was there because it's an email dependancy, should have been removed
+ cubes.remove('email')
+ cubes.remove('file')
+ self.assertEquals(set(self.config.cubes()), cubes)
+ for ertype in ('Email', 'EmailThread', 'EmailPart', 'File', 'Image',
+ 'sender', 'in_thread', 'reply_to', 'data_format'):
+ self.failIf(ertype in schema, ertype)
+ self.assertEquals(sorted(schema['see_also']._rproperties.keys()),
+ sorted([('Folder', 'Folder'),
+ ('Bookmark', 'Bookmark'),
+ ('Bookmark', 'Note'),
+ ('Note', 'Note'),
+ ('Note', 'Bookmark')]))
+ self.assertEquals(sorted(schema['see_also'].subjects()), ['Bookmark', 'Folder', 'Note'])
+ self.assertEquals(sorted(schema['see_also'].objects()), ['Bookmark', 'Folder', 'Note'])
+ self.assertEquals(self.execute('Any X WHERE X pkey "system.version.email"').rowcount, 0)
+ self.assertEquals(self.execute('Any X WHERE X pkey "system.version.file"').rowcount, 0)
+ self.failIf('email' in self.config.cubes())
+ self.failIf('file' in self.config.cubes())
+ except :
+ import traceback
+ traceback.print_exc()
+ raise
finally:
self.mh.cmd_add_cube('email')
cubes.add('email')
@@ -390,9 +403,13 @@
'sender', 'in_thread', 'reply_to', 'data_format'):
self.failUnless(ertype in schema, ertype)
self.assertEquals(sorted(schema['see_also']._rproperties.keys()),
- [('EmailThread', 'EmailThread'), ('Folder', 'Folder')])
- self.assertEquals(sorted(schema['see_also'].subjects()), ['EmailThread', 'Folder'])
- self.assertEquals(sorted(schema['see_also'].objects()), ['EmailThread', 'Folder'])
+ sorted([('EmailThread', 'EmailThread'), ('Folder', 'Folder'),
+ ('Bookmark', 'Bookmark'),
+ ('Bookmark', 'Note'),
+ ('Note', 'Note'),
+ ('Note', 'Bookmark')]))
+ self.assertEquals(sorted(schema['see_also'].subjects()), ['Bookmark', 'EmailThread', 'Folder', 'Note'])
+ self.assertEquals(sorted(schema['see_also'].objects()), ['Bookmark', 'EmailThread', 'Folder', 'Note'])
from cubes.email.__pkginfo__ import version as email_version
from cubes.file.__pkginfo__ import version as file_version
self.assertEquals(self.execute('Any V WHERE X value V, X pkey "system.version.email"')[0][0],
--- a/server/test/unittest_multisources.py Thu Jan 15 10:13:25 2009 +0100
+++ b/server/test/unittest_multisources.py Wed Jun 03 19:42:23 2009 +0200
@@ -10,10 +10,13 @@
sourcefile = 'sources_multi'
-class ExternalSourceConfiguration(TestServerConfiguration):
+class ExternalSource1Configuration(TestServerConfiguration):
sourcefile = 'sources_extern'
+
+class ExternalSource2Configuration(TestServerConfiguration):
+ sourcefile = 'sources_multi2'
-repo2, cnx2 = init_test_database('sqlite', config=ExternalSourceConfiguration('data'))
+repo2, cnx2 = init_test_database('sqlite', config=ExternalSource1Configuration('data'))
cu = cnx2.cursor()
ec1 = cu.execute('INSERT Card X: X title "C3: An external card", X wikiid "aaa"')[0][0]
cu.execute('INSERT Card X: X title "C4: Ze external card", X wikiid "zzz"')
@@ -22,9 +25,11 @@
MTIME = now() - 0.1
+repo3, cnx3 = init_test_database('sqlite', config=ExternalSource2Configuration('data'))
+
# XXX, access existing connection, no pyro connection
from cubicweb.server.sources.pyrorql import PyroRQLSource
-PyroRQLSource.get_connection = lambda x: cnx2
+PyroRQLSource.get_connection = lambda x: x.uri == 'extern-multi' and cnx3 or cnx2
# necessary since the repository is closing its initial connections pool though
# we want to keep cnx2 valid
from cubicweb.dbapi import Connection
@@ -84,12 +89,12 @@
self.assertEquals(rset.rows, rsetbase.rows[2:4])
def test_has_text(self):
- self.repo.sources[-1].synchronize(MTIME) # in case fti_update has been run before
+ self.repo.sources_by_uri['extern'].synchronize(MTIME) # in case fti_update has been run before
self.failUnless(self.execute('Any X WHERE X has_text "affref"'))
self.failUnless(self.execute('Affaire X WHERE X has_text "affref"'))
def test_anon_has_text(self):
- self.repo.sources[-1].synchronize(MTIME) # in case fti_update has been run before
+ self.repo.sources_by_uri['extern'].synchronize(MTIME) # in case fti_update has been run before
self.execute('INSERT Affaire X: X ref "no readable card"')[0][0]
aff1 = self.execute('INSERT Affaire X: X ref "card"')[0][0]
# grant read access
@@ -98,7 +103,7 @@
cnx = self.login('anon')
cu = cnx.cursor()
rset = cu.execute('Any X WHERE X has_text "card"')
- self.assertEquals(len(rset), 5)
+ self.assertEquals(len(rset), 5, zip(rset.rows, rset.description))
def test_synchronization(self):
cu = cnx2.cursor()
@@ -107,13 +112,14 @@
cnx2.commit()
try:
# force sync
- self.repo.sources[-1].synchronize(MTIME)
+ self.repo.sources_by_uri['extern'].synchronize(MTIME)
self.failUnless(self.execute('Any X WHERE X has_text "blah"'))
self.failUnless(self.execute('Any X WHERE X has_text "affreux"'))
cu.execute('DELETE Affaire X WHERE X eid %(x)s', {'x': aff2})
cnx2.commit()
- self.repo.sources[-1].synchronize(MTIME)
- self.failIf(self.execute('Any X WHERE X has_text "affreux"'))
+ self.repo.sources_by_uri['extern'].synchronize(MTIME)
+ rset = self.execute('Any X WHERE X has_text "affreux"')
+ self.failIf(rset)
finally:
# restore state
cu.execute('SET X ref "AFFREF" WHERE X eid %(x)s', {'x': aff1}, 'x')
@@ -139,7 +145,8 @@
self.execute('Any X ORDERBY DUMB_SORT(RF) WHERE X title RF')
def test_in_eid(self):
- iec1 = self.repo.extid2eid(self.repo.sources[-1], ec1, 'Card', self.session)
+ iec1 = self.repo.extid2eid(self.repo.sources_by_uri['extern'], ec1,
+ 'Card', self.session)
rset = self.execute('Any X WHERE X eid IN (%s, %s)' % (iec1, self.ic1))
self.assertEquals(sorted(r[0] for r in rset.rows), sorted([iec1, self.ic1]))
--- a/server/test/unittest_querier.py Thu Jan 15 10:13:25 2009 +0100
+++ b/server/test/unittest_querier.py Wed Jun 03 19:42:23 2009 +0200
@@ -454,7 +454,7 @@
'WHERE RT name N, RDEF relation_type RT '
'HAVING COUNT(RDEF) > 10')
self.assertListEquals(rset.rows,
- [[u'description', 11], ['in_basket', 12],
+ [[u'description', 11], ['in_basket', 11],
[u'name', 13], [u'created_by', 33],
[u'creation_date', 33], [u'is', 33], [u'is_instance_of', 33],
[u'modification_date', 33], [u'owned_by', 33]])
--- a/server/test/unittest_rql2sql.py Thu Jan 15 10:13:25 2009 +0100
+++ b/server/test/unittest_rql2sql.py Wed Jun 03 19:42:23 2009 +0200
@@ -156,11 +156,6 @@
]
ADVANCED= [
- ('Any X WHERE X is ET, ET eid 2',
- '''SELECT rel_is0.eid_from
-FROM is_relation AS rel_is0
-WHERE rel_is0.eid_to=2'''),
-
("Societe S WHERE S nom 'Logilab' OR S nom 'Caesium'",
'''SELECT S.eid
@@ -810,7 +805,7 @@
'F name "read", F require_group E, U in_group E)), U eid 1',
'''SELECT A.eid, rel_documented_by0.eid_to
FROM Affaire AS A LEFT OUTER JOIN documented_by_relation AS rel_documented_by0 ON (rel_documented_by0.eid_from=A.eid)
-WHERE ((rel_documented_by0.eid_to IS NULL) OR (EXISTS(SELECT 1 FROM require_permission_relation AS rel_require_permission1, EPermission AS F, require_group_relation AS rel_require_group2, in_group_relation AS rel_in_group3 WHERE rel_documented_by0.eid_to=rel_require_permission1.eid_from AND rel_require_permission1.eid_to=F.eid AND F.name=read AND rel_require_group2.eid_from=F.eid AND rel_in_group3.eid_from=1 AND rel_in_group3.eid_to=rel_require_group2.eid_to)))'''),
+WHERE ((rel_documented_by0.eid_to IS NULL) OR (EXISTS(SELECT 1 FROM require_permission_relation AS rel_require_permission1, EPermission AS F, require_group_relation AS rel_require_group2, in_group_relation AS rel_in_group3 WHERE rel_documented_by0.eid_to=rel_require_permission1.eid_from AND rel_require_permission1.eid_to=F.eid AND F.name=read AND rel_require_group2.eid_from=F.eid AND rel_in_group3.eid_to=rel_require_group2.eid_to AND rel_in_group3.eid_from=1)))'''),
("Any X WHERE X eid 12, P? connait X",
'''SELECT X.eid
@@ -1064,7 +1059,57 @@
]
+INTERSECT = [
+ ('Any SN WHERE NOT X in_state S, S name SN',
+ '''SELECT DISTINCT S.name
+FROM Affaire AS X, State AS S
+WHERE (X.in_state IS NULL OR X.in_state!=S.eid)
+INTERSECT
+SELECT DISTINCT S.name
+FROM EUser AS X, State AS S
+WHERE (X.in_state IS NULL OR X.in_state!=S.eid)
+INTERSECT
+SELECT DISTINCT S.name
+FROM Note AS X, State AS S
+WHERE (X.in_state IS NULL OR X.in_state!=S.eid)'''),
+ ('Any PN WHERE NOT X travaille S, X nom PN, S is IN(Division, Societe)',
+ '''SELECT X.nom
+FROM Personne AS X
+WHERE NOT EXISTS(SELECT 1 FROM travaille_relation AS rel_travaille0,Division AS S WHERE rel_travaille0.eid_from=X.eid AND rel_travaille0.eid_to=S.eid)
+INTERSECT ALL
+SELECT X.nom
+FROM Personne AS X
+WHERE NOT EXISTS(SELECT 1 FROM travaille_relation AS rel_travaille0,Societe AS S WHERE rel_travaille0.eid_from=X.eid AND rel_travaille0.eid_to=S.eid)'''),
+
+ ('Any PN WHERE NOT X travaille S, S nom PN, S is IN(Division, Societe)',
+ '''SELECT S.nom
+FROM Division AS S
+WHERE NOT EXISTS(SELECT 1 FROM travaille_relation AS rel_travaille0 WHERE rel_travaille0.eid_to=S.eid)
+UNION ALL
+SELECT S.nom
+FROM Societe AS S
+WHERE NOT EXISTS(SELECT 1 FROM travaille_relation AS rel_travaille0 WHERE rel_travaille0.eid_to=S.eid)'''),
+
+ ('Personne X WHERE NOT X travaille S, S nom "chouette"',
+ '''SELECT X.eid
+FROM Division AS S, Personne AS X
+WHERE NOT EXISTS(SELECT 1 FROM travaille_relation AS rel_travaille0 WHERE rel_travaille0.eid_from=X.eid AND rel_travaille0.eid_to=S.eid) AND S.nom=chouette
+UNION ALL
+SELECT X.eid
+FROM Personne AS X, Societe AS S
+WHERE NOT EXISTS(SELECT 1 FROM travaille_relation AS rel_travaille0 WHERE rel_travaille0.eid_from=X.eid AND rel_travaille0.eid_to=S.eid) AND S.nom=chouette
+UNION ALL
+SELECT X.eid
+FROM Personne AS X, SubDivision AS S
+WHERE NOT EXISTS(SELECT 1 FROM travaille_relation AS rel_travaille0 WHERE rel_travaille0.eid_from=X.eid AND rel_travaille0.eid_to=S.eid) AND S.nom=chouette'''),
+
+ ('Any X WHERE X is ET, ET eid 2',
+ '''SELECT rel_is0.eid_from
+FROM is_relation AS rel_is0
+WHERE rel_is0.eid_to=2'''),
+
+ ]
from logilab.common.adbh import ADV_FUNC_HELPER_DIRECTORY
class PostgresSQLGeneratorTC(RQLGeneratorTC):
@@ -1196,6 +1241,10 @@
def test_negation(self):
for t in self._parse(NEGATIONS):
yield t
+
+ def test_intersection(self):
+ for t in self._parse(INTERSECT):
+ yield t
def test_union(self):
for t in self._parse((
@@ -1370,7 +1419,7 @@
self.o = SQLGenerator(schema, dbms_helper)
def _norm_sql(self, sql):
- return sql.strip().replace(' ILIKE ', ' LIKE ')
+ return sql.strip().replace(' ILIKE ', ' LIKE ').replace('\nINTERSECT ALL\n', '\nINTERSECT\n')
def test_union(self):
for t in self._parse((
--- a/skeleton/__pkginfo__.py.tmpl Thu Jan 15 10:13:25 2009 +0100
+++ b/skeleton/__pkginfo__.py.tmpl Wed Jun 03 19:42:23 2009 +0200
@@ -1,6 +1,7 @@
# pylint: disable-msg=W0622
"""%(distname)s application packaging information"""
+modname = '%(cubename)s'
distname = '%(distname)s'
numversion = (0, 1, 0)
@@ -10,8 +11,8 @@
copyright = '''Copyright (c) %(year)s %(author)s.
%(author-web-site)s -- mailto:%(author-email)s'''
-author = %(author)s'
-author_email = %(author-email)s'
+author = '%(author)s'
+author_email = '%(author-email)s'
short_desc = '%(shortdesc)s'
long_desc = '''%(longdesc)s'''
--- a/test/unittest_cwconfig.py Thu Jan 15 10:13:25 2009 +0100
+++ b/test/unittest_cwconfig.py Wed Jun 03 19:42:23 2009 +0200
@@ -8,7 +8,7 @@
def unabsolutize(path):
parts = path.split(os.sep)
- for i, part in enumerate(parts):
+ for i, part in reversed(tuple(enumerate(parts))):
if part in ('cubicweb', 'cubes', 'cubes'):
return '/'.join(parts[i+1:])
raise Exception('duh? %s' % path)
--- a/test/unittest_rset.py Thu Jan 15 10:13:25 2009 +0100
+++ b/test/unittest_rset.py Wed Jun 03 19:42:23 2009 +0200
@@ -300,7 +300,13 @@
attr = etype == 'Bookmark' and 'title' or 'name'
self.assertEquals(entity[attr], n)
-
+ def test_related_entity_optional(self):
+ e = self.add_entity('Bookmark', title=u'aaaa', path=u'path')
+ rset = self.execute('Any B,U,L WHERE B bookmarked_by U?, U login L')
+ entity, rtype = rset.related_entity(0, 2)
+ self.assertEquals(entity, None)
+ self.assertEquals(rtype, None)
+
def test_related_entity_union_subquery(self):
e = self.add_entity('Bookmark', title=u'aaaa', path=u'path')
rset = self.execute('Any X,N ORDERBY N WITH X,N BEING '
--- a/toolsutils.py Thu Jan 15 10:13:25 2009 +0100
+++ b/toolsutils.py Wed Jun 03 19:42:23 2009 +0200
@@ -273,7 +273,7 @@
}),
("host",
{'short': 'H', 'type' : 'string', 'metavar': '<hostname>',
- 'default': 'all-in-one',
+ 'default': None,
'help': 'specify the name server\'s host name. Will be detected by \
broadcast if not provided.',
}),
--- a/vregistry.py Thu Jan 15 10:13:25 2009 +0100
+++ b/vregistry.py Wed Jun 03 19:42:23 2009 +0200
@@ -20,7 +20,7 @@
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -105,7 +105,10 @@
"can't be used together")
if '__select__' not in classdict and '__selectors__' in classdict:
selectors = classdict['__selectors__']
- classdict['__select__'] = classmethod(chainall(*selectors))
+ if len(selectors) > 1:
+ classdict['__select__'] = classmethod(chainall(*selectors))
+ else:
+ classdict['__select__'] = classmethod(selectors[0])
return super(autoselectors, mcs).__new__(mcs, name, bases, classdict)
def __setattr__(self, attr, value):
--- a/web/application.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/application.py Wed Jun 03 19:42:23 2009 +0200
@@ -1,7 +1,7 @@
"""CubicWeb web client application object
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -317,6 +317,7 @@
try:
ctrlid, rset = self.url_resolver.process(req, path)
controller = self.select_controller(ctrlid, req)
+ req.update_search_state()
result = controller.publish(rset=rset)
if req.cnx is not None:
# req.cnx is None if anonymous aren't allowed and we are
--- a/web/box.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/box.py Wed Jun 03 19:42:23 2009 +0200
@@ -14,9 +14,9 @@
accepts_registerer, extresources_registerer,
etype_rtype_priority_registerer)
from cubicweb.common.selectors import (
- etype_rtype_selector, one_line_rset, accept_selector, accept_rtype_selector,
- primaryview_selector, contextprop_selector, has_related_entities,
- _rqlcondition_selector)
+ etype_rtype_selector, one_line_rset, accept, has_relation,
+ primary_view, match_context_prop, has_related_entities,
+ _rql_condition)
from cubicweb.common.view import Template
from cubicweb.common.appobject import ReloadableMixIn
@@ -42,7 +42,7 @@
box.render(self.w)
"""
__registry__ = 'boxes'
- __selectors__ = Template.__selectors__ + (contextprop_selector,)
+ __selectors__ = Template.__selectors__ + (match_context_prop,)
categories_in_order = ()
property_defs = {
@@ -150,17 +150,15 @@
class EntityBoxTemplate(BoxTemplate):
"""base class for boxes related to a single entity"""
__registerer__ = accepts_registerer
- __selectors__ = (one_line_rset, primaryview_selector,
- contextprop_selector, etype_rtype_selector,
- accept_rtype_selector, accept_selector,
- _rqlcondition_selector)
+ __selectors__ = (one_line_rset, primary_view,
+ match_context_prop, etype_rtype_selector,
+ has_relation, accept, _rql_condition)
accepts = ('Any',)
context = 'incontext'
condition = None
def call(self, row=0, col=0, **kwargs):
- """classes inheriting from EntityBoxTemplate should defined cell_call,
- """
+ """classes inheriting from EntityBoxTemplate should define cell_call"""
self.cell_call(row, col, **kwargs)
@@ -185,7 +183,7 @@
class attributes.
"""
- def cell_call(self, row, col):
+ def cell_call(self, row, col, view=None):
self.req.add_js('cubicweb.ajax.js')
entity = self.entity(row, col)
box = SideBoxWidget(display_name(self.req, self.rtype), self.id)
--- a/web/component.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/component.py Wed Jun 03 19:42:23 2009 +0200
@@ -56,7 +56,10 @@
condition = None
def call(self, view):
- raise RuntimeError()
+ return self.cell_call(0, 0, view)
+
+ def cell_call(self, row, col, view):
+ raise NotImplementedError()
class NavigationComponent(VComponent):
@@ -70,6 +73,19 @@
selected_page_link_templ = u'<span class="selectedSlice"><a href="%s" title="%s">%s</a></span>'
previous_page_link_templ = next_page_link_templ = page_link_templ
no_previous_page_link = no_next_page_link = u''
+
+ @classmethod
+ def selected(cls, req, rset, row=None, col=None, page_size=None, **kwargs):
+ """by default web app objects are usually instantiated on
+ selection according to a request, a result set, and optional
+ row and col
+ """
+ instance = super(NavigationComponent, cls).selected(req, rset, row, col, **kwargs)
+ if page_size is not None:
+ instance.page_size = page_size
+ elif 'page_size' in req.form:
+ instance.page_size = int(req.form['page_size'])
+ return instance
def __init__(self, req, rset):
super(NavigationComponent, self).__init__(req, rset)
@@ -145,17 +161,17 @@
"""
return None
- def call(self, view=None):
+ def cell_call(self, row, col, view=None):
rql = self.rql()
if rql is None:
- entity = self.rset.get_entity(0, 0)
+ entity = self.rset.get_entity(row, col)
if self.target == 'object':
role = 'subject'
else:
role = 'object'
rset = entity.related(self.rtype, role)
else:
- eid = self.rset[0][0]
+ eid = self.rset[row][col]
rset = self.req.execute(self.rql(), {'x': eid}, 'x')
if not rset.rowcount:
return
--- a/web/controller.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/controller.py Wed Jun 03 19:42:23 2009 +0200
@@ -11,7 +11,7 @@
from cubicweb import typed_eid
from cubicweb.common.registerers import priority_registerer
-from cubicweb.common.selectors import in_group_selector
+from cubicweb.common.selectors import match_user_group
from cubicweb.common.appobject import AppObject
from cubicweb.web import LOGGER, Redirect, RequestError
@@ -68,7 +68,7 @@
"""
__registry__ = 'controllers'
__registerer__ = priority_registerer
- __selectors__ = (in_group_selector,)
+ __selectors__ = (match_user_group,)
require_groups = ()
def __init__(self, *args, **kwargs):
--- a/web/data/cubicweb.ajax.js Thu Jan 15 10:13:25 2009 +0100
+++ b/web/data/cubicweb.ajax.js Wed Jun 03 19:42:23 2009 +0200
@@ -9,6 +9,23 @@
var JSON_BASE_URL = baseuri() + 'json?';
+function postAjaxLoad(node) {
+ // find sortable tables if there are some
+ if (typeof(Sortable) != 'undefined') {
+ Sortable.sortTables(node);
+ }
+ // find textareas and wrap them if there are some
+ if (typeof(FCKeditor) != 'undefined') {
+ buildWysiwygEditors(node);
+ }
+ if (typeof initFacetBoxEvents != 'undefined') {
+ initFacetBoxEvents(node);
+ }
+ if (typeof buildWidgets != 'undefined') {
+ buildWidgets(node);
+ }
+}
+
// cubicweb loadxhtml plugin to make jquery handle xhtml response
jQuery.fn.loadxhtml = function(url, data, reqtype, mode) {
var ajax = null;
@@ -40,28 +57,12 @@
} else if (mode == 'append') {
jQuery(node).append(domnode);
}
- // find sortable tables if there are some
- if (typeof(Sortable) != 'undefined') {
- Sortable.sortTables(node);
- }
- // find textareas and wrap them if there are some
- if (typeof(FCKeditor) != 'undefined') {
- buildWysiwygEditors(node);
- }
-
- if (typeof initFacetBoxEvents != 'undefined') {
- initFacetBoxEvents(node);
- }
-
- if (typeof buildWidgets != 'undefined') {
- buildWidgets(node);
- }
-
+ postAjaxLoad(node);
while (jQuery.isFunction(callback)) {
callback = callback.apply(this, [domnode]);
}
});
-}
+};
@@ -69,7 +70,7 @@
* the associated RQL to build them (Async call)
*/
function loadDynamicFragments() {
- var fragments = getElementsByTagAndClassName('div', 'dynamicFragment');
+ var fragments = jQuery('div.dynamicFragment');
if (fragments.length == 0) {
return;
}
@@ -277,7 +278,7 @@
* while the page was generated.
*/
function unregisterUserCallback(cbname) {
- d = async_remote_exec('unregister_user_callback', cbname);
+ var d = async_remote_exec('unregister_user_callback', cbname);
d.addCallback(function() {resetCursor();});
d.addErrback(function(xxx) {
updateMessage(_("an error occured"));
--- a/web/data/cubicweb.calendar.css Thu Jan 15 10:13:25 2009 +0100
+++ b/web/data/cubicweb.calendar.css Wed Jun 03 19:42:23 2009 +0200
@@ -74,7 +74,7 @@
}
table.omcalendar tr td div.calCellTitle div.stopper {
- clear:pos;
+ /* clear:pos; # FIXME : pos is not a clear value*/
}
table.omcalendar tr td {
--- a/web/data/cubicweb.calendar_popup.css Thu Jan 15 10:13:25 2009 +0100
+++ b/web/data/cubicweb.calendar_popup.css Wed Jun 03 19:42:23 2009 +0200
@@ -45,7 +45,7 @@
table.popupCalendar th.prev,
table.popupCalendar th.next {
- color: orangered;
+ color: #ff4500;
font-size: 50%;
font-weight: bold;
padding: 2px 0px;
--- a/web/data/cubicweb.css Thu Jan 15 10:13:25 2009 +0100
+++ b/web/data/cubicweb.css Wed Jun 03 19:42:23 2009 +0200
@@ -3,10 +3,9 @@
* :copyright: 2003-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
* :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
*/
-
-/******************************************************************************/
-/* main styles */
-/******************************************************************************/
+/***************************************/
+/* xhtml tags styles */
+/***************************************/
*{
margin:0px;
@@ -23,14 +22,12 @@
font-family: Verdana, sans-serif;
}
-
h1 {
font-size: 188%;
margin: 0.2em 0px 0.3em;
border-bottom: 1px solid #000;
}
-
h2, h3 {
margin-top: 0.2em;
margin-bottom: 0.3em;
@@ -57,7 +54,7 @@
font-size:105%;
}
-a, a:active, a:link, a:visited {
+a, a:active, a:visited, a:link {
color: #ff4500;
text-decoration: none;
}
@@ -66,33 +63,17 @@
text-decoration: underline;
}
-a.grayedout {
- display: block;
- padding-left: 2px;
- color: #808080;
-}
-
-a.grayedout:visited{
- color: #808080;
-}
-
-a.grayedout:hover {
- color: #000;
-}
-
a img {
border: none;
text-align: center;
}
p {
- margin-top: 0em;
- margin-bottom: 0.2em;
+ margin: 0em 0px 0.2em;
padding-top: 2px;
}
-
-table, td, input, select {
+table, td, input, select{
font-size: 100%;
}
@@ -107,7 +88,7 @@
table td img {
vertical-align: middle;
- margin: 0px 10px 0px 0px;
+ margin-right: 10px;
}
ol {
@@ -125,29 +106,22 @@
background: url("bullet_orange.png") 0% 6px no-repeat;
}
-pre {
- font-family: Courier, "Courier New", Monaco, monospace;
- font-size: 100%;
- color: #000;
- background-color: #f2f2f2;
- border: 1px solid #ccc;
- /*overflow:auto; */
+dt {
+ font-size:1.17em;
+ font-weight:600;
}
-blockquote {
- font-family: Courier, "Courier New", serif;
- font-size: 120%;
- margin: 5px 0px;
- padding: 0.8em;
- background-color: #f2f2f2;
- border: 1px solid #ccc;
+dd {
+ margin: 0.6em 0 1.5em 2em;
}
-note, code {
- font-size: 120%;
- color: #000;
- background-color: #f2f2f2;
- border: 1px solid #ccc;
+fieldset {
+ border: none;
+}
+
+legend {
+ padding: 0px 2px;
+ font: bold 1em Verdana, sans-serif;
}
input, textarea {
@@ -160,35 +134,41 @@
border: 1px inset #ff7700;
}
-fieldset {
- border: none;
-}
-
-legend {
- padding: 0px 2px;
- font: bold 1em Verdana, sans-serif;
-}
-
label, .label {
- font-weight: bold ! important;
+ font-weight: bold;
}
iframe {
border: 0px;
}
-dt {
- font-size: 1.17em;
- font-weight: 600;
+pre {
+ font-family: Courier, "Courier New", Monaco, monospace;
+ font-size: 100%;
+ color: #000;
+ background-color: #f2f2f2;
+ border: 1px solid #ccc;
}
-dd {
- margin: 0.6em 0 1.5em 2em;
+code {
+ font-size: 120%;
+ color: #000;
+ background-color: #f2f2f2;
+ border: 1px solid #ccc;
}
-/******************************************************************************/
-/* generic classes */
-/******************************************************************************/
+blockquote {
+ font-family: Courier, "Courier New", serif;
+ font-size: 120%;
+ margin: 5px 0px;
+ padding: 0.8em;
+ background-color: #f2f2f2;
+ border: 1px solid #ccc;
+}
+
+/***************************************/
+/* generic classes */
+/***************************************/
.odd {
background-color: #f7f6f1;
@@ -215,77 +195,70 @@
clear: both;
}
-.noborder {
- border: none;
-}
-
-.strong{
- font-weight:bold;
-}
-
-.title {
- text-align: left;
- font-size: large;
- font-weight: bold;
-}
-
-.titleUnderline {
- color: #000;
- clear: left;
- margin: 0px;
- padding-top: 0.5em;
- border-bottom: 1px solid black;
-}
-
-.helper{
- font-size: 96%;
- color: #555544;
-}
-
-.helper:hover {
- color: #000;
- cursor: default;
-}
-
.hidden {
display: none;
visibility: hidden;
}
-.needsvalidation {
- font-style: italic;
- color: grey ! important;
-}
-.folder {
- /* disable odd/even under folder class */
- background-color: transparent;
-}
+/* FIXME need to be moved to cubicweb.forms.css */
+li.invisible { list-style: none; background: none; padding: 0px 0px
+1px 1px; }
-li.invisible {
- list-style: none;
- background: none;
- padding: 0px 0px 1px 1px;
-}
-
+/* FIXME Should use span in html insteed */
li.invisible div {
display: inline;
}
-div.row {
- clear: both;
- padding-bottom:0.4px
+
+/***************************************/
+/* LAYOUT */
+/***************************************/
+
+/* header */
+
+table#header {
+ background: #ff7700 url("banner.png") left top repeat-x;
+ text-align: left;
+}
+
+table#header td {
+ vertical-align: middle;
+}
+
+table#header a {
+color: #000;
}
-div.row span.label{
- padding-right:1em
+span#appliName {
+ font-weight: bold;
+ color: #000;
+ white-space: nowrap;
+}
+
+table#header td#headtext {
+ width: 100%;
}
-div.field {
- margin-left: 0.2em;
- display: inline;
+a.help{
+ display: block;
+ margin: 0px 5px 0px 8px;
+ height: 17px;
+ width: 17px;
+ background: url('help.png') 0% 0% no-repeat;
}
+a.help:hover {
+ background-position: 0px -16px;
+ text-decoration: none;
+}
+
+/* FIXME appear with 4px width in IE6 */
+div#stateheader{
+ min-width: 66%;
+}
+
+/* Popup on login box and userActionBox */
div.popup {
position: absolute;
z-index: 400;
@@ -300,42 +273,7 @@
color: black;
}
-/******************************************************************************/
-/* header / layout */
-/******************************************************************************/
-
-.logo {
- background: #fff;
- border-left: #f2f2f2;
-}
-
-span#appliName {
- font-weight: bold;
- color: #000;
- white-space: nowrap;
-}
-
-#header {
- background: #ff7700 url("banner.png") left top repeat-x;
- text-align: left;
-}
-
-table#header td {
- vertical-align: middle;
-}
-
-table#header a {
-color: #000;
-}
-
-td#headtext {
- width: 100%;
-}
-
-/*FIXME appear with 4px width in IE6*/
-div#stateheader{
- width: 66%;
-}
+/* main zone */
div#page {
background: #e2e2e2;
@@ -343,16 +281,16 @@
min-height: 800px;
}
-td#contentcol {
- padding: 8px 5px 5px 10px;
+table#mainLayout{
+ margin:0px 3px;
}
+table#mainLayout td#contentcol {
+ padding: 8px 10px 5px;
+}
-div#pageContent {
- clear: both;
- padding: 10px 1em 2em;
- background: #ffffff;
- border: 1px solid #ccc;
+table#mainLayout td.navcol {
+ width: 16em;
}
#contentheader {
@@ -364,157 +302,29 @@
color: #000;
}
-td.firstcolumn {
- width: 220px;
-}
-
-td.navcol {
- width: 16em;
-}
-
-div.footer {
- text-align: center;
-}
-div.footer a {
- color: #000;
- text-decoration: none;
+div#pageContent {
+ clear: both;
+ padding: 10px 1em 2em;
+ background: #ffffff;
+ border: 1px solid #ccc;
}
-/******************************************************************************/
-/* help button */
-/******************************************************************************/
-
-a.help{
- display: block;
- margin: 0px 5px 0px 8px;
- height: 17px;
- width: 17px;
- background: url('help.png') 0% 0% no-repeat;
-}
+/* rql bar */
-a.help:hover {
- background-position: 0px -16px;
- text-decoration: none;
-}
-
-/******************************************************************************/
-/* rql bar */
-/******************************************************************************/
-
-div#rqlform {
- width: 100%;
+div#rqlinput {
+ border: 1px solid #cfceb7;
+ margin-bottom: 8px;
+ padding: 3px;
+ background: #cfceb7;
}
input#rql{
- width: 80%;
- margin-left: 12px;
-}
-
-/******************************************************************************/
-/* user actions menu */
-/******************************************************************************/
-
-a.logout, a.logout:visited, a.logout:hover{
- color: #fff;
- text-decoration: none;
-}
-
-div#userActionsBox {
- width: 14em;
- text-align: right;
-}
-
-div#userActionsBox a.popupMenu {
- color: black;
- text-decoration: underline;
-}
-
-/******************************************************************************/
-/* buttons */
-/******************************************************************************/
-
-input#rqlboxsubmit, input#rqlboxsubmit2 {
- background: #fffff8 url("go.png") 50% 50% no-repeat;
- width: 20px;
- height: 20px;
- margin: 0px;
-}
-
-input.button,
-input.formButton,
-input.validateButton,
-input.searchButton,
-input.loginButton {
- border-top: 1px solid #edecd2;
- border-left: 1px solid #edecd2;
- border-right: 1px solid #cfceb7;
- border-bottom: 1px solid #cfceb7;
- background: #fffff8 url("button.png") bottom left repeat-x;
-}
-
-input.searchButton {
- background: #f0eff0 url("gradient-grey-up.png") left top repeat-x;
-}
-
-input.button,
-input.validateButton {
- margin: 1em 1em 0px 0px ! important;
+ width: 95%;
}
-/******************************************************************************/
-/* primary view */
-/******************************************************************************/
-
-.mainInfo {
- margin-right: 1em;
- padding: 0.2em;
-}
-
-div.mainRelated {
- border: none;
- margin-right: 1em;
- padding: 0.5em 0.2em 0.2em;
-}
-
-div.sideRelated h4,
-div.sideRelated h5 {
- margin-top: 0px;
- margin-bottom: 0px;
-}
-
-div.sideRelated {
- margin-right: 1em;
- padding: 12px 0px 12px 12px;
- min-width: 21em;
- max-width: 50em;
-}
-
-div.metadata {
- font-size: 90%;
- margin: 5px 0px 3px;
- color: #666;
- font-style: italic;
- text-align: right;
-}
-
-div.section {
- margin-top: 0.5em;
- width:100%;
-}
-
-div.section a:hover {
- text-decoration: none;
-}
-
-
-
-/******************************************************************************/
-/* boxes */
-/******************************************************************************/
-
+/* boxes */
div.navboxes {
- padding-left: 3px;
- margin-top: 8px;
+ margin-top: 8px;
}
div.boxFrame {
@@ -594,12 +404,14 @@
color: #111100;
}
+
a.boxMenu {
background: transparent url("puce_down.png") 98% 6px no-repeat;
display: block;
padding: 1px 9px 1px 3px;
}
+
a.popupMenu {
background: transparent url("puce_down_black.png") 2% 6px no-repeat;
padding-left: 2em;
@@ -648,6 +460,12 @@
background: #eeedd9;
}
+ul.sideBox li{
+ list-style: none;
+ background: none;
+ padding: 0px 0px 1px 1px;
+ }
+
div.sideBoxBody {
padding: 0.2em 5px;
}
@@ -680,62 +498,45 @@
padding:0px 5px;
}
-/******************************************************************************/
-/* inline edition and generic form classes */
-/******************************************************************************/
+/* FIXME rqlboxsubmit2 still necessary ? */
-div.inlineedit {
- display: none;
+input.rqlsubmit,
+input#rqlboxsubmit2 {
+ background: #fffff8 url("go.png") 50% 50% no-repeat;
+ width: 20px;
+ height: 20px;
+ margin: 0px;
}
-div.editableField {
- display: inline;
-}
-
-div.editableField:hover,
-div.editableField p:hover {
- background-color: #eeedd9;
+input#norql{
+ width:13em;
+ margin-right: 2px;
}
-option.separator {
- font-weight: bold;
- background: #ccc;
- text-align: center;
-}
-
-input.error {
- background: transparent url("error.png") 100% 50% no-repeat;
+/* user actions menu */
+a.logout, a.logout:visited, a.logout:hover{
+ color: #fff;
+ text-decoration: none;
}
-span.error {
- display: block;
- font-weight: bold;
- color: #ed0d0d;
+div#userActionsBox {
+ width: 14em;
+ text-align: right;
}
-/******************************************************************************/
-/* navigation */
-/******************************************************************************/
+div#userActionsBox a.popupMenu {
+ color: black;
+ text-decoration: underline;
+}
+/**************/
+/* navigation */
+/**************/
div#etyperestriction {
margin-bottom: 1ex;
border-bottom: 1px solid #ccc;
}
-div.navigation a {
- text-align: center;
- text-decoration: none;
-}
-
-div.prevnext {
- width: 100%;
- margin-bottom: 1em;
-}
-
-div.prevnext a {
- color: #000;
-}
-
span.slice a:visited,
span.slice a:hover{
color: #555544;
@@ -746,15 +547,95 @@
color: #000;
}
-/******************************************************************************/
-/* messages */
-/******************************************************************************/
+/* FIXME should be moved to cubes/folder */
+div.navigation a {
+ text-align: center;
+ text-decoration: none;
+}
+
+/* FIXME seems to be not used in cubicweb framework */
+div.prevnext {
+ width: 100%;
+ margin-bottom: 1em;
+}
+
+div.prevnext a {
+ color: #000;
+}
+
+
+/***************************************/
+/* entity views */
+/***************************************/
+
+.mainInfo {
+ margin-right: 1em;
+ padding: 0.2em;
+}
+
+
+div.mainRelated {
+ border: none;
+ margin-right: 1em;
+ padding: 0.5em 0.2em 0.2em;
+}
+
+div.sideRelated h4,
+div.sideRelated h5 {
+ margin-top: 0px;
+ margin-bottom: 0px;
+}
+
+div.sideRelated {
+ margin-right: 1em;
+ float: right;
+ padding: 12px 0px 12px 12px;
+ min-width: 21em;
+ max-width: 50em;
+}
+
+div.metadata {
+ font-size: 90%;
+ margin: 5px 0px 3px;
+ color: #666;
+ font-style: italic;
+ text-align: right;
+}
+
+div.section {
+ margin-top: 0.5em;
+ width:100%;
+}
+
+div.section a:hover {
+ text-decoration: none;
+}
+
+/* basic entity view */
+
+div.row {
+ clear: both;
+ padding-bottom:0.4px
+}
+
+div.row span.label{
+ padding-right:1em
+}
+
+div.field {
+ margin-left: 0.2em;
+ display: inline;
+}
+
+
+/***************************************/
+/* messages */
+/***************************************/
.warning,
.message,
-.errorMessage,
-.searchMessage,
-.statemessage {
+.errorMessage ,
+.searchMessage{
padding: 0.3em 0.3em 0.3em 1em;
font-weight: bold;
}
@@ -772,13 +653,6 @@
background: #f8f8ee;
}
-div#rqlinput {
- border: 1px solid #cfceb7;
- margin-bottom: 8px;
- padding: 3px;
- background: #cfceb7;
-}
-
.message {
margin: 0px;
background: #f8f8ee url("information.png") 5px center no-repeat;
@@ -823,9 +697,9 @@
display: none;
}
-/******************************************************************************/
-/* listing table */
-/******************************************************************************/
+/***************************************/
+/* listing table */
+/***************************************/
table.listing {
margin: 10px 0em;
@@ -872,9 +746,10 @@
top: -1px;
}
-/******************************************************************************/
-/* drag and drop zone (XXX only used in seo for now) */
-/******************************************************************************/
+/***************************************/
+/* drag and drop zone */
+/* (XXX only used in seo for now) */
+/***************************************/
div.droppable {
border: 1px dashed black;
@@ -887,19 +762,11 @@
background: #f4f5ed;
}
-/******************************************************************************/
-/* search box */
-/******************************************************************************/
+/****************************************/
+/* filter box FIXME is not used anymore*/
+/****************************************/
-input#norql{
- width:13em;
- margin-right: 2px;
-}
-
-/******************************************************************************/
-/* filter box */
-/******************************************************************************/
-
+/*
#filter_box input {
width: 180px;
}
@@ -916,38 +783,11 @@
#filter_box option.disabled {
background: lightgray;
}
-
-/******************************************************************************/
-/* table filter form */
-/******************************************************************************/
-
-table.filter th {
- font-weight: bold;
- background: #ebe8d9 url("button.png") repeat-x;
- padding: 0.3em;
- border-bottom: 1px solid #cfceb7;
- text-align: left;
-}
+*/
-table.filter div.facet {
- padding: 0.6em 0.2em;
- margin: 0em 1em;
- border: 1px solid #ccc;
-}
-
-table.filter div.facetTitle {
- font-weight: bold;
-}
-
-
-div#tableActionsBox {
- direction:rtl;
- float:right
-}
-
-/******************************************************************************/
-/* error view (views/management.py) */
-/******************************************************************************/
+/***************************************/
+/* error view (views/management.py) */
+/***************************************/
div.pycontext { /* html traceback */
font-family: Verdana, sans-serif;
@@ -961,32 +801,10 @@
color: #ff0000;
}
-/******************************************************************************/
-/* index view (views/startup.py) */
-/******************************************************************************/
-table.startup {
- width: 100%;
-}
-
-table.startup td {
- padding: 0.1em 0.2em;
-}
-
-table.startup td.addcol {
- text-align: right;
- width: 0.5em;
-}
-
-table.startup th{
- padding-top: 3px;
- padding-bottom: 3px;
- text-align: left;
-}
-
-/******************************************************************************/
-/* addcombobox */
-/******************************************************************************/
+/***************************************/
+/* addcombobox */
+/***************************************/
input#newopt{
width:120px ;
@@ -1005,3 +823,51 @@
display:block;
float:left;
}
+
+/***************************************/
+/* buttons */
+/***************************************/
+
+input.button{
+ margin: 1em 1em 0px 0px;
+ border: 1px solid #edecd2;
+ border-color:#edecd2 #cfceb7 #cfceb7 #edecd2;
+ background: #fffff8 url("button.png") bottom left repeat-x;
+}
+
+/* FileItemInnerView jquery.treeview.css */
+.folder {
+ /* disable odd/even under folder class */
+ background-color: transparent;
+}
+
+/***************************************/
+/* footer */
+/***************************************/
+
+div.footer {
+ text-align: center;
+}
+div.footer a {
+ color: #000;
+ text-decoration: none;
+}
+
+
+/****************************************/
+/* FIXME must by managed by cubes */
+/****************************************/
+.needsvalidation {
+ font-style: italic;
+ color: gray;
+}
+
+
+/***************************************/
+/* FIXME : Deprecated ? entity view ? */
+/***************************************/
+.title {
+ text-align: left;
+ font-size: large;
+ font-weight: bold;
+}
--- a/web/data/cubicweb.facets.css Thu Jan 15 10:13:25 2009 +0100
+++ b/web/data/cubicweb.facets.css Wed Jun 03 19:42:23 2009 +0200
@@ -69,7 +69,7 @@
}
div#filter_box div.boxTitle {
- visibility: none;
+ visibility: hidden;
display: none;
}
--- a/web/data/cubicweb.form.css Thu Jan 15 10:13:25 2009 +0100
+++ b/web/data/cubicweb.form.css Wed Jun 03 19:42:23 2009 +0200
@@ -9,7 +9,7 @@
width: 100%;
font-size : 160%;
font-weight: bold;
- color: orangered;
+ color: #ff4500;
padding-bottom : 0.4em;
text-transform: capitalize;
background: url("bg_trame_grise.png") left bottom repeat-x;
@@ -178,6 +178,35 @@
margin-left: 2em;
}
+/*FIXME inlineedit not used ?*/
+div.inlineedit {
+ display: none;}
+
+div.editableField {
+ display: inline;
+}
+
+div.editableField:hover,
+div.editableField p:hover {
+ background-color: #eeedd9;
+}
+
+input.error {
+ background: transparent url("error.png") 100% 50% no-repeat;
+}
+
+span.error {
+ display: block;
+ font-weight: bold;
+ color: #ed0d0d;
+}
+
+option.separator {
+ font-weight: bold;
+ background: #ccc;
+ text-align: center;
+}
+
div.trame_grise {
background: url("bg_trame_grise.png") left top repeat-x;
}
@@ -189,3 +218,21 @@
padding-left: 2em;
background : #f8f8ee url("information.png") 5px center no-repeat ;
}
+
+.helper{
+ font-size: 96%;
+ color: #555544;
+}
+
+.helper:hover {
+ color: #000;
+ cursor: default;
+}
+
+input.validateButton {
+ margin: 1em 1em 0px 0px;
+ border: 1px solid #edecd2;
+ border-color:#edecd2 #cfceb7 #cfceb7 #edecd2;
+ background: #fffff8 url("button.png") bottom left repeat-x;
+}
+
--- a/web/data/cubicweb.formfilter.js Thu Jan 15 10:13:25 2009 +0100
+++ b/web/data/cubicweb.formfilter.js Wed Jun 03 19:42:23 2009 +0200
@@ -109,10 +109,9 @@
root = root || document;
jQuery(root).find('form').each(function () {
var form = jQuery(this);
- var facetargs = form.attr('cubicweb:facetargs');
- if (facetargs) {
+ var facetargs = evalJSON(form.attr('cubicweb:facetargs'));
+ if (facetargs !== undefined && facetargs.length) {
form.submit(function() {
- var facetargs = evalJSON(form.attr('cubicweb:facetargs'));
buildRQL.apply(null, facetargs); //(divid, vid, paginate, extraargs);
return false;
});
@@ -122,7 +121,6 @@
this.setAttribute('cubicweb:idx', i);
});
facet.find('div.facetCheckBox').click(function () {
- var facetargs = evalJSON(form.attr('cubicweb:facetargs'));
var $this = jQuery(this);
if ($this.hasClass('facetValueSelected')) {
$this.removeClass('facetValueSelected');
--- a/web/data/cubicweb.gmap.js Thu Jan 15 10:13:25 2009 +0100
+++ b/web/data/cubicweb.gmap.js Wed Jun 03 19:42:23 2009 +0200
@@ -26,7 +26,7 @@
var self = this; // bind this to a local variable
jQuery.getJSON(jsonurl, function(geodata) {
if (geodata.center) {
- var zoomLevel = 8; // FIXME arbitrary !
+ var zoomLevel = geodata.zoomlevel;
map.setCenter(new GLatLng(geodata.center.latitude, geodata.center.longitude),
zoomLevel);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/web/data/cubicweb.lazy.js Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,14 @@
+
+function load_now(eltsel, holesel, reloadable) {
+ var lazydiv = jQuery(eltsel);
+ var hole = lazydiv.children(holesel);
+ if ((hole.length == 0) && !reloadable) {
+ /* the hole is already filled */
+ return;
+ }
+ lazydiv.loadxhtml(lazydiv.attr('cubicweb:loadurl'));
+}
+
+function trigger_load(divid) {
+ jQuery('#lazy-' + divid).trigger('load_' + divid);
+}
--- a/web/data/cubicweb.login.css Thu Jan 15 10:13:25 2009 +0100
+++ b/web/data/cubicweb.login.css Wed Jun 03 19:42:23 2009 +0200
@@ -76,7 +76,8 @@
}
input.loginButton {
- display:block;
+ border: 1px solid #edecd2;
+ border-color:#edecd2 #cfceb7 #cfceb7 #edecd2;
margin: 2px 0px 0px;
background: #f0eff0 url("gradient-grey-up.png") left top repeat-x;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/web/data/cubicweb.manageview.css Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,22 @@
+/***************************************/
+/* Manage view (views/startup.py) */
+/***************************************/
+
+table.startup {
+ width: 100%;
+}
+
+table.startup td {
+ padding: 0.1em 0.2em;
+}
+
+table.startup td.addcol {
+ text-align: right;
+ width: 0.5em;
+}
+
+table.startup th{
+ padding-top: 3px;
+ padding-bottom: 3px;
+ text-align: left;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/web/data/cubicweb.preferences.js Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,10 @@
+/* toggle visibility of an element by its id
+ * & set current visibility status in a cookie
+ * XXX whenever used outside of preferences, don't forget to
+ * move me in a more appropriate place
+ */
+function toggle_and_remember_visibility(elemId, cookiename) {
+ jqNode(elemId).toggleClass('hidden');
+ async_remote_exec('set_cookie', cookiename,
+ jQuery('#' + elemId).attr('class'));
+}
--- a/web/data/cubicweb.schema.css Thu Jan 15 10:13:25 2009 +0100
+++ b/web/data/cubicweb.schema.css Wed Jun 03 19:42:23 2009 +0200
@@ -5,6 +5,16 @@
* :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
*/
+
+.titleUnderline {
+ color: #000;
+ clear: left;
+ margin: 0px;
+ padding-top: 0.5em;
+ border-bottom: 1px solid black;
+}
+
+
div.relationDefinition {
float: left;
position: relative;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/web/data/cubicweb.tableview.css Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,27 @@
+/***************************************/
+/* filter table form */
+/***************************************/
+
+table.filter th {
+ font-weight: bold;
+ background: #ebe8d9 url("button.png") repeat-x;
+ padding: 0.3em;
+ border-bottom: 1px solid #cfceb7;
+ text-align: left;
+}
+
+table.filter div.facet {
+ padding: 0.6em 0.2em;
+ margin: 0em 1em;
+ border: 1px solid #ccc;
+}
+
+table.filter div.facetTitle {
+ font-weight: bold;
+}
+
+
+div#tableActionsBox {
+ direction:rtl;
+ float:right
+}
--- a/web/data/cubicweb.tabs.js Thu Jan 15 10:13:25 2009 +0100
+++ b/web/data/cubicweb.tabs.js Wed Jun 03 19:42:23 2009 +0200
@@ -1,5 +1,6 @@
-function set_tab(tabname) {
- // set appropriate cookie
- // XXX see if we can no just do it with jQuery
- async_remote_exec('remember_active_tab', tabname);
+function set_tab(tabname, cookiename) {
+ // set appropriate cookie
+ async_remote_exec('set_cookie', cookiename, tabname);
+ // trigger show + tabname event
+ trigger_load(tabname);
}
--- a/web/data/cubicweb.timetable.css Thu Jan 15 10:13:25 2009 +0100
+++ b/web/data/cubicweb.timetable.css Wed Jun 03 19:42:23 2009 +0200
@@ -12,7 +12,7 @@
table.timetable th {
padding:1pt;
- align:center;
+ text-align:center;
}
@@ -52,7 +52,7 @@
font-family: Verdana, sans-serif;
padding-left: 4pt;
padding-right: 4pt;
- align: left;
+ text-align: left;
width: auto;
}
--- a/web/data/cubicweb.widgets.js Thu Jan 15 10:13:25 2009 +0100
+++ b/web/data/cubicweb.widgets.js Wed Jun 03 19:42:23 2009 +0200
@@ -181,14 +181,6 @@
}
}
-Widgets.TreeView = defclass("TreeView", null, {
- __init__: function(wdgnode) {
- jQuery(wdgnode).treeview({toggle: toggleTree,
- prerendered: true
- });
- }
-});
-
/* widget based on SIMILE's timeline widget
* http://code.google.com/p/simile-widgets/
--- a/web/data/jquery.corner.js Thu Jan 15 10:13:25 2009 +0100
+++ b/web/data/jquery.corner.js Wed Jun 03 19:42:23 2009 +0200
@@ -1,1 +1,178 @@
-if(!document.createElement('canvas').getContext){(function(){var m=Math;var y=m.round;var z=m.sin;var A=m.cos;var Z=10;var B=Z/2;function getContext(){if(this.context_){return this.context_}return this.context_=new CanvasRenderingContext2D_(this)}var C=Array.prototype.slice;function bind(f,b,c){var a=C.call(arguments,2);return function(){return f.apply(b,a.concat(C.call(arguments)))}}var D={init:function(a){if(/MSIE/.test(navigator.userAgent)&&!window.opera){var b=a||document;b.createElement('canvas');b.attachEvent('onreadystatechange',bind(this.init_,this,b))}},init_:function(a){if(!a.namespaces['g_vml_']){a.namespaces.add('g_vml_','urn:schemas-microsoft-com:vml')}if(!a.styleSheets['ex_canvas_']){var b=a.createStyleSheet();b.owningElement.id='ex_canvas_';b.cssText='canvas{display:inline-block;overflow:hidden;'+'text-align:left;width:300px;height:150px}'+'g_vml_\\:*{behavior:url(#default#VML)}'}},i:function(a){if(!a.getContext){a.getContext=getContext;a.attachEvent('onpropertychange',onPropertyChange);a.attachEvent('onresize',onResize);var b=a.attributes;if(b.width&&b.width.specified){a.style.width=b.width.nodeValue+'px'}else{a.width=a.clientWidth}if(b.height&&b.height.specified){a.style.height=b.height.nodeValue+'px'}else{a.height=a.clientHeight}}return a}};function onPropertyChange(e){var a=e.srcElement;switch(e.propertyName){case'width':a.style.width=a.attributes.width.nodeValue+'px';a.getContext().clearRect();break;case'height':a.style.height=a.attributes.height.nodeValue+'px';a.getContext().clearRect();break}}function onResize(e){var a=e.srcElement;if(a.firstChild){a.firstChild.style.width=a.clientWidth+'px';a.firstChild.style.height=a.clientHeight+'px'}}D.init();var E=[];for(var i=0;i<16;i++){for(var j=0;j<16;j++){E[i*16+j]=i.toString(16)+j.toString(16)}}function createMatrixIdentity(){return[[1,0,0],[0,1,0],[0,0,1]]}function processStyle(a){var b,alpha=1;a=String(a);if(a.substring(0,3)=='rgb'){var c=a.indexOf('(',3);var d=a.indexOf(')',c+1);var e=a.substring(c+1,d).split(',');b='#';for(var i=0;i<3;i++){b+=E[Number(e[i])]}if(e.length==4&&a.substr(3,1)=='a'){alpha=e[3]}}else{b=a}return[b,alpha]}function processLineCap(a){switch(a){case'butt':return'flat';case'round':return'round';case'square':default:return'square'}}function CanvasRenderingContext2D_(a){this.m_=createMatrixIdentity();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.strokeStyle='#000';this.fillStyle='#000';this.lineWidth=1;this.lineJoin='miter';this.lineCap='butt';this.miterLimit=Z*1;this.globalAlpha=1;this.canvas=a;var b=a.ownerDocument.createElement('div');b.style.width=a.clientWidth+'px';b.style.height=a.clientHeight+'px';b.style.overflow='hidden';b.style.position='absolute';a.appendChild(b);this.element_=b;this.arcScaleX_=1;this.arcScaleY_=1}var F=CanvasRenderingContext2D_.prototype;F.clearRect=function(){this.element_.innerHTML='';this.currentPath_=[]};F.beginPath=function(){this.currentPath_=[]};F.moveTo=function(a,b){var p=this.getCoords_(a,b);this.currentPath_.push({type:'moveTo',x:p.x,y:p.y});this.currentX_=p.x;this.currentY_=p.y};F.lineTo=function(a,b){var p=this.getCoords_(a,b);this.currentPath_.push({type:'lineTo',x:p.x,y:p.y});this.currentX_=p.x;this.currentY_=p.y};F.bezierCurveTo=function(a,b,c,d,e,f){var p=this.getCoords_(e,f);var g=this.getCoords_(a,b);var h=this.getCoords_(c,d);this.currentPath_.push({type:'bezierCurveTo',cp1x:g.x,cp1y:g.y,cp2x:h.x,cp2y:h.y,x:p.x,y:p.y});this.currentX_=p.x;this.currentY_=p.y};F.fillRect=function(a,b,c,d){this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath();this.fill();this.currentPath_=[]};F.createLinearGradient=function(a,b,c,d){return new CanvasGradient_('gradient')};F.createRadialGradient=function(a,b,c,d,e,f){var g=new CanvasGradient_('gradientradial');g.radius1_=c;g.radius2_=f;g.focus_.x=a;g.focus_.y=b;return g};F.stroke=function(d){var e=[];var f=false;var a=processStyle(d?this.fillStyle:this.strokeStyle);var g=a[0];var h=a[1]*this.globalAlpha;var W=10;var H=10;e.push('<g_vml_:shape',' fillcolor="',g,'"',' filled="',Boolean(d),'"',' style="position:absolute;width:',W,';height:',H,';"',' coordorigin="0 0" coordsize="',Z*W,' ',Z*H,'"',' stroked="',!d,'"',' strokeweight="',this.lineWidth,'"',' strokecolor="',g,'"',' path="');var j=false;var k={x:null,y:null};var l={x:null,y:null};for(var i=0;i<this.currentPath_.length;i++){var p=this.currentPath_[i];var c;switch(p.type){case'moveTo':e.push(' m ');c=p;e.push(y(p.x),',',y(p.y));break;case'lineTo':e.push(' l ');e.push(y(p.x),',',y(p.y));break;case'close':e.push(' x ');p=null;break;case'bezierCurveTo':e.push(' c ');e.push(y(p.cp1x),',',y(p.cp1y),',',y(p.cp2x),',',y(p.cp2y),',',y(p.x),',',y(p.y));break;case'at':case'wa':e.push(' ',p.type,' ');e.push(y(p.x-this.arcScaleX_*p.radius),',',y(p.y-this.arcScaleY_*p.radius),' ',y(p.x+this.arcScaleX_*p.radius),',',y(p.y+this.arcScaleY_*p.radius),' ',y(p.xStart),',',y(p.yStart),' ',y(p.xEnd),',',y(p.yEnd));break}if(p){if(k.x==null||p.x<k.x){k.x=p.x}if(l.x==null||p.x>l.x){l.x=p.x}if(k.y==null||p.y<k.y){k.y=p.y}if(l.y==null||p.y>l.y){l.y=p.y}}}e.push(' ">');if(typeof this.fillStyle=='object'){var m={x:'50%',y:'50%'};var n=l.x-k.x;var o=l.y-k.y;var q=n>o?n:o;m.x=y(this.fillStyle.focus_.x/n*100+50)+'%';m.y=y(this.fillStyle.focus_.y/o*100+50)+'%';var r=[];if(this.fillStyle.type_=='gradientradial'){var s=this.fillStyle.radius1_/q*100;var t=this.fillStyle.radius2_/q*100-s}else{var s=0;var t=100}var u={offset:null,color:null};var v={offset:null,color:null};this.fillStyle.colors_.sort(function(a,b){return a.offset-b.offset});for(var i=0;i<this.fillStyle.colors_.length;i++){var w=this.fillStyle.colors_[i];r.push(w.offset*t+s,'% ',w.color,',');if(w.offset>u.offset||u.offset==null){u.offset=w.offset;u.color=w.color}if(w.offset<v.offset||v.offset==null){v.offset=w.offset;v.color=w.color}}r.pop();e.push('<g_vml_:fill',' color="',v.color,'"',' color2="',u.color,'"',' type="',this.fillStyle.type_,'"',' focusposition="',m.x,', ',m.y,'"',' colors="',r.join(''),'"',' opacity="',h,'" />')}else if(d){e.push('<g_vml_:fill color="',g,'" opacity="',h,'" />')}else{var x=Math.max(this.arcScaleX_,this.arcScaleY_)*this.lineWidth;e.push('<g_vml_:stroke',' opacity="',h,'"',' joinstyle="',this.lineJoin,'"',' miterlimit="',this.miterLimit,'"',' endcap="',processLineCap(this.lineCap),'"',' weight="',x,'px"',' color="',g,'" />')}e.push('</g_vml_:shape>');this.element_.insertAdjacentHTML('beforeEnd',e.join(''))};F.fill=function(){this.stroke(true)};F.closePath=function(){this.currentPath_.push({type:'close'})};F.getCoords_=function(a,b){return{x:Z*(a*this.m_[0][0]+b*this.m_[1][0]+this.m_[2][0])-B,y:Z*(a*this.m_[0][1]+b*this.m_[1][1]+this.m_[2][1])-B}};function CanvasPattern_(){}G_vmlCMjrc=D})()}if(jQuery.browser.msie){document.execCommand("BackgroundImageCache",false,true)}(function($){var N=$.browser.msie;var O=N&&!window.XMLHttpRequest;var P=$.browser.opera;var Q=typeof document.createElement('canvas').getContext=="function";var R=function(i){return parseInt(i,10)||0};var S=function(a,b,c){var x=a,y;if(x.currentStyle){y=x.currentStyle[b]}else if(window.getComputedStyle){if(typeof arguments[2]=="string")b=c;y=document.defaultView.getComputedStyle(x,null).getPropertyValue(b)}return y};var T=function(a,p){return S(a,'border'+p+'Color','border-'+p.toLowerCase()+'-color')};var U=function(a,p){if(a.currentStyle&&!P){w=a.currentStyle['border'+p+'Width'];if(w=='thin')w=2;if(w=='medium'&&!(a.currentStyle['border'+p+'Style']=='none'))w=4;if(w=='thick')w=6}else{p=p.toLowerCase();w=document.defaultView.getComputedStyle(a,null).getPropertyValue('border-'+p+'-width')}return R(w)};var V=function(a,i){return a.tagName.toLowerCase()==i};var W=function(e,a,b,c,d){if(e=='tl')return a;if(e=='tr')return b;if(e=='bl')return c;if(e=='br')return d};var X=function(a,b,c,d,e,f,g){var h,curve_to;if(d.indexOf('rgba')!=-1){var i=/^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/;var j=i.exec(d);if(j){var k=[R(j[1]),R(j[2]),R(j[3])];d='rgb('+k[0]+', '+k[1]+', '+k[2]+')'}}var l=a.getContext('2d');if(b==1||g=='notch'){if(e>0&&b>1){l.fillStyle=f;l.fillRect(0,0,b,b);l.fillStyle=d;h=W(c,[0-e,0-e],[e,0-e],[0-e,e],[e,e]);l.fillRect(h[0],h[1],b,b)}else{l.fillStyle=d;l.fillRect(0,0,b,b)}return a}else if(g=='bevel'){h=W(c,[0,0,0,b,b,0,0,0],[0,0,b,b,b,0,0,0],[0,0,b,b,0,b,0,0],[b,b,b,0,0,b,b,b]);l.fillStyle=d;l.beginPath();l.moveTo(h[0],h[1]);l.lineTo(h[2],h[3]);l.lineTo(h[4],h[5]);l.lineTo(h[6],h[7]);l.fill();if(e>0&&e<b){l.strokeStyle=f;l.lineWidth=e;l.beginPath();h=W(c,[0,b,b,0],[0,0,b,b],[b,b,0,0],[0,b,b,0]);l.moveTo(h[0],h[1]);l.lineTo(h[2],h[3]);l.stroke()}return a}h=W(c,[0,0,b,0,b,0,0,b,0,0],[b,0,b,b,b,0,0,0,0,0],[0,b,b,b,0,b,0,0,0,b],[b,b,b,0,b,0,0,b,b,b]);l.fillStyle=d;l.beginPath();l.moveTo(h[0],h[1]);l.lineTo(h[2],h[3]);if(c=='br')l.bezierCurveTo(h[4],h[5],b,b,h[6],h[7]);else l.bezierCurveTo(h[4],h[5],0,0,h[6],h[7]);l.lineTo(h[8],h[9]);l.fill();if(e>0&&e<b){var m=e/2;var n=b-m;h=W(c,[n,m,n,m,m,n],[n,n,n,m,m,m],[n,n,m,n,m,m,m,n],[n,m,n,m,m,n,n,n]);curve_to=W(c,[0,0],[0,0],[0,0],[b,b]);l.strokeStyle=f;l.lineWidth=e;l.beginPath();l.moveTo(h[0],h[1]);l.bezierCurveTo(h[2],h[3],curve_to[0],curve_to[1],h[4],h[5]);l.stroke()}return a};var Y=function(p,a){var b=document.createElement('canvas');b.setAttribute("height",a);b.setAttribute("width",a);b.style.display="block";b.style.position="absolute";b.className="jrCorner";Z(p,b);if(!Q&&N){if(typeof G_vmlCanvasManager=="object"){b=G_vmlCanvasManager.initElement(b)}else if(typeof G_vmlCMjrc=="object"){b=G_vmlCMjrc.i(b)}else{throw Error('Could not find excanvas');}}return b};var Z=function(p,a){if(p.is("table")){p.children("tbody").children("tr:first").children("td:first").append(a);p.css('display','block')}else if(p.is("td")){if(p.children(".JrcTdContainer").length===0){p.html('<div class="JrcTdContainer" style="padding:0px;position:relative;margin:-1px;zoom:1;">'+p.html()+'</div>');p.css('zoom','1');if(O){p.children(".JrcTdContainer").get(0).style.setExpression("height","this.parentNode.offsetHeight")}}p.children(".JrcTdContainer").append(a)}else{p.append(a)}};if(N){var ba=document.createStyleSheet();ba.media='print';ba.cssText='.jrcIECanvasDiv { display:none !important; }'}var bb=function(D){if(this.length==0||!(Q||N)){return this}if(D=="destroy"){return this.each(function(){var p,elm=$(this);if(elm.is(".jrcRounded")){if(typeof elm.data("ie6tmr.jrc")=='number')window.clearInterval(elm.data("ie6tmr.jrc"));if(elm.is("table"))p=elm.children("tbody").children("tr:first").children("td:first");else if(elm.is("td"))p=elm.children(".JrcTdContainer");else p=elm;p.children(".jrCorner").remove();elm.unbind('mouseleave.jrc').unbind('mouseenter.jrc').removeClass('jrcRounded').removeData('ie6tmr.jrc');if(elm.is("td"))elm.html(elm.children(".JrcTdContainer").html())}})}var o=(D||"").toLowerCase();var E=R((o.match(/(\d+)px/)||[])[1])||"auto";var F=((o.match(/(#[0-9a-f]+)/)||[])[1])||"auto";var G=/round|bevel|notch/;var H=((o.match(G)||['round'])[0]);var I=/hover/.test(o);var J=/oversized/.test(o);var K=o.match("hiddenparent");if(N){var G=/ie6nofix|ie6fixinit|ie6fixexpr|ie6fixonload|ie6fixwidthint|ie6fixheightint|ie6fixbothint/;var L=((o.match(G)||['ie6fixinit'])[0])}var M={tl:/top|left|tl/.test(o),tr:/top|right|tr/.test(o),bl:/bottom|left|bl/.test(o),br:/bottom|right|br/.test(o)};if(!M.tl&&!M.tr&&!M.bl&&!M.br)M={tl:1,tr:1,bl:1,br:1};this.each(function(){var d=$(this),rbg=null,bg,s,b,pr;var a=this;var e=S(this,'display');var f=S(this,'position');var g=S(this,'lineHeight','line-height');if(F=="auto"){s=d.siblings(".jrcRounded:eq(0)");if(s.length>0){b=s.data("rbg.jrc");if(typeof b=="string"){rbg=b}}}if(K||rbg===null){var h=this.parentNode,hidden_parents=new Array(),a=0;while((typeof h=='object')&&!V(h,'html')){if(K&&S(h,'display')=='none'){hidden_parents.push({originalvisibility:S(h,'visibility'),elm:h});h.style.display='block';h.style.visibility='hidden'}var j=S(h,'backgroundColor','background-color');if(rbg===null&&j!="transparent"&&j!="rgba(0, 0, 0, 0)"){rbg=j}h=h.parentNode}if(rbg===null)rbg="#ffffff"}if(F=="auto"){bg=rbg;d.data("rbg.jrc",rbg)}else{bg=F}if(e=='none'){var k=S(this,'visibility');this.style.display='block';this.style.visibility='hidden';var l=true}else{var m=false}var n=d.height();var p=d.width();if(I){var q=o.replace(/hover|ie6nofix|ie6fixinit|ie6fixexpr|ie6fixonload|ie6fixwidthint|ie6fixheightint|ie6fixbothint/g,"");if(L!='ie6nofix')q="ie6fixinit "+q;d.bind("mouseenter.jrc",function(){d.addClass('jrcHover');d.corner(q)});d.bind("mouseleave.jrc",function(){d.removeClass('jrcHover');d.corner(q)})}if(O&&L!='ie6nofix'){this.style.zoom=1;if(L!='ie6fixexpr'){if(d.width()%2!=0)d.width(d.width()+1);if(d.height()%2!=0)d.height(d.height()+1)}$(window).load(function(){if(L=='ie6fixonload'){if(d.css('height')=='auto')d.height(d.css('height'));if(d.width()%2!=0)d.width(d.width()+1);if(d.height()%2!=0)d.height(d.height()+1)}else if(L=='ie6fixwidthint'||L=='ie6fixheightint'||L=='ie6fixbothint'){var c,ie6FixFunction;if(L=='ie6fixheightint'){ie6FixFunction=function(){d.height('auto');var a=d.height();if(a%2!=0)a=a+1;d.css({height:a})}}else if(L=='ie6fixwidthint'){ie6FixFunction=function(){d.width('auto');var a=d.width();if(a%2!=0)a=a+1;d.css({width:a});d.data('lastWidth.jrc',d.get(0).offsetWidth)}}else if(L=='ie6fixbothint'){ie6FixFunction=function(){d.width('auto');d.height('auto');var a=d.width();var b=d.height();if(b%2!=0)b=b+1;if(a%2!=0)a=a+1;d.css({width:a,height:b})}}c=window.setInterval(ie6FixFunction,100);d.data("ie6tmr.jrc",c)}})}var r=n<p?this.offsetHeight:this.offsetWidth;if(E=="auto"){E=r/2;if(E>10)E=r/4}if(E>r/2&&!J){E=r/2}E=Math.floor(E);var t=U(this,'Top');var u=U(this,'Right');var v=U(this,'Bottom');var w=U(this,'Left');if(f=='static'&&!V(this,'td')){this.style.position='relative'}else if(f=='fixed'&&N&&!(document.compatMode=='CSS1Compat'&&!O)){this.style.position='absolute'}if(t+u+v+w>0){this.style.overflow='visible'}if(l)d.css({display:'none',visibility:k});if(typeof hidden_parents!="undefined"){for(var i=0;i<hidden_parents.length;i++){hidden_parents[i].elm.style.display='none';hidden_parents[i].elm.style.visibility=hidden_parents[i].originalvisibility}}var x=0-t,p_right=0-u,p_bottom=0-v,p_left=0-w;var y=(d.find("canvas").length>0);if(y){if(V(this,'table'))pr=d.children("tbody").children("tr:first").children("td:first");else if(V(this,'td'))pr=d.children(".JrcTdContainer");else pr=d}if(M.tl){bordersWidth=t<w?t:w;if(y)pr.children("canvas.jrcTL").remove();var z=X(Y(d,E),E,'tl',bg,bordersWidth,T(this,'Top'),H);$(z).css({left:p_left,top:x}).addClass('jrcTL')}if(M.tr){bordersWidth=t<u?t:u;if(y)pr.children("canvas.jrcTR").remove();var A=X(Y(d,E),E,'tr',bg,bordersWidth,T(this,'Top'),H);$(A).css({right:p_right,top:x}).addClass('jrcTR')}if(M.bl){bordersWidth=v<w?v:w;if(y)pr.children("canvas.jrcBL").remove();var B=X(Y(d,E),E,'bl',bg,bordersWidth,T(this,'Bottom'),H);$(B).css({left:p_left,bottom:p_bottom}).addClass('jrcBL')}if(M.br){bordersWidth=v<u?v:u;if(y)pr.children("canvas.jrcBR").remove();var C=X(Y(d,E),E,'br',bg,bordersWidth,T(this,'Bottom'),H);$(C).css({right:p_right,bottom:p_bottom}).addClass('jrcBR')}if(N)d.children('canvas.jrCorner').children('div').addClass('jrcIECanvasDiv');if(O&&L=='ie6fixexpr'){if(M.bl){B.style.setExpression("bottom","this.parentNode.offsetHeight % 2 == 0 || this.parentNode.offsetWidth % 2 == 0 ? 0-(parseInt(this.parentNode.currentStyle['borderBottomWidth'])) : 0-(parseInt(this.parentNode.currentStyle['borderBottomWidth'])+1)")}if(M.br){C.style.setExpression("right","this.parentNode.offsetWidth % 2 == 0 || this.parentNode.offsetWidth % 2 == 0 ? 0-(parseInt(this.parentNode.currentStyle['borderRightWidth'])) : 0-(parseInt(this.parentNode.currentStyle['borderRightWidth'])+1)");C.style.setExpression("bottom","this.parentNode.offsetHeight % 2 == 0 || this.parentNode.offsetWidth % 2 == 0 ? 0-(parseInt(this.parentNode.currentStyle['borderBottomWidth'])) : 0-(parseInt(this.parentNode.currentStyle['borderBottomWidth'])+1)")}if(M.tr){A.style.setExpression("right","this.parentNode.offsetWidth % 2 == 0 || this.parentNode.offsetWidth % 2 == 0 ? 0-(parseInt(this.parentNode.currentStyle['borderRightWidth'])) : 0-(parseInt(this.parentNode.currentStyle['borderRightWidth'])+1)")}}d.addClass('jrcRounded')});if(typeof arguments[1]=="function")arguments[1](this);return this};$.fn.corner=bb})(jQuery);
\ No newline at end of file
+/*
+ * jQuery corner plugin
+ *
+ * version 1.92 (12/18/2007)
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ */
+
+/**
+ * The corner() method provides a simple way of styling DOM elements.
+ *
+ * corner() takes a single string argument: $().corner("effect corners width")
+ *
+ * effect: The name of the effect to apply, such as round or bevel.
+ * If you don't specify an effect, rounding is used.
+ *
+ * corners: The corners can be one or more of top, bottom, tr, tl, br, or bl.
+ * By default, all four corners are adorned.
+ *
+ * width: The width specifies the width of the effect; in the case of rounded corners this
+ * will be the radius of the width.
+ * Specify this value using the px suffix such as 10px, and yes it must be pixels.
+ *
+ * For more details see: http://methvin.com/jquery/jq-corner.html
+ * For a full demo see: http://malsup.com/jquery/corner/
+ *
+ *
+ * @example $('.adorn').corner();
+ * @desc Create round, 10px corners
+ *
+ * @example $('.adorn').corner("25px");
+ * @desc Create round, 25px corners
+ *
+ * @example $('.adorn').corner("notch bottom");
+ * @desc Create notched, 10px corners on bottom only
+ *
+ * @example $('.adorn').corner("tr dog 25px");
+ * @desc Create dogeared, 25px corner on the top-right corner only
+ *
+ * @example $('.adorn').corner("round 8px").parent().css('padding', '4px').corner("round 10px");
+ * @desc Create a rounded border effect by styling both the element and its parent
+ *
+ * @name corner
+ * @type jQuery
+ * @param String options Options which control the corner style
+ * @cat Plugins/Corner
+ * @return jQuery
+ * @author Dave Methvin (dave.methvin@gmail.com)
+ * @author Mike Alsup (malsup@gmail.com)
+ */
+(function($) {
+
+$.fn.corner = function(o) {
+ var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent);
+ function sz(el, p) { return parseInt($.css(el,p))||0; };
+ function hex2(s) {
+ var s = parseInt(s).toString(16);
+ return ( s.length < 2 ) ? '0'+s : s;
+ };
+ function gpc(node) {
+ for ( ; node && node.nodeName.toLowerCase() != 'html'; node = node.parentNode ) {
+ var v = $.css(node,'backgroundColor');
+ if ( v.indexOf('rgb') >= 0 ) {
+ if ($.browser.safari && v == 'rgba(0, 0, 0, 0)')
+ continue;
+ var rgb = v.match(/\d+/g);
+ return '#'+ hex2(rgb[0]) + hex2(rgb[1]) + hex2(rgb[2]);
+ }
+ if ( v && v != 'transparent' )
+ return v;
+ }
+ return '#ffffff';
+ };
+ function getW(i) {
+ switch(fx) {
+ case 'round': return Math.round(width*(1-Math.cos(Math.asin(i/width))));
+ case 'cool': return Math.round(width*(1+Math.cos(Math.asin(i/width))));
+ case 'sharp': return Math.round(width*(1-Math.cos(Math.acos(i/width))));
+ case 'bite': return Math.round(width*(Math.cos(Math.asin((width-i-1)/width))));
+ case 'slide': return Math.round(width*(Math.atan2(i,width/i)));
+ case 'jut': return Math.round(width*(Math.atan2(width,(width-i-1))));
+ case 'curl': return Math.round(width*(Math.atan(i)));
+ case 'tear': return Math.round(width*(Math.cos(i)));
+ case 'wicked': return Math.round(width*(Math.tan(i)));
+ case 'long': return Math.round(width*(Math.sqrt(i)));
+ case 'sculpt': return Math.round(width*(Math.log((width-i-1),width)));
+ case 'dog': return (i&1) ? (i+1) : width;
+ case 'dog2': return (i&2) ? (i+1) : width;
+ case 'dog3': return (i&3) ? (i+1) : width;
+ case 'fray': return (i%2)*width;
+ case 'notch': return width;
+ case 'bevel': return i+1;
+ }
+ };
+ o = (o||"").toLowerCase();
+ var keep = /keep/.test(o); // keep borders?
+ var cc = ((o.match(/cc:(#[0-9a-f]+)/)||[])[1]); // corner color
+ var sc = ((o.match(/sc:(#[0-9a-f]+)/)||[])[1]); // strip color
+ var width = parseInt((o.match(/(\d+)px/)||[])[1]) || 10; // corner width
+ var re = /round|bevel|notch|bite|cool|sharp|slide|jut|curl|tear|fray|wicked|sculpt|long|dog3|dog2|dog/;
+ var fx = ((o.match(re)||['round'])[0]);
+ var edges = { T:0, B:1 };
+ var opts = {
+ TL: /top|tl/.test(o), TR: /top|tr/.test(o),
+ BL: /bottom|bl/.test(o), BR: /bottom|br/.test(o)
+ };
+ if ( !opts.TL && !opts.TR && !opts.BL && !opts.BR )
+ opts = { TL:1, TR:1, BL:1, BR:1 };
+ var strip = document.createElement('div');
+ strip.style.overflow = 'hidden';
+ strip.style.height = '1px';
+ strip.style.backgroundColor = sc || 'transparent';
+ strip.style.borderStyle = 'solid';
+ return this.each(function(index){
+ var pad = {
+ T: parseInt($.css(this,'paddingTop'))||0, R: parseInt($.css(this,'paddingRight'))||0,
+ B: parseInt($.css(this,'paddingBottom'))||0, L: parseInt($.css(this,'paddingLeft'))||0
+ };
+
+ if ($.browser.msie) this.style.zoom = 1; // force 'hasLayout' in IE
+ if (!keep) this.style.border = 'none';
+ strip.style.borderColor = cc || gpc(this.parentNode);
+ var cssHeight = $.curCSS(this, 'height');
+
+ for (var j in edges) {
+ var bot = edges[j];
+ // only add stips if needed
+ if ((bot && (opts.BL || opts.BR)) || (!bot && (opts.TL || opts.TR))) {
+ strip.style.borderStyle = 'none '+(opts[j+'R']?'solid':'none')+' none '+(opts[j+'L']?'solid':'none');
+ var d = document.createElement('div');
+ $(d).addClass('jquery-corner');
+ var ds = d.style;
+
+ bot ? this.appendChild(d) : this.insertBefore(d, this.firstChild);
+
+ if (bot && cssHeight != 'auto') {
+ if ($.css(this,'position') == 'static')
+ this.style.position = 'relative';
+ ds.position = 'absolute';
+ ds.bottom = ds.left = ds.padding = ds.margin = '0';
+ if ($.browser.msie)
+ ds.setExpression('width', 'this.parentNode.offsetWidth');
+ else
+ ds.width = '100%';
+ }
+ else if (!bot && $.browser.msie) {
+ if ($.css(this,'position') == 'static')
+ this.style.position = 'relative';
+ ds.position = 'absolute';
+ ds.top = ds.left = ds.right = ds.padding = ds.margin = '0';
+
+ // fix ie6 problem when blocked element has a border width
+ var bw = 0;
+ if (ie6 || !$.boxModel)
+ bw = sz(this,'borderLeftWidth') + sz(this,'borderRightWidth');
+ ie6 ? ds.setExpression('width', 'this.parentNode.offsetWidth - '+bw+'+ "px"') : ds.width = '100%';
+ }
+ else {
+ ds.margin = !bot ? '-'+pad.T+'px -'+pad.R+'px '+(pad.T-width)+'px -'+pad.L+'px' :
+ (pad.B-width)+'px -'+pad.R+'px -'+pad.B+'px -'+pad.L+'px';
+ }
+
+ for (var i=0; i < width; i++) {
+ var w = Math.max(0,getW(i));
+ var e = strip.cloneNode(false);
+ e.style.borderWidth = '0 '+(opts[j+'R']?w:0)+'px 0 '+(opts[j+'L']?w:0)+'px';
+ bot ? d.appendChild(e) : d.insertBefore(e, d.firstChild);
+ }
+ }
+ }
+ });
+};
+
+$.fn.uncorner = function(o) { return $('.jquery-corner', this).remove(); };
+
+})(jQuery);
--- a/web/facet.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/facet.py Wed Jun 03 19:42:23 2009 +0200
@@ -29,7 +29,7 @@
def prepare_facets_rqlst(rqlst, args=None):
"""prepare a syntax tree to generate facet filters
-
+
* remove ORDERBY clause
* cleanup selection (remove everything)
* undefine unnecessary variables
@@ -64,7 +64,7 @@
def get_facet(req, facetid, rqlst, mainvar):
return req.vreg.object_by_id('facets', facetid, req, rqlst=rqlst,
filtered_variable=mainvar)
-
+
def filter_hiddens(w, **kwargs):
for key, val in kwargs.items():
@@ -139,7 +139,7 @@
rqlst.add_group_var(newvar)
rqlst.add_selected(newvar)
return newvar, rel
-
+
def _remove_relation(rqlst, rel, var):
"""remove a constraint relation from the syntax tree"""
# remove the relation
@@ -229,10 +229,10 @@
if ovarname == mainvar.name:
continue
if not has_path(vargraph, ovarname, mainvar.name):
- toremove.add(rqlst.defined_vars[ovarname])
+ toremove.add(rqlst.defined_vars[ovarname])
-
-
+
+
## base facet classes #########################################################
class AbstractFacet(AcceptMixIn, AppRsetObject):
__registerer__ = priority_registerer
@@ -243,16 +243,16 @@
help=_('display the box or not')),
_('order'): dict(type='Int', default=99,
help=_('display order of the box')),
- _('context'): dict(type='String', default=None,
+ _('context'): dict(type='String', default='',
# None <-> both
- vocabulary=(_('tablefilter'), _('facetbox'), None),
+ vocabulary=(_('tablefilter'), _('facetbox'), ''),
help=_('context where this box should be displayed')),
}
visible = True
- context = None
+ context = ''
needs_update = False
start_unfolded = True
-
+
@classmethod
def selected(cls, req, rset=None, rqlst=None, context=None,
filtered_variable=None):
@@ -280,20 +280,20 @@
def operator(self):
# OR between selected values by default
return self.req.form.get(self.id + '_andor', 'OR')
-
+
def get_widget(self):
"""return the widget instance to use to display this facet
"""
raise NotImplementedError
-
+
def add_rql_restrictions(self):
"""add restriction for this facet into the rql syntax tree"""
raise NotImplementedError
-
+
class VocabularyFacet(AbstractFacet):
needs_update = True
-
+
def get_widget(self):
"""return the widget instance to use to display this facet
@@ -311,12 +311,12 @@
else:
wdg.append(FacetItem(self.req, label, value, value in selected))
return wdg
-
+
def vocabulary(self):
"""return vocabulary for this facet, eg a list of 2-uple (label, value)
"""
raise NotImplementedError
-
+
def possible_values(self):
"""return a list of possible values (as string since it's used to
compare to a form value in javascript) for this facet
@@ -325,13 +325,13 @@
def support_and(self):
return False
-
+
def rqlexec(self, rql, args=None, cachekey=None):
try:
return self.req.execute(rql, args, cachekey)
except Unauthorized:
return []
-
+
class RelationFacet(VocabularyFacet):
__selectors__ = (one_has_relation, match_context_prop)
@@ -344,10 +344,10 @@
sortfunc = None
# ascendant/descendant sorting
sortasc = True
-
+
@property
def title(self):
- return display_name(self.req, self.rtype, form=self.role)
+ return display_name(self.req, self.rtype, form=self.role)
def vocabulary(self):
"""return vocabulary for this facet, eg a list of 2-uple (label, value)
@@ -367,7 +367,7 @@
finally:
rqlst.recover()
return self.rset_vocabulary(rset)
-
+
def possible_values(self):
"""return a list of possible values (as string since it's used to
compare to a form value in javascript) for this facet
@@ -380,7 +380,7 @@
return [str(x) for x, in self.rqlexec(rqlst.as_string())]
finally:
rqlst.recover()
-
+
def rset_vocabulary(self, rset):
_ = self.req._
return [(_(label), eid) for eid, label in rset]
@@ -432,7 +432,9 @@
class AttributeFacet(RelationFacet):
# attribute type
attrtype = 'String'
-
+ # type of comparison: default is an exact match on the attribute value
+ comparator = '=' # could be '<', '<=', '>', '>='
+
def vocabulary(self):
"""return vocabulary for this facet, eg a list of 2-uple (label, value)
"""
@@ -452,14 +454,14 @@
finally:
rqlst.recover()
return self.rset_vocabulary(rset)
-
+
def rset_vocabulary(self, rset):
_ = self.req._
return [(_(value), value) for value, in rset]
def support_and(self):
return False
-
+
def add_rql_restrictions(self):
"""add restriction for this facet into the rql syntax tree"""
value = self.req.form.get(self.id)
@@ -467,16 +469,16 @@
return
mainvar = self.filtered_variable
self.rqlst.add_constant_restriction(mainvar, self.rtype, value,
- self.attrtype)
+ self.attrtype, self.comparator)
-
+
class FilterRQLBuilder(object):
"""called by javascript to get a rql string from filter form"""
def __init__(self, req):
self.req = req
-
+
def build_rql(self):#, tablefilter=False):
form = self.req.form
facetids = form['facets'].split(',')
@@ -490,18 +492,18 @@
toupdate.append(facetid)
return select.as_string(), toupdate
-
+
## html widets ################################################################
class FacetVocabularyWidget(HTMLWidget):
-
+
def __init__(self, facet):
self.facet = facet
self.items = []
def append(self, item):
self.items.append(item)
-
+
def _render(self):
title = html_escape(self.facet.title)
facetid = html_escape(self.facet.id)
@@ -527,7 +529,7 @@
self.w(u'</div>\n')
self.w(u'</div>\n')
-
+
class FacetStringWidget(HTMLWidget):
def __init__(self, facet):
self.facet = facet
@@ -558,12 +560,14 @@
if self.selected:
cssclass = ' facetValueSelected'
imgsrc = self.req.datadir_url + self.selected_img
+ imgalt = self.req._('selected')
else:
cssclass = ''
- imgsrc = self.req.datadir_url + self.unselected_img
+ imgsrc = self.req.datadir_url + self.unselected_img
+ imgalt = self.req._('not selected')
self.w(u'<div class="facetValue facetCheckBox%s" cubicweb:value="%s">\n'
% (cssclass, html_escape(unicode(self.value))))
- self.w(u'<img src="%s" /> ' % imgsrc)
+ self.w(u'<img src="%s" alt="%s"/> ' % (imgsrc, imgalt))
self.w(u'<a href="javascript: {}">%s</a>' % html_escape(self.label))
self.w(u'</div>')
@@ -571,7 +575,7 @@
class FacetSeparator(HTMLWidget):
def __init__(self, label=None):
self.label = label or u' '
-
+
def _render(self):
pass
--- a/web/form.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/form.py Wed Jun 03 19:42:23 2009 +0200
@@ -11,7 +11,7 @@
from logilab.mtconverter import html_escape
from cubicweb import typed_eid
-from cubicweb.common.selectors import req_form_params_selector
+from cubicweb.common.selectors import match_form_params
from cubicweb.common.registerers import accepts_registerer
from cubicweb.common.view import NOINDEX, NOFOLLOW, View, EntityView, AnyRsetView
from cubicweb.web import stdmsgs
@@ -239,7 +239,7 @@
should list necessary parameters in the form to be accepted.
"""
__registerer__ = accepts_registerer
- __select__ = classmethod(req_form_params_selector)
+ __select__ = classmethod(match_form_params)
form_params = ()
--- a/web/request.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/request.py Wed Jun 03 19:42:23 2009 +0200
@@ -201,7 +201,7 @@
def update_search_state(self):
"""update the current search state"""
searchstate = self.form.get('__mode')
- if not searchstate:
+ if not searchstate and self.cnx is not None:
searchstate = self.get_session_data('search_state', 'normal')
self.set_search_state(searchstate)
@@ -212,7 +212,8 @@
else:
self.search_state = ('linksearch', searchstate.split(':'))
assert len(self.search_state[-1]) == 4
- self.set_session_data('search_state', searchstate)
+ if self.cnx is not None:
+ self.set_session_data('search_state', searchstate)
def update_breadcrumbs(self):
"""stores the last visisted page in session data"""
@@ -640,7 +641,11 @@
def xhtml_browser(self):
useragent = self.useragent()
- if useragent and ('MSIE' in useragent or 'KHTML' in useragent):
+ # MSIE does not support xml content-type
+ # quick fix: Opera supports xhtml and handles namespaces
+ # properly but it breaks jQuery.attr()
+ if useragent and ('MSIE' in useragent or 'KHTML' in useragent
+ or 'Opera' in useragent):
return False
return True
--- a/web/test/jstest_python.jst Thu Jan 15 10:13:25 2009 +0100
+++ b/web/test/jstest_python.jst Wed Jun 03 19:42:23 2009 +0200
@@ -1,11 +1,13 @@
+// run tests with the following command line :
+// $ crosscheck jstest_python.jst
crosscheck.addTest({
setup: function() {
crosscheck.load("testutils.js");
crosscheck.load("../data/jquery.js");
- crosscheck.load("../data/compat.js");
- crosscheck.load("../data/python.js");
+ crosscheck.load("../data/cubicweb.compat.js");
+ crosscheck.load("../data/cubicweb.python.js");
},
test_basic_number_parsing: function () {
--- a/web/test/test_views.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/test/test_views.py Wed Jun 03 19:42:23 2009 +0200
@@ -37,11 +37,11 @@
def test_manual_tests(self):
rset = self.execute('Any P,F,S WHERE P is EUser, P firstname F, P surname S')
self.view('table', rset, template=None, displayfilter=True, displaycols=[0,2])
- rset = self.execute('Any P,F,S WHERE P is EUser, P firstname F, P surname S LIMIT 1')
+ rset = self.execute('Any P,F,S LIMIT 1 WHERE P is EUser, P firstname F, P surname S')
rset.req.form['rtype'] = 'firstname'
- self.view('editrelation', rset, template=None, htmlcheck=False)
+ self.view('editrelation', rset, template=None)
rset.req.form['rtype'] = 'use_email'
- self.view('editrelation', rset, template=None, htmlcheck=False)
+ self.view('editrelation', rset, template=None)
def test_sortable_js_added(self):
@@ -49,7 +49,7 @@
# sortable.js should not be included by default
self.failIf('jquery.tablesorter.js' in self.view('oneline', rset))
# but should be included by the tableview
- rset = self.execute('Any P,F,S WHERE P is EUser, P firstname F, P surname S LIMIT 1')
+ rset = self.execute('Any P,F,S LIMIT 1 WHERE P is EUser, P firstname F, P surname S')
self.failUnless('jquery.tablesorter.js' in self.view('table', rset))
def test_js_added_only_once(self):
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/web/test/unittest_owl.py Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,4075 @@
+"""unittests for schema2dot"""
+
+import os
+
+from logilab.common.testlib import TestCase, unittest_main
+from logilab.common.compat import set
+from cubicweb.devtools.testlib import WebTest
+
+from lxml import etree
+from StringIO import StringIO
+
+
+class OWLTC(WebTest):
+
+ def test_schema2owl(self):
+
+ parser = etree.XMLParser(dtd_validation=True)
+
+ owl= StringIO('''<xsd:schema
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:owl="http://www.w3.org/2002/07/owl#"
+ targetNamespace="http://www.w3.org/2002/07/owl#"
+ elementFormDefault="qualified" attributeFormDefault="unqualified">
+
+<xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+
+<!-- The ontology -->
+
+<xsd:element name="Import">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:anyURI">
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="Ontology">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="owl:Import" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:group ref="owl:ontologyAnnotations"/>
+ <xsd:group ref="owl:Axiom" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="ontologyIRI" type="xsd:anyURI" use="optional"/>
+ <xsd:attribute name="versionIRI" type="xsd:anyURI" use="optional"/>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<!-- Entities, anonymous individuals, and literals -->
+
+<xsd:group name="Entity">
+ <xsd:choice>
+ <xsd:element ref="owl:Class"/>
+ <xsd:element ref="owl:Datatype"/>
+ <xsd:element ref="owl:ObjectProperty"/>
+ <xsd:element ref="owl:DataProperty"/>
+ <xsd:element ref="owl:AnnotationProperty"/>
+ <xsd:element ref="owl:NamedIndividual"/>
+ </xsd:choice>
+</xsd:group>
+
+<xsd:element name="Class">
+ <xsd:complexType>
+ <xsd:attribute name="IRI" type="xsd:anyURI" use="required"/>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="Datatype">
+ <xsd:complexType>
+ <xsd:attribute name="IRI" type="xsd:anyURI" use="required"/>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="ObjectProperty">
+ <xsd:complexType>
+ <xsd:attribute name="IRI" type="xsd:anyURI" use="required"/>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DataProperty">
+ <xsd:complexType>
+ <xsd:attribute name="IRI" type="xsd:anyURI" use="required"/>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="AnnotationProperty">
+ <xsd:complexType>
+ <xsd:attribute name="IRI" type="xsd:anyURI" use="required"/>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:group name="Individual">
+ <xsd:choice>
+ <xsd:element ref="owl:NamedIndividual"/>
+ <xsd:element ref="owl:AnonymousIndividual"/>
+ </xsd:choice>
+</xsd:group>
+
+<xsd:element name="NamedIndividual">
+ <xsd:complexType>
+ <xsd:attribute name="IRI" type="xsd:anyURI" use="required"/>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="AnonymousIndividual">
+ <xsd:complexType>
+ <xsd:attribute name="nodeID" type="xsd:NCName" use="required"/>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="Literal">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="datatypeIRI" type="xsd:anyURI"/>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+</xsd:element>
+
+<!-- Declarations -->
+
+<xsd:element name="Declaration">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:Entity"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<!-- Object property expressions -->
+
+<xsd:group name="ObjectPropertyExpression">
+ <xsd:choice>
+ <xsd:element ref="owl:ObjectProperty"/>
+ <xsd:element ref="owl:InverseObjectProperty"/>
+ </xsd:choice>
+</xsd:group>
+
+<xsd:element name="InverseObjectProperty">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="owl:ObjectProperty"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<!-- Data property expressions -->
+
+<xsd:group name="DataPropertyExpression">
+ <xsd:sequence>
+ <xsd:element ref="owl:DataProperty"/>
+ </xsd:sequence>
+</xsd:group>
+
+<!-- Data ranges -->
+
+<xsd:group name="DataRange">
+ <xsd:choice>
+ <xsd:element ref="owl:Datatype"/>
+ <xsd:element ref="owl:DataIntersectionOf"/>
+ <xsd:element ref="owl:DataUnionOf"/>
+ <xsd:element ref="owl:DataComplementOf"/>
+ <xsd:element ref="owl:DataOneOf"/>
+ <xsd:element ref="owl:DatatypeRestriction"/>
+ </xsd:choice>
+</xsd:group>
+
+<xsd:element name="DataIntersectionOf">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:DataRange" minOccurs="2" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DataUnionOf">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:DataRange" minOccurs="2" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DataComplementOf">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:DataRange"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DataOneOf">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="owl:Literal" minOccurs="1" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DatatypeRestriction">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="owl:Datatype"/>
+ <xsd:element name="FacetRestriction" minOccurs="1" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="owl:Literal"/>
+ </xsd:sequence>
+ <xsd:attribute name="facet" type="xsd:anyURI" use="required"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<!-- Class expressions -->
+
+<xsd:group name="ClassExpression">
+ <xsd:choice>
+ <xsd:element ref="owl:Class"/>
+ <xsd:element ref="owl:ObjectIntersectionOf"/>
+ <xsd:element ref="owl:ObjectUnionOf"/>
+ <xsd:element ref="owl:ObjectComplementOf"/>
+ <xsd:element ref="owl:ObjectOneOf"/>
+ <xsd:element ref="owl:ObjectSomeValuesFrom"/>
+ <xsd:element ref="owl:ObjectAllValuesFrom"/>
+ <xsd:element ref="owl:ObjectHasValue"/>
+ <xsd:element ref="owl:ObjectHasSelf"/>
+ <xsd:element ref="owl:ObjectMinCardinality"/>
+ <xsd:element ref="owl:ObjectMaxCardinality"/>
+ <xsd:element ref="owl:ObjectExactCardinality"/>
+ <xsd:element ref="owl:DataSomeValuesFrom"/>
+ <xsd:element ref="owl:DataAllValuesFrom"/>
+ <xsd:element ref="owl:DataHasValue"/>
+ <xsd:element ref="owl:DataMinCardinality"/>
+ <xsd:element ref="owl:DataMaxCardinality"/>
+ <xsd:element ref="owl:DataExactCardinality"/>
+ </xsd:choice>
+</xsd:group>
+
+<xsd:element name="ObjectIntersectionOf">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:ClassExpression" minOccurs="2" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="ObjectUnionOf">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:ClassExpression" minOccurs="2" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="ObjectComplementOf">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:ClassExpression"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="ObjectOneOf">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:Individual" minOccurs="1" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="ObjectSomeValuesFrom">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ <xsd:group ref="owl:ClassExpression"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="ObjectAllValuesFrom">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ <xsd:group ref="owl:ClassExpression"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="ObjectHasValue">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ <xsd:group ref="owl:Individual"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="ObjectHasSelf">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="ObjectMinCardinality">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ <xsd:group ref="owl:ClassExpression" minOccurs="0" maxOccurs="1"/>
+ </xsd:sequence>
+ <xsd:attribute name="cardinality" type="xsd:nonNegativeInteger" use="required"/>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="ObjectMaxCardinality">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ <xsd:group ref="owl:ClassExpression" minOccurs="0" maxOccurs="1"/>
+ </xsd:sequence>
+ <xsd:attribute name="cardinality" type="xsd:nonNegativeInteger" use="required"/>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="ObjectExactCardinality">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ <xsd:group ref="owl:ClassExpression" minOccurs="0" maxOccurs="1"/>
+ </xsd:sequence>
+ <xsd:attribute name="cardinality" type="xsd:nonNegativeInteger" use="required"/>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DataSomeValuesFrom">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:DataPropertyExpression" minOccurs="1" maxOccurs="unbounded"/>
+ <xsd:group ref="owl:DataRange"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DataAllValuesFrom">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:DataPropertyExpression" minOccurs="1" maxOccurs="unbounded"/>
+ <xsd:group ref="owl:DataRange"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DataHasValue">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:DataPropertyExpression"/>
+ <xsd:element ref="owl:Literal"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DataMinCardinality">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:DataPropertyExpression"/>
+ <xsd:group ref="owl:DataRange" minOccurs="0" maxOccurs="1"/>
+ </xsd:sequence>
+ <xsd:attribute name="cardinality" type="xsd:nonNegativeInteger" use="required"/>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DataMaxCardinality">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:DataPropertyExpression"/>
+ <xsd:group ref="owl:DataRange" minOccurs="0" maxOccurs="1"/>
+ </xsd:sequence>
+ <xsd:attribute name="cardinality" type="xsd:nonNegativeInteger" use="required"/>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DataExactCardinality">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:DataPropertyExpression"/>
+ <xsd:group ref="owl:DataRange" minOccurs="0" maxOccurs="1"/>
+ </xsd:sequence>
+ <xsd:attribute name="cardinality" type="xsd:nonNegativeInteger" use="required"/>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<!-- Axioms -->
+
+<xsd:group name="Axiom">
+ <xsd:choice>
+ <xsd:element ref="owl:Declaration"/>
+ <xsd:group ref="owl:ClassAxiom"/>
+ <xsd:group ref="owl:ObjectPropertyAxiom"/>
+ <xsd:group ref="owl:DataPropertyAxiom"/>
+ <xsd:element ref="owl:HasKey"/>
+ <xsd:group ref="owl:Assertion"/>
+ <xsd:group ref="owl:AnnotationAxiom"/>
+ </xsd:choice>
+</xsd:group>
+
+<!-- Class expression axioms -->
+
+<xsd:group name="ClassAxiom">
+ <xsd:choice>
+ <xsd:element ref="owl:SubClassOf"/>
+ <xsd:element ref="owl:EquivalentClasses"/>
+ <xsd:element ref="owl:DisjointClasses"/>
+ <xsd:element ref="owl:DisjointUnion"/>
+ </xsd:choice>
+</xsd:group>
+
+<xsd:element name="SubClassOf">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ClassExpression"/> <!-- This is the subexpression -->
+ <xsd:group ref="owl:ClassExpression"/> <!-- This is the superexpression -->
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="EquivalentClasses">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ClassExpression" minOccurs="2" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DisjointClasses">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ClassExpression" minOccurs="2" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DisjointUnion">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:element ref="owl:Class"/>
+ <xsd:group ref="owl:ClassExpression" minOccurs="2" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<!-- Object property axioms -->
+
+<xsd:group name="ObjectPropertyAxiom">
+ <xsd:choice>
+ <xsd:element ref="owl:SubObjectPropertyOf"/>
+ <xsd:element ref="owl:EquivalentObjectProperties"/>
+ <xsd:element ref="owl:DisjointObjectProperties"/>
+ <xsd:element ref="owl:InverseObjectProperties"/>
+ <xsd:element ref="owl:ObjectPropertyDomain"/>
+ <xsd:element ref="owl:ObjectPropertyRange"/>
+ <xsd:element ref="owl:FunctionalObjectProperty"/>
+ <xsd:element ref="owl:InverseFunctionalObjectProperty"/>
+ <xsd:element ref="owl:ReflexiveObjectProperty"/>
+ <xsd:element ref="owl:IrreflexiveObjectProperty"/>
+ <xsd:element ref="owl:SymmetricObjectProperty"/>
+ <xsd:element ref="owl:AsymmetricObjectProperty"/>
+ <xsd:element ref="owl:TransitiveObjectProperty"/>
+ </xsd:choice>
+</xsd:group>
+
+<xsd:element name="SubObjectPropertyOf">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:choice> <!-- This is the subproperty expression or the property chain -->
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ <xsd:element name="PropertyChain">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:ObjectPropertyExpression" minOccurs="2" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ <xsd:group ref="owl:ObjectPropertyExpression"/> <!-- This is the superproperty expression -->
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="EquivalentObjectProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ObjectPropertyExpression" minOccurs="2" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DisjointObjectProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ObjectPropertyExpression" minOccurs="2" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="ObjectPropertyDomain">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ <xsd:group ref="owl:ClassExpression"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="ObjectPropertyRange">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ <xsd:group ref="owl:ClassExpression"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="InverseObjectProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ObjectPropertyExpression" minOccurs="2" maxOccurs="2"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="FunctionalObjectProperty">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="InverseFunctionalObjectProperty">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="ReflexiveObjectProperty">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="IrreflexiveObjectProperty">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="SymmetricObjectProperty">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="AsymmetricObjectProperty">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="TransitiveObjectProperty">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<!-- Data property axioms -->
+
+<xsd:group name="DataPropertyAxiom">
+ <xsd:choice>
+ <xsd:element ref="owl:SubDataPropertyOf"/>
+ <xsd:element ref="owl:EquivalentDataProperties"/>
+ <xsd:element ref="owl:DisjointDataProperties"/>
+ <xsd:element ref="owl:DataPropertyDomain"/>
+ <xsd:element ref="owl:DataPropertyRange"/>
+ <xsd:element ref="owl:FunctionalDataProperty"/>
+ </xsd:choice>
+</xsd:group>
+
+<xsd:element name="SubDataPropertyOf">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:DataPropertyExpression"/> <!-- This is the subproperty expression -->
+ <xsd:group ref="owl:DataPropertyExpression"/> <!-- This is the superproperty expression -->
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="EquivalentDataProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:DataPropertyExpression" minOccurs="2" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DisjointDataProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:DataPropertyExpression" minOccurs="2" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DataPropertyDomain">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:DataPropertyExpression"/>
+ <xsd:group ref="owl:ClassExpression"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DataPropertyRange">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:DataPropertyExpression"/>
+ <xsd:group ref="owl:DataRange"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="FunctionalDataProperty">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:DataPropertyExpression"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<!-- Key axioms -->
+
+<xsd:element name="HasKey">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ClassExpression"/>
+ <xsd:choice minOccurs="1" maxOccurs="unbounded">
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ <xsd:group ref="owl:DataPropertyExpression"/>
+ </xsd:choice>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<!-- Assertions -->
+
+<xsd:group name="Assertion">
+ <xsd:choice>
+ <xsd:element ref="owl:SameIndividual"/>
+ <xsd:element ref="owl:DifferentIndividuals"/>
+ <xsd:element ref="owl:ClassAssertion"/>
+ <xsd:element ref="owl:ObjectPropertyAssertion"/>
+ <xsd:element ref="owl:NegativeObjectPropertyAssertion"/>
+ <xsd:element ref="owl:DataPropertyAssertion"/>
+ <xsd:element ref="owl:NegativeDataPropertyAssertion"/>
+ </xsd:choice>
+</xsd:group>
+
+<xsd:element name="SameIndividual">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:Individual" minOccurs="2" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DifferentIndividuals">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:Individual" minOccurs="2" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="ClassAssertion">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ClassExpression"/>
+ <xsd:group ref="owl:Individual"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="ObjectPropertyAssertion">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ <xsd:group ref="owl:Individual"/> <!-- This is the source invididual -->
+ <xsd:group ref="owl:Individual"/> <!-- This is the target individual -->
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="NegativeObjectPropertyAssertion">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:ObjectPropertyExpression"/>
+ <xsd:group ref="owl:Individual"/> <!-- This is the source invididual -->
+ <xsd:group ref="owl:Individual"/> <!-- This is the target individual -->
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="DataPropertyAssertion">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:DataPropertyExpression"/>
+ <xsd:group ref="owl:Individual"/> <!-- This is the source invididual -->
+ <xsd:element ref="owl:Literal"/> <!-- This is the target value -->
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="NegativeDataPropertyAssertion">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:group ref="owl:DataPropertyExpression"/>
+ <xsd:group ref="owl:Individual"/> <!-- This is the source invididual -->
+ <xsd:element ref="owl:Literal"/> <!-- This is the target value -->
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<!-- Annotations -->
+
+<xsd:element name="IRI">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:anyURI">
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:group name="AnnotationSubject">
+ <xsd:choice>
+ <xsd:element ref="owl:IRI"/>
+ <xsd:element ref="owl:AnonymousIndividual"/>
+ </xsd:choice>
+</xsd:group>
+
+<xsd:group name="AnnotationValue">
+ <xsd:choice>
+ <xsd:element ref="owl:IRI"/>
+ <xsd:element ref="owl:AnonymousIndividual"/>
+ <xsd:element ref="owl:Literal"/>
+ </xsd:choice>
+</xsd:group>
+
+<xsd:element name="Annotation">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:annotationAnnotations"/>
+ <xsd:element ref="owl:AnnotationProperty"/>
+ <xsd:group ref="owl:AnnotationValue"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:group name="axiomAnnotations">
+ <xsd:sequence>
+ <xsd:element ref="owl:Annotation" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+</xsd:group>
+
+<xsd:group name="ontologyAnnotations">
+ <xsd:sequence>
+ <xsd:element ref="owl:Annotation" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+</xsd:group>
+
+<xsd:group name="annotationAnnotations">
+ <xsd:sequence>
+ <xsd:element ref="owl:Annotation" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+</xsd:group>
+
+<!-- Annotation axioms -->
+
+<xsd:group name="AnnotationAxiom">
+ <xsd:choice>
+ <xsd:element ref="owl:AnnotationAssertion"/>
+ <xsd:element ref="owl:SubAnnotationPropertyOf"/>
+ <xsd:element ref="owl:AnnotationPropertyDomain"/>
+ <xsd:element ref="owl:AnnotationPropertyRange"/>
+ </xsd:choice>
+</xsd:group>
+
+<xsd:element name="AnnotationAssertion">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:element ref="owl:AnnotationProperty"/>
+ <xsd:group ref="owl:AnnotationSubject"/>
+ <xsd:group ref="owl:AnnotationValue"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="SubAnnotationPropertyOf">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:element ref="owl:AnnotationProperty"/> <!-- This is the subproperty -->
+ <xsd:element ref="owl:AnnotationProperty"/> <!-- This is the superproperty -->
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="AnnotationPropertyDomain">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:element ref="owl:AnnotationProperty"/>
+ <xsd:element ref="owl:IRI"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+<xsd:element name="AnnotationPropertyRange">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="owl:axiomAnnotations"/>
+ <xsd:element ref="owl:AnnotationProperty"/>
+ <xsd:element ref="owl:IRI"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xml:specialAttrs"/>
+ </xsd:complexType>
+</xsd:element>
+
+</xsd:schema>
+
+''')
+
+ rdf = StringIO('''<xsd:schema
+ xmlns:xsd="http://www.w3.org/1999/XMLSchema"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ targetNamespace="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+
+ <xsd:element name="RDF">
+ <xsd:complexType content="elementOnly" >
+ <xsd:sequence maxOccurs="*" >
+ <xsd:choice>
+ <xsd:element ref="rdf:TypedNode" /><!-- abstract !-->
+ <xsd:element ref="rdf:Bag" />
+ <xsd:element ref="rdf:Seq" />
+ <xsd:element ref="rdf:Alt" />
+ </xsd:choice>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <!-- RDF Typed nodes -->
+ <xsd:complexType name="TypedNodeType" content="elementOnly" >
+ <xsd:sequence maxOccurs="*" >
+ <xsd:element ref="rdf:PropertyElt" /><!--abstract !-->
+ </xsd:sequence>
+ <xsd:attribute name="id" minOccurs="0" type="ID" />
+ <xsd:attribute name="type" minOccurs="0" type="string" />
+ <xsd:attribute name="about" minOccurs="0" type="string" />
+ <xsd:attribute name="aboutEach" minOccurs="0" type="string" />
+ <xsd:attribute name="aboutEachPrefix" minOccurs="0" type="string" />
+ <xsd:attribute name="badID" minOccurs="0" type="ID" />
+ </xsd:complexType>
+ <xsd:element name="TypedNode" abstract="true" type="rdf:TypedNodeType" />
+
+ <xsd:element name="Description"
+ type="rdf:TypedNodeType" equivClass="rdf:TypedNode" />
+
+
+ <!-- RDF Property Elements -->
+ <xsd:complexType name="PropertyEltType" >
+ <xsd:any minOccurs="0" />
+ <xsd:attribute name="id" minOccurs="0" type="ID" />
+ <xsd:attribute name="resource" minOccurs="0" type="string" />
+ <xsd:attribute name="value" minOccurs="0" type="string" />
+ <xsd:attribute name="badID" minOccurs="0" type="ID" />
+ <xsd:attribute name="parseType" minOccurs="0" >
+ <xsd:simpleType base="NMTOKEN">
+ <xsd:enumeration value="Resource"/>
+ <xsd:enumeration value="Literal" />
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:anyAttribute />
+ </xsd:complexType>
+
+ <xsd:element name="PropertyElt" abstract="true" type="rdf:PropertyEltType" />
+
+ <xsd:element name="subject" equivClass="rdf:PropertyElt" />
+ <xsd:element name="predicate" equivClass="rdf:PropertyElt" />
+ <xsd:element name="object" equivClass="rdf:PropertyElt" />
+ <xsd:element name="type" equivClass="rdf:PropertyElt" />
+
+ <xsd:element name="value">
+ <xsd:complexType>
+ <xsd:any />
+ <xsd:anyAttribute />
+ </xsd:complexType>
+ </xsd:element>
+
+
+ <!-- RDF Containers -->
+ <xsd:complexType name="Container" abstract="true" content="elementOnly" >
+ <xsd:sequence maxOccurs="*">
+ <xsd:element name="li">
+ <xsd:complexType>
+ <xsd:any/>
+ <xsd:attribute name="id" minOccurs="0" type="ID" />
+ <xsd:attribute name="parseType" minOccurs="0" >
+ <xsd:simpleType base="NMTOKEN">
+ <xsd:enumeration value="Resource"/>
+ <xsd:enumeration value="Literal" />
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:anyAttribute />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute name="id" type="ID" />
+ <xsd:anyAttribute />
+ </xsd:complexType>
+
+ <xsd:element name="Alt" type="rdf:Container" />
+ <xsd:element name="Bag" type="rdf:Container" />
+ <xsd:element name="Seq" type="rdf:Container" />
+
+</xsd:schema>
+
+ ''')
+
+
+ xmlschema_rdf = etree.parse(rdf)
+ xmlschema_owl = etree.parse(owl)
+
+ owlschema = etree.XMLSchema(xmlschema_owl)
+ valid = StringIO('''<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE rdf:RDF [
+ <!ENTITY owl "http://www.w3.org/2002/07/owl#" >
+ <!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" >
+ <!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#" >
+ <!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
+ <!ENTITY inst_jplorg2 "http://logilab.org/owl/ontologies/inst_jplorg2#" >
+
+ ]>
+<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns="http://logilab.org/owl/ontologies/inst_jplorg2#" xmlns:inst_jplorg2="http://logilab.org/owl/ontologies/inst_jplorg2#" xml:base="http://logilab.org/owl/ontologies/inst_jplorg2#">
+
+ <owl:Ontology rdf:about="">
+ <rdfs:comment>
+ inst_jplorg2 Cubicweb OWL Ontology
+
+ </rdfs:comment>
+ <!-- classes definition --><owl:Class rdf:ID="Blog"><rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
+ <!-- relations --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_basket"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#interested_in"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#entry_of"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <!-- attributes --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#title"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#description"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#creation_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#modification_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf></owl:Class><owl:Class rdf:ID="BlogEntry"><rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
+ <!-- relations --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#entry_of"/>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_basket"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#filed_under"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#interested_in"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#comments"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#tags"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <!-- attributes --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#title"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#content_format"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#content"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#creation_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#modification_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf></owl:Class><owl:Class rdf:ID="Card"><rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
+ <!-- relations --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_basket"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#filed_under"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#require_permission"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#test_case_for"/>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#test_case_of"/>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#documented_by"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#instance_of"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#comments"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#tags"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <!-- attributes --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#title"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#synopsis"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#content_format"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#content"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#wikiid"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#creation_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#modification_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf></owl:Class><owl:Class rdf:ID="Email"><rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
+ <!-- relations --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#sent_on"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_basket"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#sender"/>
+ <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#recipients"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#cc"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#parts"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#attachment"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#reply_to"/>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#cites"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_thread"/>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#tags"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#generated_by"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#generated_by"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#comments"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#reply_to"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#cites"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <!-- attributes --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#subject"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#messageid"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#headers"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#creation_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#modification_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf></owl:Class><owl:Class rdf:ID="EmailThread"><rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
+ <!-- relations --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#forked_from"/>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_basket"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_thread"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#forked_from"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <!-- attributes --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#title"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#creation_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#modification_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf></owl:Class><owl:Class rdf:ID="ExtProject"><rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
+ <!-- relations --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_basket"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#filed_under"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#require_permission"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#recommends"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#uses"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#tags"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <!-- attributes --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#name"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#description_format"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#description"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#url"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#creation_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#modification_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf></owl:Class><owl:Class rdf:ID="File"><rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
+ <!-- relations --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_basket"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#filed_under"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#require_permission"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#documented_by"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#comments"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#attachment"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#attachment"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#tags"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <!-- attributes --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#data"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#data_format"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#data_encoding"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#name"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#description_format"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#description"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#creation_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#modification_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf></owl:Class><owl:Class rdf:ID="Image"><rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
+ <!-- relations --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_basket"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#require_permission"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#attachment"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#screenshot"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#tags"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <!-- attributes --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#data"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#data_format"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#data_encoding"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#name"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#description_format"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#description"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#creation_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#modification_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf></owl:Class><owl:Class rdf:ID="License"><rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
+ <!-- relations --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_basket"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#license_of"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#tags"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <!-- attributes --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#name"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#shortdesc"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#longdesc_format"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#longdesc"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#url"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#creation_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#modification_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf></owl:Class><owl:Class rdf:ID="Link"><rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
+ <!-- relations --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_basket"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#filed_under"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#comments"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#tags"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <!-- attributes --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#title"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#url"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#embed"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#description_format"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#description"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#creation_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#modification_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf></owl:Class><owl:Class rdf:ID="MailingList"><rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
+ <!-- relations --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_basket"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#use_email"/>
+ <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#mailinglist_of"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#sent_on"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#tags"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <!-- attributes --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#name"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#mlid"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#description_format"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#description"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#archive"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#homepage"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#creation_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#modification_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf></owl:Class><owl:Class rdf:ID="Project"><rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
+ <!-- relations --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_basket"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#uses"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#uses"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#recommends"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#recommends"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#documented_by"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#documented_by"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#screenshot"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_state"/>
+ <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#filed_under"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#require_permission"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#recommends"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#tags"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#concerns"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#test_case_of"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#mailinglist_of"/>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#uses"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#interested_in"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#license_of"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#version_of"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#wf_info_for"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <!-- attributes --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#name"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#summary"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#url"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#vcsurl"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#reporturl"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#downloadurl"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#debian_source_package"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#description_format"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#description"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#creation_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#modification_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf></owl:Class><owl:Class rdf:ID="TestInstance"><rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
+ <!-- relations --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#instance_of"/>
+ <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#for_version"/>
+ <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#generate_bug"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_basket"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_state"/>
+ <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#require_permission"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#comments"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#wf_info_for"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <!-- attributes --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#name"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#creation_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#modification_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf></owl:Class><owl:Class rdf:ID="Ticket"><rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
+ <!-- relations --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#see_also"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_basket"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#concerns"/>
+ <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#appeared_in"/>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#done_in"/>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_state"/>
+ <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#attachment"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#attachment"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#identical_to"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#depends_on"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#require_permission"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#tags"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#depends_on"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#comments"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#generate_bug"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#wf_info_for"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#test_case_for"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <!-- attributes --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#title"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#type"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#priority"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#load"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#load_left"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#debian_bug_number"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#description_format"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#description"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#creation_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#modification_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf></owl:Class><owl:Class rdf:ID="Version"><rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
+ <!-- relations --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_basket"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#version_of"/>
+ <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#todo_by"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#in_state"/>
+ <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality>
+ <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#conflicts"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#depends_on"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#require_permission"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#done_in"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#tags"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#depends_on"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#for_version"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#wf_info_for"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#appeared_in"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">n</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf>
+ <!-- attributes --><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#num"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#description_format"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#description"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#starting_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#prevision_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#publication_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#creation_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf><rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#modification_date"/>
+ <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality>
+ </owl:Restriction>
+ </rdfs:subClassOf></owl:Class><!-- property definition --><!-- object property --><owl:ObjectProperty rdf:ID="in_basket">
+ <rdfs:domain rdf:resource="#Blog"/>
+ <rdfs:range rdf:resource="#Basket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="interested_in">
+ <rdfs:domain rdf:resource="#Blog"/>
+ <rdfs:range rdf:resource="#EUser"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="entry_of">
+ <rdfs:domain rdf:resource="#Blog"/>
+ <rdfs:range rdf:resource="#BlogEntry"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="#Link"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="#ExtProject"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="#BlogEntry"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="#Card"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="#File"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="#Image"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="entry_of">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="#Blog"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_basket">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="#Basket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="filed_under">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="#Folder"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="interested_in">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="#EUser"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="comments">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="#Comment"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="tags">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="#Tag"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="#ExtProject"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="#Link"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="#BlogEntry"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="#File"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="#Image"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="#Card"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_basket">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="#Basket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="filed_under">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="#Folder"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="require_permission">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="#EPermission"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="test_case_for">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="test_case_of">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="documented_by">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="instance_of">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="#TestInstance"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="comments">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="#Comment"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="tags">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="#Tag"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#Image"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="sent_on">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#MailingList"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_basket">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#Basket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="sender">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#EmailAddress"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="recipients">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#EmailAddress"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="cc">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#EmailAddress"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="parts">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#EmailPart"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="attachment">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#File"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="reply_to">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#Email"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="cites">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#Email"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_thread">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#EmailThread"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="tags">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#Tag"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="generated_by">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#TrInfo"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="generated_by">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#Comment"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="comments">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#Comment"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="reply_to">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#Email"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="cites">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="#Email"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#EmailThread"/>
+ <rdfs:range rdf:resource="#EmailThread"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="forked_from">
+ <rdfs:domain rdf:resource="#EmailThread"/>
+ <rdfs:range rdf:resource="#EmailThread"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_basket">
+ <rdfs:domain rdf:resource="#EmailThread"/>
+ <rdfs:range rdf:resource="#Basket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_thread">
+ <rdfs:domain rdf:resource="#EmailThread"/>
+ <rdfs:range rdf:resource="#Email"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="forked_from">
+ <rdfs:domain rdf:resource="#EmailThread"/>
+ <rdfs:range rdf:resource="#EmailThread"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="#BlogEntry"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="#Card"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="#Link"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="#File"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="#Image"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="#ExtProject"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_basket">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="#Basket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="filed_under">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="#Folder"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="require_permission">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="#EPermission"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="recommends">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="uses">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="tags">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="#Tag"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="#Link"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="#BlogEntry"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="#Image"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="#ExtProject"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="#Card"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="#File"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_basket">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="#Basket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="filed_under">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="#Folder"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="require_permission">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="#EPermission"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="documented_by">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="comments">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="#Comment"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="attachment">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="#Email"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="attachment">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="tags">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="#Tag"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_basket">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="#Basket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="#File"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="#ExtProject"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="#Card"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="#BlogEntry"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="#Link"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="#Email"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="#Image"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="require_permission">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="#EPermission"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="attachment">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="screenshot">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="tags">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="#Tag"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_basket">
+ <rdfs:domain rdf:resource="#License"/>
+ <rdfs:range rdf:resource="#Basket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="license_of">
+ <rdfs:domain rdf:resource="#License"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="tags">
+ <rdfs:domain rdf:resource="#License"/>
+ <rdfs:range rdf:resource="#Tag"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="#BlogEntry"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="#Card"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="#ExtProject"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="#File"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="#Link"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="#Image"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_basket">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="#Basket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="filed_under">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="#Folder"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="comments">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="#Comment"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="tags">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="#Tag"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_basket">
+ <rdfs:domain rdf:resource="#MailingList"/>
+ <rdfs:range rdf:resource="#Basket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="use_email">
+ <rdfs:domain rdf:resource="#MailingList"/>
+ <rdfs:range rdf:resource="#EmailAddress"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="mailinglist_of">
+ <rdfs:domain rdf:resource="#MailingList"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="sent_on">
+ <rdfs:domain rdf:resource="#MailingList"/>
+ <rdfs:range rdf:resource="#Email"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="tags">
+ <rdfs:domain rdf:resource="#MailingList"/>
+ <rdfs:range rdf:resource="#Tag"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#BlogEntry"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#Link"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#Card"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#File"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#ExtProject"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#Image"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_basket">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#Basket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="uses">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#ExtProject"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="uses">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="recommends">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#ExtProject"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="recommends">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="documented_by">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#Card"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="documented_by">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#File"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="screenshot">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#Image"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_state">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#State"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="filed_under">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#Folder"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="require_permission">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#EPermission"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="recommends">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="tags">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#Tag"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="concerns">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="test_case_of">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#Card"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="mailinglist_of">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#MailingList"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="uses">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="interested_in">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#EUser"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="license_of">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#License"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="version_of">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#Version"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="wf_info_for">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="#TrInfo"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="instance_of">
+ <rdfs:domain rdf:resource="#TestInstance"/>
+ <rdfs:range rdf:resource="#Card"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="for_version">
+ <rdfs:domain rdf:resource="#TestInstance"/>
+ <rdfs:range rdf:resource="#Version"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="generate_bug">
+ <rdfs:domain rdf:resource="#TestInstance"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_basket">
+ <rdfs:domain rdf:resource="#TestInstance"/>
+ <rdfs:range rdf:resource="#Basket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_state">
+ <rdfs:domain rdf:resource="#TestInstance"/>
+ <rdfs:range rdf:resource="#State"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="require_permission">
+ <rdfs:domain rdf:resource="#TestInstance"/>
+ <rdfs:range rdf:resource="#EPermission"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="comments">
+ <rdfs:domain rdf:resource="#TestInstance"/>
+ <rdfs:range rdf:resource="#Comment"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="wf_info_for">
+ <rdfs:domain rdf:resource="#TestInstance"/>
+ <rdfs:range rdf:resource="#TrInfo"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#ExtProject"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#Card"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#File"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#BlogEntry"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#Link"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#Email"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#Image"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="see_also">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_basket">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#Basket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="concerns">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="appeared_in">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#Version"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="done_in">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#Version"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_state">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#State"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="attachment">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#Image"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="attachment">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#File"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="identical_to">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="depends_on">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="require_permission">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#EPermission"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="tags">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#Tag"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="depends_on">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="comments">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#Comment"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="generate_bug">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#TestInstance"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="wf_info_for">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#TrInfo"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="test_case_for">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="#Card"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_basket">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="#Basket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="version_of">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="#Project"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="todo_by">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="#EUser"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="in_state">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="#State"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="conflicts">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="#Version"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="depends_on">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="#Version"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="require_permission">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="#EPermission"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="done_in">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="tags">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="#Tag"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="depends_on">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="#Version"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="for_version">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="#TestInstance"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="wf_info_for">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="#TrInfo"/>
+ </owl:ObjectProperty>
+
+ <owl:ObjectProperty rdf:ID="appeared_in">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="#Ticket"/>
+ </owl:ObjectProperty>
+
+ <!-- datatype property --><owl:DatatypeProperty rdf:ID="title">
+ <rdfs:domain rdf:resource="#Blog"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="description">
+ <rdfs:domain rdf:resource="#Blog"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="creation_date">
+ <rdfs:domain rdf:resource="#Blog"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="modification_date">
+ <rdfs:domain rdf:resource="#Blog"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="title">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="content_format">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="content">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="creation_date">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="modification_date">
+ <rdfs:domain rdf:resource="#BlogEntry"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="title">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="synopsis">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="content_format">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="content">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="wikiid">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="creation_date">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="modification_date">
+ <rdfs:domain rdf:resource="#Card"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="subject">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="date">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="messageid">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="headers">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="creation_date">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="modification_date">
+ <rdfs:domain rdf:resource="#Email"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="title">
+ <rdfs:domain rdf:resource="#EmailThread"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="creation_date">
+ <rdfs:domain rdf:resource="#EmailThread"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="modification_date">
+ <rdfs:domain rdf:resource="#EmailThread"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="name">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="description_format">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="description">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="url">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="creation_date">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="modification_date">
+ <rdfs:domain rdf:resource="#ExtProject"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="data">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="xsd:byte"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="data_format">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="data_encoding">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="name">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="description_format">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="description">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="creation_date">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="modification_date">
+ <rdfs:domain rdf:resource="#File"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="data">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="xsd:byte"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="data_format">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="data_encoding">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="name">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="description_format">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="description">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="creation_date">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="modification_date">
+ <rdfs:domain rdf:resource="#Image"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="name">
+ <rdfs:domain rdf:resource="#License"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="shortdesc">
+ <rdfs:domain rdf:resource="#License"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="longdesc_format">
+ <rdfs:domain rdf:resource="#License"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="longdesc">
+ <rdfs:domain rdf:resource="#License"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="url">
+ <rdfs:domain rdf:resource="#License"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="creation_date">
+ <rdfs:domain rdf:resource="#License"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="modification_date">
+ <rdfs:domain rdf:resource="#License"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="title">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="url">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="embed">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="xsd:boolean"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="description_format">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="description">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="creation_date">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="modification_date">
+ <rdfs:domain rdf:resource="#Link"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="name">
+ <rdfs:domain rdf:resource="#MailingList"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="mlid">
+ <rdfs:domain rdf:resource="#MailingList"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="description_format">
+ <rdfs:domain rdf:resource="#MailingList"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="description">
+ <rdfs:domain rdf:resource="#MailingList"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="archive">
+ <rdfs:domain rdf:resource="#MailingList"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="homepage">
+ <rdfs:domain rdf:resource="#MailingList"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="creation_date">
+ <rdfs:domain rdf:resource="#MailingList"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="modification_date">
+ <rdfs:domain rdf:resource="#MailingList"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="name">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="summary">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="url">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="vcsurl">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="reporturl">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="downloadurl">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="debian_source_package">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="description_format">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="description">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="creation_date">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="modification_date">
+ <rdfs:domain rdf:resource="#Project"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="name">
+ <rdfs:domain rdf:resource="#TestInstance"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="creation_date">
+ <rdfs:domain rdf:resource="#TestInstance"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="modification_date">
+ <rdfs:domain rdf:resource="#TestInstance"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="title">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="type">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="priority">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="load">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="xsd:float"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="load_left">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="xsd:float"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="debian_bug_number">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="xsd:int"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="description_format">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="description">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="creation_date">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="modification_date">
+ <rdfs:domain rdf:resource="#Ticket"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="num">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="description_format">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="description">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="xsd:string"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="starting_date">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="xsd:date"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="prevision_date">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="xsd:date"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="publication_date">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="xsd:date"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="creation_date">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty><owl:DatatypeProperty rdf:ID="modification_date">
+ <rdfs:domain rdf:resource="#Version"/>
+ <rdfs:range rdf:resource="xsd:dateTime"/>
+ </owl:DatatypeProperty> </owl:Ontology></rdf:RDF> ''')
+ doc = etree.parse(valid)
+ owlschema.validate(doc)
+
+if __name__ == '__main__':
+ unittest_main()
+
--- a/web/test/unittest_viewselector.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/test/unittest_viewselector.py Wed Jun 03 19:42:23 2009 +0200
@@ -1,6 +1,5 @@
# -*- coding: iso-8859-1 -*-
"""XXX rename, split, reorganize this
-
"""
import os.path as osp
@@ -10,16 +9,17 @@
from cubicweb import CW_SOFTWARE_ROOT as BASE, Binary
-from cubicweb.common.selectors import in_group_selector
+from cubicweb.common.selectors import match_user_group
from cubicweb.web._exceptions import NoSelectableObject
from cubicweb.web.action import Action
from cubicweb.web.views import (baseviews, tableview, baseforms, calendar,
- management, embedding, actions, startup,
- euser, schemaentities, xbel, vcard,
- idownloadable, wdoc, debug)
+ management, embedding, actions, startup,
+ euser, schemaentities, xbel, vcard,
+ treeview, idownloadable, wdoc, debug)
from cubicweb.entities.lib import Card
from cubicweb.interfaces import IMileStone
+from cubicweb.web.views import owl
USERACTIONS = [('myprefs', actions.UserPreferencesAction),
('myinfos', actions.UserInfoAction),
@@ -75,6 +75,7 @@
('index', startup.IndexView),
('info', management.ProcessInformationView),
('manage', startup.ManageView),
+ ('owl', owl.OWLView),
('schema', startup.SchemaView),
('systemepropertiesform', management.SystemEpropertiesForm)])
# no entity but etype
@@ -94,14 +95,18 @@
[('csvexport', baseviews.CSVRsetView),
('ecsvexport', baseviews.CSVEntityView),
('editable-table', tableview.EditableTableView),
+ ('filetree', treeview.FileTreeView),
('list', baseviews.ListView),
('oneline', baseviews.OneLineView),
+ ('owlabox', owl.OWLABOXView),
('primary', baseviews.PrimaryView),
+ ('rsetxml', baseviews.XMLRsetView),
('rss', baseviews.RssView),
('secondary', baseviews.SecondaryView),
('security', management.SecurityManagementView),
('table', tableview.TableView),
('text', baseviews.TextView),
+ ('treeview', treeview.TreeView),
('xbel', xbel.XbelView),
('xml', baseviews.XmlView),
])
@@ -111,14 +116,18 @@
[('csvexport', baseviews.CSVRsetView),
('ecsvexport', baseviews.CSVEntityView),
('editable-table', tableview.EditableTableView),
+ ('filetree', treeview.FileTreeView),
('list', baseviews.ListView),
('oneline', baseviews.OneLineView),
+ ('owlabox', owl.OWLABOXView),
('primary', baseviews.PrimaryView),
+ ('rsetxml', baseviews.XMLRsetView),
('rss', baseviews.RssView),
('secondary', baseviews.SecondaryView),
('security', management.SecurityManagementView),
('table', tableview.TableView),
('text', baseviews.TextView),
+ ('treeview', treeview.TreeView),
('xbel', xbel.XbelView),
('xml', baseviews.XmlView),
])
@@ -128,14 +137,18 @@
[('csvexport', baseviews.CSVRsetView),
('ecsvexport', baseviews.CSVEntityView),
('editable-table', tableview.EditableTableView),
+ ('filetree', treeview.FileTreeView),
('list', baseviews.ListView),
('oneline', baseviews.OneLineView),
+ ('owlabox', owl.OWLABOXView),
('primary', baseviews.PrimaryView),
+ ('rsetxml', baseviews.XMLRsetView),
('rss', baseviews.RssView),
('secondary', baseviews.SecondaryView),
('security', management.SecurityManagementView),
('table', tableview.TableView),
('text', baseviews.TextView),
+ ('treeview', treeview.TreeView),
('xbel', xbel.XbelView),
('xml', baseviews.XmlView),
])
@@ -144,6 +157,7 @@
self.assertListEqual(self.pviews(req, rset),
[('csvexport', baseviews.CSVRsetView),
('editable-table', tableview.EditableTableView),
+ ('rsetxml', baseviews.XMLRsetView),
('table', tableview.TableView),
])
# list of euser entities
@@ -152,14 +166,19 @@
[('csvexport', baseviews.CSVRsetView),
('ecsvexport', baseviews.CSVEntityView),
('editable-table', tableview.EditableTableView),
+ ('filetree', treeview.FileTreeView),
+ ('foaf', euser.FoafView),
('list', baseviews.ListView),
('oneline', baseviews.OneLineView),
+ ('owlabox', owl.OWLABOXView),
('primary', euser.EUserPrimaryView),
+ ('rsetxml', baseviews.XMLRsetView),
('rss', baseviews.RssView),
('secondary', baseviews.SecondaryView),
('security', management.SecurityManagementView),
('table', tableview.TableView),
('text', baseviews.TextView),
+ ('treeview', treeview.TreeView),
('vcard', vcard.VCardEUserView),
('xbel', xbel.XbelView),
('xml', baseviews.XmlView),
@@ -387,12 +406,12 @@
- def test_owners_in_group_selector(self):
- """tests usage of 'owners' group with in_group_selector"""
+ def test_owners_match_user_group(self):
+ """tests usage of 'owners' group with match_user_group"""
class SomeAction(Action):
id = 'yo'
category = 'foo'
- __selectors__ = (in_group_selector,)
+ __selectors__ = (match_user_group,)
require_groups = ('owners', )
self.vreg.register_vobject_class(SomeAction)
self.failUnless(SomeAction in self.vreg['actions']['yo'], self.vreg['actions'])
--- a/web/views/actions.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/actions.py Wed Jun 03 19:42:23 2009 +0200
@@ -6,11 +6,12 @@
"""
__docformat__ = "restructuredtext en"
-from cubicweb import UnknownEid
-from cubicweb.common.selectors import *
+from cubicweb.common.selectors import (searchstate_accept, match_user_group, yes,
+ one_line_rset, two_lines_rset, one_etype_rset,
+ authenticated_user,
+ match_search_state, chainfirst, chainall)
-from cubicweb.web.action import (Action, EntityAction, LinkToEntityAction,
- LinkToEntityAction2)
+from cubicweb.web.action import Action, EntityAction, LinkToEntityAction
from cubicweb.web.views import linksearch_select_url, linksearch_match
from cubicweb.web.views.baseviews import vid_from_rset
@@ -55,7 +56,7 @@
class ViewAction(Action):
category = 'mainactions'
- __selectors__ = (in_group_selector, searchstate_accept)
+ __selectors__ = (match_user_group, searchstate_accept)
require_groups = ('users', 'managers')
order = 0
@@ -110,7 +111,7 @@
class MultipleEditAction(EntityAction):
category = 'mainactions'
- __selectors__ = (two_lines_rset, oneetyperset_selector,
+ __selectors__ = (two_lines_rset, one_etype_rset,
searchstate_accept)
schema_action = 'update'
order = 10
@@ -198,7 +199,7 @@
return 0
__selectors__ = (match_search_state,
chainfirst(etype_rset_selector,
- chainall(two_lines_rset, oneetyperset_selector,
+ chainall(two_lines_rset, one_etype_rset,
has_add_perm_selector)))
@property
@@ -219,7 +220,7 @@
class UserPreferencesAction(Action):
category = 'useractions'
- __selectors__ = not_anonymous_selector,
+ __selectors__ = authenticated_user,
order = 10
id = 'myprefs'
@@ -231,7 +232,7 @@
class UserInfoAction(Action):
category = 'useractions'
- __selectors__ = not_anonymous_selector,
+ __selectors__ = authenticated_user,
order = 20
id = 'myinfos'
@@ -243,7 +244,7 @@
class LogoutAction(Action):
category = 'useractions'
- __selectors__ = not_anonymous_selector,
+ __selectors__ = authenticated_user,
order = 30
id = 'logout'
@@ -258,7 +259,7 @@
class ManagersAction(Action):
category = 'siteactions'
__abstract__ = True
- __selectors__ = in_group_selector,
+ __selectors__ = match_user_group,
require_groups = ('managers',)
def url(self):
@@ -301,7 +302,7 @@
return self.rset.get_entity(self.row or 0, self.col or 0).actual_url()
class UserPreferencesEntityAction(EntityAction):
- __selectors__ = EntityAction.__selectors__ + (one_line_rset, in_group_selector,)
+ __selectors__ = EntityAction.__selectors__ + (one_line_rset, match_user_group,)
require_groups = ('owners', 'managers')
category = 'mainactions'
accepts = ('EUser',)
--- a/web/views/ajaxedit.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/ajaxedit.py Wed Jun 03 19:42:23 2009 +0200
@@ -6,8 +6,8 @@
"""
__docformat__ = "restructuredtext en"
-from cubicweb.common.selectors import (chainfirst, req_form_params_selector,
- kwargs_selector)
+from cubicweb.common.selectors import (chainfirst, match_form_params,
+ match_kwargs)
from cubicweb.web.box import EditRelationBoxTemplate
class AddRelationView(EditRelationBoxTemplate):
@@ -18,7 +18,7 @@
class attributes.
"""
__registry__ = 'views'
- __selectors__ = (chainfirst(req_form_params_selector, kwargs_selector),)
+ __selectors__ = (chainfirst(match_form_params, match_kwargs),)
property_defs = {} # don't want to inherit this from Box
id = 'xaddrelation'
expected_kwargs = form_params = ('rtype', 'target')
--- a/web/views/basecomponents.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/basecomponents.py Wed Jun 03 19:42:23 2009 +0200
@@ -14,10 +14,10 @@
from cubicweb import Unauthorized
from cubicweb.common.uilib import html_escape, toggle_action
-from cubicweb.common.selectors import yes, nfentity_selector, one_line_rset
+from cubicweb.common.selectors import yes, non_final_entity, one_line_rset
from cubicweb.schema import display_name
-from cubicweb.common.selectors import (chainfirst, multitype_selector,
- req_form_params_selector)
+from cubicweb.common.selectors import (chainfirst, two_etypes_rset,
+ match_form_params)
from cubicweb.web.htmlwidgets import MenuWidget, PopupBoxMenu, BoxSeparator, BoxLink
from cubicweb.web.component import (VComponent, SingletonVComponent, EntityVComponent,
@@ -44,11 +44,11 @@
<form action="%s">
<fieldset>
<input type="text" id="rql" name="rql" value="%s" title="%s" tabindex="%s" accesskey="q" class="searchField" />
-<input type="submit" value="%s" class="searchButton" tabindex="%s" />
+<input type="submit" value="" class="rqlsubmit" tabindex="%s" />
</fieldset>
''' % (not self.propval('visible') and 'hidden' or '',
self.build_url('view'), html_escape(rql), req._('full text or RQL query'), req.next_tabindex(),
- req._('search'), req.next_tabindex()))
+ req.next_tabindex()))
if self.req.search_state[0] != 'normal':
self.w(u'<input type="hidden" name="__mode" value="%s"/>'
% ':'.join(req.search_state[1]))
@@ -138,9 +138,9 @@
target = 'subject'
title = _('Workflow history')
- def call(self, view=None):
+ def cell_call(self, row, col, view=None):
_ = self.req._
- eid = self.rset[0][0]
+ eid = self.rset[row][col]
sel = 'Any FS,TS,WF,D'
rql = ' ORDERBY D DESC WHERE WF wf_info_for X,'\
'WF from_state FS, WF to_state TS, WF comment C,'\
@@ -191,7 +191,7 @@
to be able to filter accordingly.
"""
id = 'etypenavigation'
- __select__ = classmethod(chainfirst(multitype_selector, req_form_params_selector))
+ __select__ = classmethod(chainfirst(two_etypes_rset, match_form_params))
form_params = ('__restrtype', '__restrtypes', '__restrrql')
visible = False # disabled by default
@@ -238,14 +238,14 @@
class RSSFeedURL(VComponent):
id = 'rss_feed_url'
- __selectors__ = (nfentity_selector,)
+ __selectors__ = (non_final_entity,)
def feed_url(self):
return self.build_url(rql=self.limited_rql(), vid='rss')
class RSSEntityFeedURL(VComponent):
id = 'rss_feed_url'
- __selectors__ = (nfentity_selector, one_line_rset)
+ __selectors__ = (non_final_entity, one_line_rset)
def feed_url(self):
return self.entity(0, 0).rss_feed_url()
--- a/web/views/basecontrollers.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/basecontrollers.py Wed Jun 03 19:42:23 2009 +0200
@@ -60,7 +60,6 @@
def publish(self, rset=None):
"""publish a request, returning an encoded string"""
- self.req.update_search_state()
template = self.req.property_value('ui.main-template')
if template not in self.vreg.registry('templates') :
template = self.template
@@ -235,7 +234,7 @@
stream.write(u'<div id="pageContent">')
vtitle = self.req.form.get('vtitle')
if vtitle:
- w(u'<h1 class="vtitle">%s</h1>\n' % vtitle)
+ stream.write(u'<h1 class="vtitle">%s</h1>\n' % vtitle)
view.pagination(req, rset, view.w, not view.need_navigation)
if divid == 'pageContent':
stream.write(u'<div id="contentmain">')
@@ -453,7 +452,14 @@
# link the new entity to the main entity
rql = 'SET F %(rel)s T WHERE F eid %(eid_to)s, T eid %(eid_from)s' % {'rel' : rel, 'eid_to' : eid_to, 'eid_from' : eid_from}
return eid_from
-
+
+ def js_set_cookie(self, cookiename, cookievalue):
+ # XXX we should consider jQuery.Cookie
+ cookiename, cookievalue = str(cookiename), str(cookievalue)
+ cookies = self.req.get_cookie()
+ cookies[cookiename] = cookievalue
+ self.req.set_cookie(cookies, cookiename)
+
class SendMailController(Controller):
id = 'sendmail'
require_groups = ('managers', 'users')
--- a/web/views/baseforms.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/baseforms.py Wed Jun 03 19:42:23 2009 +0200
@@ -2,7 +2,7 @@
or a list of entities of the same type
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -17,9 +17,9 @@
from cubicweb.interfaces import IWorkflowable
from cubicweb.common.utils import make_uid
from cubicweb.common.uilib import cut
-from cubicweb.common.selectors import (etype_form_selector, kwargs_selector,
- one_line_rset, interface_selector,
- req_form_params_selector, accept_selector)
+from cubicweb.common.selectors import (accept_etype, match_kwargs,
+ one_line_rset, implement_interface,
+ match_form_params, accept)
from cubicweb.common.view import EntityView
from cubicweb.web import INTERNAL_FIELD_VALUE, stdmsgs, eid_param
from cubicweb.web.controller import NAV_FORM_PARAMETERS
@@ -33,6 +33,9 @@
title = _('delete')
domid = 'deleteconf'
onsubmit = None
+ # don't use navigation, all entities asked to be deleted should be displayed
+ # else we will only delete the displayed page
+ need_navigation = False
def call(self):
"""ask for confirmation before real deletion"""
@@ -87,7 +90,7 @@
id = 'statuschange'
title = _('status change')
- __selectors__ = (interface_selector, req_form_params_selector)
+ __selectors__ = (implement_interface, match_form_params)
accepts_interfaces = (IWorkflowable,)
form_params = ('treid',)
@@ -150,7 +153,7 @@
class ClickAndEditForm(EntityForm):
id = 'reledit'
- __selectors__ = (kwargs_selector, )
+ __selectors__ = (match_kwargs, )
expected_kwargs = ('rtype',)
#FIXME editableField class could be toggleable from userprefs
@@ -216,7 +219,7 @@
dynamic default values such as the 'tomorrow' date or the user's login
being connected
"""
- __selectors__ = (one_line_rset, accept_selector)
+ __selectors__ = (one_line_rset, accept)
id = 'edition'
title = _('edition')
@@ -392,17 +395,20 @@
if rschema != 'eid']
def relations_form(self, entity, kwargs):
+ srels_by_cat = entity.srelations_by_category(('generic', 'metadata'), 'add')
+ if not srels_by_cat:
+ return u''
req = self.req
_ = self.req._
label = u'%s :' % _('This %s' % entity.e_schema).capitalize()
eid = entity.eid
html = []
- pendings = list(self.restore_pending_inserts(entity))
w = html.append
w(u'<fieldset class="subentity">')
w(u'<legend class="iformTitle">%s</legend>' % label)
w(u'<table id="relatedEntities">')
for row in self.relations_table(entity):
+ # already linked entities
if row[2]:
w(u'<tr><th class="labelCol">%s</th>' % row[0].display_name(req, row[1]))
w(u'<td>')
@@ -415,10 +421,12 @@
w(u'</ul>')
w(u'</td>')
w(u'</tr>')
+ pendings = list(self.restore_pending_inserts(entity))
if not pendings:
w(u'<tr><th> </th><td> </td></tr>')
else:
for row in pendings:
+ # soon to be linked to entities
w(u'<tr id="tr%s">' % row[1])
w(u'<th>%s</th>' % row[3])
w(u'<td>')
@@ -434,7 +442,8 @@
w(u'<select id="relationSelector_%s" tabindex="%s" onchange="javascript:showMatchingSelect(this.options[this.selectedIndex].value,%s);">'
% (eid, req.next_tabindex(), html_escape(dumps(eid))))
w(u'<option value="">%s</option>' % _('select a relation'))
- for i18nrtype, rschema, target in entity.srelations_by_category(('generic', 'metadata'), 'add'):
+ for i18nrtype, rschema, target in srels_by_cat:
+ # more entities to link to
w(u'<option value="%s_%s">%s</option>' % (rschema, target, i18nrtype))
w(u'</select>')
w(u'</th>')
@@ -517,7 +526,7 @@
class CreationForm(EditionForm):
- __selectors__ = (etype_form_selector, )
+ __selectors__ = (accept_etype, )
id = 'creation'
title = _('creation')
@@ -630,7 +639,7 @@
class InlineEntityCreationForm(InlineFormMixIn, CreationForm):
id = 'inline-creation'
- __selectors__ = (kwargs_selector, etype_form_selector)
+ __selectors__ = (match_kwargs, accept_etype)
expected_kwargs = ('ptype', 'peid', 'rtype')
EDITION_BODY = u'''\
@@ -669,7 +678,7 @@
class InlineEntityEditionForm(InlineFormMixIn, EditionForm):
id = 'inline-edition'
- __selectors__ = (accept_selector, kwargs_selector)
+ __selectors__ = (accept, match_kwargs)
expected_kwargs = ('ptype', 'peid', 'rtype')
EDITION_BODY = u'''\
@@ -872,7 +881,7 @@
class UnrelatedDivs(EntityView):
id = 'unrelateddivs'
- __selectors__ = (req_form_params_selector,)
+ __selectors__ = (match_form_params,)
form_params = ('relation',)
@property
--- a/web/views/basetemplates.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/basetemplates.py Wed Jun 03 19:42:23 2009 +0200
@@ -2,16 +2,18 @@
"""default templates for CubicWeb web client
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
+
from logilab.mtconverter import html_escape
from cubicweb import NoSelectableObject, ObjectNotFound
from cubicweb.common.view import Template, MainTemplate, NOINDEX, NOFOLLOW
from cubicweb.common.utils import make_uid
+from cubicweb.common.utils import UStringIO
from cubicweb.web.views.baseviews import vid_from_rset
@@ -56,8 +58,9 @@
title = 'logged out'
def content(self, w):
+ # FIXME Deprecated code ?
msg = self.req._('you have been logged out')
- w(u'<h1 class="noborder">%s</h1>\n' % msg)
+ w(u'<h2>%s</h2>\n' % msg)
if self.config['anonymous-user']:
indexurl = self.build_url('view', vid='index', __message=msg)
w(u'<p><a href="%s">%s</a><p>' % (
@@ -162,7 +165,10 @@
self.req, self.rset)
if etypefilter and etypefilter.propval('visible'):
etypefilter.dispatch(w=self.w)
- self.pagination(self.req, self.rset, self.w, not (view and view.need_navigation))
+ self.nav_html = UStringIO()
+ self.pagination(self.req, self.rset, self.nav_html.write,
+ not (view and view.need_navigation))
+ self.w(_(self.nav_html.getvalue()))
self.w(u'<div id="contentmain">\n')
def template_html_header(self, content_type, page_title, additional_headers=()):
@@ -194,10 +200,11 @@
w(u'<div id="pageContent">\n')
vtitle = self.req.form.get('vtitle')
if vtitle:
- w(u'<h1 class="vtitle">%s</h1>\n' % vtitle)
+ w(u'<h1 class="vtitle">%s</h1>\n' % html_escape(vtitle))
def template_footer(self, view=None):
self.w(u'</div>\n') # close id=contentmain
+ self.w(_(self.nav_html.getvalue()))
self.w(u'</div>\n') # closes id=pageContent
self.content_footer(view)
self.w(u'</td>\n')
@@ -288,7 +295,7 @@
w(u'<div id="pageContent">\n')
vtitle = self.req.form.get('vtitle')
if vtitle:
- w(u'<h1 class="vtitle">%s</h1>' % (vtitle))
+ w(u'<h1 class="vtitle">%s</h1>' % html_escape(vtitle))
def topleft_header(self):
self.w(u'<table id="header"><tr>\n')
@@ -418,7 +425,7 @@
req._(ChangeLogView.title).lower()))
self.w(u'<a href="%s">%s</a> | ' % (req.build_url('doc/about'),
req._('about this site')))
- self.w(u'© 2001-2008 <a href="http://www.logilab.fr">Logilab S.A.</a>')
+ self.w(u'© 2001-2009 <a href="http://www.logilab.fr">Logilab S.A.</a>')
self.w(u'</div>')
--- a/web/views/baseviews.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/baseviews.py Wed Jun 03 19:42:23 2009 +0200
@@ -8,24 +8,25 @@
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
+from warnings import warn
from time import timezone
from rql import nodes
from logilab.common.decorators import cached
-from logilab.mtconverter import html_escape, TransformError
+from logilab.mtconverter import TransformError, html_escape, xml_escape
from cubicweb import Unauthorized, NoSelectableObject, typed_eid
-from cubicweb.common.selectors import (yes, nonempty_rset, accept_selector,
+from cubicweb.common.selectors import (yes, nonempty_rset, accept,
one_line_rset, match_search_state,
- req_form_params_selector, accept_rset_selector)
+ match_form_params, accept_rset)
from cubicweb.common.uilib import (cut, printable_value, UnicodeCSVWriter,
- ajax_replace_url, rql_for_eid)
+ ajax_replace_url, rql_for_eid, simple_sgml_tag)
from cubicweb.common.view import EntityView, AnyRsetView, EmptyRsetView
from cubicweb.web.httpcache import MaxAgeHTTPCacheManager
from cubicweb.web.views import vid_from_rset, linksearch_select_url, linksearch_match
@@ -56,14 +57,14 @@
"""
id = 'final'
- def cell_call(self, row, col, props=None, displaytime=False):
+ def cell_call(self, row, col, props=None, displaytime=False, format='text/html'):
etype = self.rset.description[row][col]
value = self.rset.rows[row][col]
if etype == 'String':
entity, rtype = self.rset.related_entity(row, col)
if entity is not None:
# yes !
- self.w(entity.printable_value(rtype, value))
+ self.w(entity.printable_value(rtype, value, format=format))
return
if etype in ('Time', 'Interval'):
_ = self.req._
@@ -143,12 +144,7 @@
self.w(u'<div class="mainInfo">')
self.render_entity_attributes(entity, siderelations)
self.w(u'</div>')
- self.w(u'<div class="navcontenttop">')
- for comp in self.vreg.possible_vobjects('contentnavigation',
- self.req, self.rset,
- view=self, context='navcontenttop'):
- comp.dispatch(w=self.w, view=self)
- self.w(u'</div>')
+ self.content_navigation_components('navcontenttop')
if self.main_related_section:
self.render_entity_relations(entity, siderelations)
self.w(u'</td>')
@@ -158,13 +154,21 @@
self.w(u'</td>')
self.w(u'</tr>')
self.w(u'</table>')
- self.w(u'<div class="navcontentbottom">')
+ self.content_navigation_components('navcontentbottom')
+
+ def content_navigation_components(self, context):
+ self.w(u'<div class="%s">' % context)
for comp in self.vreg.possible_vobjects('contentnavigation',
- self.req, self.rset,
- view=self, context='navcontentbottom'):
- comp.dispatch(w=self.w, view=self)
+ self.req, self.rset, row=self.row,
+ view=self, context=context):
+ try:
+ comp.dispatch(w=self.w, row=self.row, view=self)
+ except NotImplementedError:
+ warn('component %s doesnt implement cell_call, please update'
+ % comp.__class__, DeprecationWarning)
+ comp.dispatch(w=self.w, view=self)
self.w(u'</div>')
-
+
def iter_attributes(self, entity):
for rschema, targetschema in entity.e_schema.attribute_definitions():
attr = rschema.type
@@ -251,11 +255,11 @@
# continue
self._render_related_entities(entity, *relatedinfos)
self.w(u'</div>')
- for box in self.vreg.possible_vobjects('boxes', self.req, entity.rset,
- col=entity.col, row=entity.row,
- view=self, context='incontext'):
+ for box in self.vreg.possible_vobjects('boxes', self.req, self.rset,
+ row=self.row, view=self,
+ context='incontext'):
try:
- box.dispatch(w=self.w, col=entity.col, row=entity.row)
+ box.dispatch(w=self.w, row=self.row)
except NotImplementedError:
# much probably a context insensitive box, which only implements
# .call() and not cell_call()
@@ -350,10 +354,10 @@
self.w(u'</a>')
class TextView(EntityView):
- """the simplest text view for an entity
- """
+ """the simplest text view for an entity"""
id = 'text'
title = _('text')
+ content_type = 'text/plain'
accepts = 'Any',
def call(self, **kwargs):
"""the view is called for an entire result set, by default loop
@@ -571,8 +575,7 @@
self.wview(self.item_vid, self.rset, row=row, col=col)
def call(self):
- """display a list of entities by calling their <item_vid> view
- """
+ """display a list of entities by calling their <item_vid> view"""
self.w(u'<?xml version="1.0" encoding="%s"?>\n' % self.req.encoding)
self.w(u'<%s size="%s">\n' % (self.xml_root, len(self.rset)))
for i in xrange(self.rset.rowcount):
@@ -599,7 +602,7 @@
from base64 import b64encode
value = '<![CDATA[%s]]>' % b64encode(value.getvalue())
elif isinstance(value, basestring):
- value = value.replace('&', '&').replace('<', '<')
+ value = xml_escape(value)
self.w(u' <%s>%s</%s>\n' % (attr, value, attr))
self.w(u'</%s>\n' % (entity.e_schema))
@@ -619,21 +622,25 @@
eschema = self.schema.eschema
labels = self.columns_labels(False)
w(u'<?xml version="1.0" encoding="%s"?>\n' % self.req.encoding)
- w(u'<%s>\n' % self.xml_root)
+ w(u'<%s query="%s">\n' % (self.xml_root, html_escape(rset.printable_rql())))
for rowindex, row in enumerate(self.rset):
w(u' <row>\n')
for colindex, val in enumerate(row):
etype = descr[rowindex][colindex]
tag = labels[colindex]
+ attrs = {}
+ if '(' in tag:
+ attrs['expr'] = tag
+ tag = 'funccall'
if val is not None and not eschema(etype).is_final():
+ attrs['eid'] = val
# csvrow.append(val) # val is eid in that case
- content = self.view('textincontext', rset,
- row=rowindex, col=colindex)
- w(u' <%s eid="%s">%s</%s>\n' % (tag, val, html_escape(content), tag))
+ val = self.view('textincontext', rset,
+ row=rowindex, col=colindex)
else:
- content = self.view('final', rset, displaytime=True,
- row=rowindex, col=colindex)
- w(u' <%s>%s</%s>\n' % (tag, html_escape(content), tag))
+ val = self.view('final', rset, displaytime=True,
+ row=rowindex, col=colindex, format='text/plain')
+ w(simple_sgml_tag(tag, val, **attrs))
w(u' </row>\n')
w(u'</%s>\n' % self.xml_root)
@@ -740,7 +747,8 @@
content = self.view('textincontext', rset,
row=rowindex, col=colindex)
else:
- content = self.view('final', rset, displaytime=True,
+ content = self.view('final', rset,
+ displaytime=True, format='text/plain',
row=rowindex, col=colindex)
csvrow.append(content)
writer.writerow(csvrow)
@@ -785,7 +793,7 @@
"""
id = 'search-associate'
title = _('search for association')
- __selectors__ = (one_line_rset, match_search_state, accept_selector)
+ __selectors__ = (one_line_rset, match_search_state, accept)
accepts = ('Any',)
search_states = ('linksearch',)
@@ -793,7 +801,7 @@
rset, vid, divid, paginate = self.filter_box_context_info()
self.w(u'<div id="%s">' % divid)
self.pagination(self.req, rset, w=self.w)
- self.wview(vid, rset)
+ self.wview(vid, rset, 'noresult')
self.w(u'</div>')
@cached
@@ -842,7 +850,7 @@
"""
id = 'editrelation'
- __selectors__ = (req_form_params_selector,)
+ __selectors__ = (match_form_params,)
form_params = ('rtype',)
# TODO: inlineview, multiple edit, (widget view ?)
@@ -855,13 +863,8 @@
assert rtype is not None, "rtype is mandatory for 'edirelation' view"
targettype = self.req.form.get('targettype', targettype)
role = self.req.form.get('role', role)
- mode = entity.rtags.get_mode(rtype, targettype, role)
- if mode == 'create':
- return
category = entity.rtags.get_category(rtype, targettype, role)
- if category in ('generated', 'metadata'):
- return
- elif category in ('primary', 'secondary'):
+ if category in ('primary', 'secondary') or self.schema.rschema(rtype).is_final():
if hasattr(entity, '%s_format' % rtype):
formatwdg = entity.get_widget('%s_format' % rtype, role)
self.w(formatwdg.edit_render(entity))
@@ -872,10 +875,8 @@
self.w(u'%s %s %s' %
(wdg.render_error(entity), wdg.edit_render(entity),
wdg.render_help(entity),))
- elif category == 'generic':
+ else:
self._render_generic_relation(entity, rtype, role)
- else:
- self.error("oops, wrong category %s", category)
def _render_generic_relation(self, entity, relname, role):
text = self.req.__('add %s %s %s' % (entity.e_schema, relname, role))
--- a/web/views/bookmark.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/bookmark.py Wed Jun 03 19:42:23 2009 +0200
@@ -68,9 +68,9 @@
dlink = u'[<a href="javascript:removeBookmark(%s)" title="%s">-</a>]' % (
bookmark.eid, _('delete this bookmark'))
label = '%s %s' % (dlink, label)
- box.append(RawBoxItem(label, liclass=u'invisible'))
+ box.append(RawBoxItem(label))
if eschema.has_perm(req, 'add') and rschema.has_perm(req, 'add', toeid=ueid):
- boxmenu = BoxMenu(req._('manage bookmarks'), liclass=u'invisible')
+ boxmenu = BoxMenu(req._('manage bookmarks'))
linkto = 'bookmarked_by:%s:subject' % ueid
# use a relative path so that we can move the application without
# loosing bookmarks
--- a/web/views/boxes.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/boxes.py Wed Jun 03 19:42:23 2009 +0200
@@ -10,14 +10,14 @@
* startup views box
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
from logilab.mtconverter import html_escape
-from cubicweb.common.selectors import (rset_selector, appobject_selectable)
+from cubicweb.common.selectors import any_rset, appobject_selectable
from cubicweb.web.htmlwidgets import BoxWidget, BoxMenu, BoxHtml, RawBoxItem
from cubicweb.web.box import BoxTemplate, ExtResourcesBoxTemplate
@@ -29,7 +29,7 @@
box with all actions impacting the entity displayed: edit, copy, delete
change state, add related entities
"""
- __selectors__ = (rset_selector,) + BoxTemplate.__selectors__
+ __selectors__ = (any_rset,) + BoxTemplate.__selectors__
id = 'edit_box'
title = _('actions')
order = 2
@@ -143,7 +143,7 @@
<input type="hidden" name="__fromsearchbox" value="1" />
<input type="hidden" name="subvid" value="tsearch" />
</td><td>
-<input tabindex="%s" type="submit" id="rqlboxsubmit" value="" />
+<input tabindex="%s" type="submit" id="rqlboxsubmit" class="rqlsubmit" value="" />
</td></tr></table>
</form>"""
@@ -175,17 +175,16 @@
def call(self, **kwargs):
box = BoxWidget(self.req._(self.title), self.id)
- actions = [v for v in self.vreg.possible_views(self.req, self.rset)
- if v.category != 'startupview']
- for category, actions in self.sort_actions(actions):
+ views = [v for v in self.vreg.possible_views(self.req, self.rset)
+ if v.category != 'startupview']
+ for category, views in self.sort_actions(views):
menu = BoxMenu(category)
- for action in actions:
- menu.append(self.box_action(action))
+ for view in views:
+ menu.append(self.box_action(view))
box.append(menu)
if not box.is_empty():
box.render(self.w)
-
class RSSIconBox(ExtResourcesBoxTemplate):
"""just display the RSS icon on uniform result set"""
@@ -200,25 +199,8 @@
urlgetter = self.vreg.select_component('rss_feed_url', self.req, self.rset)
url = urlgetter.feed_url()
rss = self.req.external_resource('RSS_LOGO')
- self.w(u'<a href="%s"><img src="%s" border="0" /></a>\n' % (html_escape(url), rss))
-
+ self.w(u'<a href="%s"><img src="%s" alt="rss"/></a>\n' % (html_escape(url), rss))
-## warning("schemabox ne marche plus pour le moment")
-## class SchemaBox(BoxTemplate):
-## """display a box containing link to list of entities by type"""
-## id = 'schema_box'
-## visible = False # disabled by default
-## title = _('entity list')
-## order = 60
-
-## def call(self, **kwargs):
-## box = BoxWidget(self.req._(title), self.id)
-## for etype in self.config.etypes(self.req.user, 'read'):
-## view = self.vreg.select_view('list', self.req, self.etype_rset(etype))
-## box.append(self.mk_action(display_name(self.req, etype, 'plural'),
-## view.url(), etype=etype))
-## if not box.is_empty():
-## box.render(self.w)
class StartupViewsBox(BoxTemplate):
"""display a box containing links to all startup views"""
--- a/web/views/calendar.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/calendar.py Wed Jun 03 19:42:23 2009 +0200
@@ -15,7 +15,7 @@
from cubicweb.interfaces import ICalendarable
from cubicweb.common.utils import date_range
from cubicweb.common.uilib import ajax_replace_url
-from cubicweb.common.selectors import interface_selector
+from cubicweb.common.selectors import implement_interface
from cubicweb.common.registerers import priority_registerer
from cubicweb.common.view import EntityView
@@ -83,7 +83,7 @@
Does apply to ICalendarable compatible entities
"""
__registerer__ = priority_registerer
- __selectors__ = (interface_selector,)
+ __selectors__ = (implement_interface,)
accepts_interfaces = (ICalendarable,)
need_navigation = False
content_type = 'text/calendar'
@@ -114,11 +114,11 @@
Does apply to ICalendarable compatible entities
"""
__registerer__ = priority_registerer
- __selectors__ = (interface_selector,)
+ __selectors__ = (implement_interface,)
accepts_interfaces = (ICalendarable,)
need_navigation = False
title = _('hCalendar')
- templatable = False
+ #templatable = False
id = 'hcal'
def call(self):
@@ -146,7 +146,7 @@
class OneMonthCal(EntityView):
"""At some point, this view will probably replace ampm calendars"""
__registerer__ = priority_registerer
- __selectors__ = (interface_selector, )
+ __selectors__ = (implement_interface, )
accepts_interfaces = (ICalendarable,)
need_navigation = False
id = 'onemonthcal'
@@ -331,7 +331,7 @@
class OneWeekCal(EntityView):
"""At some point, this view will probably replace ampm calendars"""
__registerer__ = priority_registerer
- __selectors__ = (interface_selector, )
+ __selectors__ = (implement_interface, )
accepts_interfaces = (ICalendarable,)
need_navigation = False
id = 'oneweekcal'
--- a/web/views/embedding.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/embedding.py Wed Jun 03 19:42:23 2009 +0200
@@ -18,7 +18,7 @@
from cubicweb.interfaces import IEmbedable
from cubicweb.common.uilib import soup2xhtml
from cubicweb.common.selectors import (one_line_rset, score_entity_selector,
- match_search_state, interface_selector)
+ match_search_state, implement_interface)
from cubicweb.common.view import NOINDEX, NOFOLLOW
from cubicweb.web.controller import Controller
from cubicweb.web.action import Action
@@ -82,7 +82,7 @@
id = 'embed'
controller = 'embed'
__selectors__ = (one_line_rset, match_search_state,
- interface_selector, score_entity_selector)
+ implement_interface, score_entity_selector)
accepts_interfaces = (IEmbedable,)
title = _('embed')
--- a/web/views/euser.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/euser.py Wed Jun 03 19:42:23 2009 +0200
@@ -1,17 +1,18 @@
"""Specific views for users
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
from logilab.common.decorators import cached
+from logilab.mtconverter import html_escape
from cubicweb.schema import display_name
from cubicweb.web import INTERNAL_FIELD_VALUE
from cubicweb.web.form import EntityForm
-from cubicweb.web.views.baseviews import PrimaryView
+from cubicweb.web.views.baseviews import PrimaryView, EntityView
class EUserPrimaryView(PrimaryView):
accepts = ('EUser',)
@@ -31,8 +32,48 @@
return rschema.type in ['interested_in', 'tags',
'todo_by', 'bookmarked_by',
]
+class FoafView(EntityView):
+ id = 'foaf'
+ accepts = ('EUser',)
+ title = _('foaf')
+ templatable = False
+ content_type = 'text/xml'
+ def call(self):
+ self.w('''<?xml version="1.0" encoding="%s"?>
+<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:rdfs="http://www.w3org/2000/01/rdf-schema#"
+ xmlns:foaf="http://xmlns.com/foaf/0.1/"> '''% self.req.encoding)
+ for i in xrange(self.rset.rowcount):
+ self.cell_call(i, 0)
+ self.w(u'</rdf:RDF>\n')
+ def cell_call(self, row, col):
+ entity = self.complete_entity(row, col)
+ self.w(u'''<foaf:PersonalProfileDocument rdf:about="">
+ <foaf:maker rdf:resource="%s"/>
+ <foaf:primaryTopic rdf:resource="%s"/>
+ </foaf:PersonalProfileDocument>''' % (entity.absolute_url(), entity.absolute_url()))
+
+ self.w(u'<foaf:Person rdf:ID="%s">\n' % entity.eid)
+ self.w(u'<foaf:name>%s</foaf:name>\n' % html_escape(entity.dc_long_title()))
+ if entity.surname:
+ self.w(u'<foaf:family_name>%s</foaf:family_name>\n'
+ % html_escape(entity.surname))
+ if entity.firstname:
+ self.w(u'<foaf:givenname>%s</foaf:givenname>\n'
+ % html_escape(entity.firstname))
+ emailaddr = entity.get_email()
+ if emailaddr:
+ self.w(u'<foaf:mbox>%s</foaf:mbox>\n' % html_escape(emailaddr))
+ self.w(u'</foaf:Person>\n')
+
+class FoafUsableView(FoafView):
+ id = 'foaf_usable'
+
+ def call(self):
+ self.cell_call(0, 0)
+
class EditGroups(EntityForm):
"""displays a simple euser / egroups editable table"""
--- a/web/views/facets.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/facets.py Wed Jun 03 19:42:23 2009 +0200
@@ -1,7 +1,7 @@
"""the facets box and some basic facets
:organization: Logilab
-:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -10,9 +10,9 @@
from logilab.mtconverter import html_escape
-from cubicweb.common.selectors import (chainfirst, chainall, nfentity_selector,
- two_lines_rset, contextprop_selector,
- yes, one_has_relation_selector)
+from cubicweb.common.selectors import (chainfirst, chainall, non_final_entity,
+ two_lines_rset, match_context_prop,
+ yes, one_has_relation)
from cubicweb.web.box import BoxTemplate
from cubicweb.web.facet import (AbstractFacet, VocabularyFacet, FacetStringWidget,
RelationFacet, prepare_facets_rqlst, filter_hiddens)
@@ -28,8 +28,8 @@
"""filter results of a query"""
id = 'filter_box'
__selectors__ = (chainfirst(contextview_selector,
- chainall(nfentity_selector, two_lines_rset)),
- contextprop_selector)
+ chainall(non_final_entity, two_lines_rset)),
+ match_context_prop)
context = 'left'
title = _('boxes_filter_box')
visible = True # functionality provided by the search box by default
@@ -153,7 +153,7 @@
class HasTextFacet(AbstractFacet):
- __selectors__ = (one_has_relation_selector, contextprop_selector)
+ __selectors__ = (one_has_relation, match_context_prop)
id = 'has_text-facet'
rtype = 'has_text'
role = 'subject'
--- a/web/views/ibreadcrumbs.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/ibreadcrumbs.py Wed Jun 03 19:42:23 2009 +0200
@@ -9,8 +9,8 @@
from logilab.mtconverter import html_escape
from cubicweb.interfaces import IBreadCrumbs
-from cubicweb.common.selectors import (contextprop_selector, one_line_rset,
- interface_selector)
+from cubicweb.common.selectors import (match_context_prop, one_line_rset,
+ implement_interface)
from cubicweb.common.view import EntityView
from cubicweb.common.uilib import cut
# don't use AnyEntity since this may cause bug with isinstance() due to reloading
@@ -29,7 +29,7 @@
# register msg not generated since no entity implements IPrevNext in cubicweb itself
title = _('contentnavigation_breadcrumbs')
help = _('contentnavigation_breadcrumbs_description')
- __selectors__ = (one_line_rset, contextprop_selector, interface_selector)
+ __selectors__ = (one_line_rset, match_context_prop, implement_interface)
accepts_interfaces = (IBreadCrumbs,)
context = 'navtop'
order = 5
@@ -73,7 +73,7 @@
class BreadCrumbComponent(BreadCrumbEntityVComponent):
__registry__ = 'components'
- __selectors__ = (one_line_rset, interface_selector)
+ __selectors__ = (one_line_rset, implement_interface)
visible = True
--- a/web/views/idownloadable.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/idownloadable.py Wed Jun 03 19:42:23 2009 +0200
@@ -11,7 +11,7 @@
from cubicweb.interfaces import IDownloadable
from cubicweb.common.mttransforms import ENGINE
from cubicweb.common.selectors import (one_line_rset, score_entity_selector,
- interface_selector, contextprop_selector)
+ implement_interface, match_context_prop)
from cubicweb.web.box import EntityBoxTemplate
from cubicweb.web.views import baseviews
@@ -35,7 +35,7 @@
class DownloadBox(EntityBoxTemplate):
id = 'download_box'
- __selectors__ = (one_line_rset, interface_selector, contextprop_selector)
+ __selectors__ = (one_line_rset, implement_interface, match_context_prop)
accepts_interfaces = (IDownloadable,)
order = 10
def cell_call(self, row, col, title=None, label=None, **kwargs):
@@ -48,7 +48,7 @@
of entities providing the necessary interface
"""
id = 'download'
- __selectors__ = (one_line_rset, interface_selector)
+ __selectors__ = (one_line_rset, implement_interface)
accepts_interfaces = (IDownloadable,)
templatable = False
@@ -77,7 +77,7 @@
"""view displaying a link to download the file"""
id = 'downloadlink'
title = None # should not be listed in possible views
- __selectors__ = (interface_selector,)
+ __selectors__ = (implement_interface,)
accepts_interfaces = (IDownloadable,)
@@ -89,7 +89,7 @@
class IDownloadablePrimaryView(baseviews.PrimaryView):
- __selectors__ = (interface_selector,)
+ __selectors__ = (implement_interface,)
#skip_attrs = ('eid', 'data',) # XXX
accepts_interfaces = (IDownloadable,)
@@ -122,7 +122,7 @@
class IDownloadableLineView(baseviews.OneLineView):
- __selectors__ = (interface_selector,)
+ __selectors__ = (implement_interface,)
# don't kick default oneline view
accepts_interfaces = (IDownloadable,)
@@ -138,7 +138,7 @@
class ImageView(baseviews.EntityView):
- __selectors__ = (interface_selector, score_entity_selector)
+ __selectors__ = (implement_interface, score_entity_selector)
id = 'image'
title = _('image')
accepts_interfaces = (IDownloadable,)
--- a/web/views/igeocodable.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/igeocodable.py Wed Jun 03 19:42:23 2009 +0200
@@ -4,7 +4,7 @@
from cubicweb.interfaces import IGeocodable
from cubicweb.common.view import EntityView
-from cubicweb.common.selectors import interface_selector
+from cubicweb.common.selectors import implement_interface
class GeocodingJsonView(EntityView):
id = 'geocoding-json'
@@ -12,10 +12,11 @@
templatable = False
content_type = 'application/json'
- __selectors__ = (interface_selector,)
+ __selectors__ = (implement_interface,)
accepts_interfaces = (IGeocodable,)
-
+
def call(self):
+ zoomlevel = self.req.form.pop('zoomlevel', 8)
extraparams = self.req.form.copy()
extraparams.pop('vid', None)
extraparams.pop('rql', None)
@@ -26,40 +27,41 @@
'longitude': sum(marker['longitude'] for marker in markers) / len(markers),
}
geodata = {
+ 'zoomlevel': int(zoomlevel),
'center': center,
'markers': markers,
}
self.w(simplejson.dumps(geodata))
-
+
def build_marker_data(self, row, extraparams):
entity = self.entity(row, 0)
return {'latitude': entity.latitude, 'longitude': entity.longitude,
'title': entity.dc_long_title(),
#icon defines : (icon._url, icon.size, icon.iconAncho', icon.shadow)
- 'icon': entity.marker_icon() or (self.req.external_resource('GMARKER_ICON'), (20, 34), (4, 34), None),
+ 'icon': entity.marker_icon() or (self.req.external_resource('GMARKER_ICON'), (20, 34), (4, 34), None),
'bubbleUrl': entity.absolute_url(vid='gmap-bubble', __notemplate=1, **extraparams),
}
class GoogleMapBubbleView(EntityView):
id = 'gmap-bubble'
-
- __selectors__ = (interface_selector,)
+
+ __selectors__ = (implement_interface,)
accepts_interfaces = (IGeocodable,)
-
+
def cell_call(self, row, col):
entity = self.entity(row, col)
self.w(u'<div>%s</div>' % entity.view('oneline'))
# FIXME: we should call something like address-view if available
-
+
class GoogleMapsView(EntityView):
id = 'gmap-view'
-
- __selectors__ = (interface_selector,)
+
+ __selectors__ = (implement_interface,)
accepts_interfaces = (IGeocodable,)
need_navigation = False
-
+
def call(self, gmap_key, width=400, height=400, uselabel=True, urlparams=None):
self.req.add_js('http://maps.google.com/maps?file=api&v=2&key=%s' % gmap_key,
localfile=False);
@@ -70,13 +72,13 @@
else:
loadurl = self.build_url(rql=rql, vid='geocoding-json', **urlparams)
self.w(u'<div style="width: %spx; height: %spx;" class="widget gmap" '
- u'cubicweb:wdgtype="GMapWidget" cubicweb:loadtype="auto" '
+ u'cubicweb:wdgtype="GMapWidget" cubicweb:loadtype="auto" '
u'cubicweb:loadurl="%s" cubicweb:uselabel="%s"> </div>' % (width, height, loadurl, uselabel))
-
+
class GoogeMapsLegend(EntityView):
id = 'gmap-legend'
-
+
def call(self):
self.w(u'<ol>')
for rowidx in xrange(len(self.rset)):
--- a/web/views/iprogress.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/iprogress.py Wed Jun 03 19:42:23 2009 +0200
@@ -12,7 +12,7 @@
from cubicweb.interfaces import IProgress, IMileStone
from cubicweb.schema import display_name
from cubicweb.common.view import EntityView
-from cubicweb.common.selectors import interface_selector, accept_selector
+from cubicweb.common.selectors import implement_interface, accept
from cubicweb.web.htmlwidgets import ProgressBarWidget
@@ -35,7 +35,7 @@
id = 'progress_table_view'
title = _('task progression')
- __selectors__ = (accept_selector, interface_selector)
+ __selectors__ = (accept, implement_interface)
accepts_interfaces = (IMileStone,)
@@ -182,7 +182,7 @@
"""displays a progress bar"""
id = 'progressbar'
title = _('progress bar')
- __selectors__ = (accept_selector, interface_selector)
+ __selectors__ = (accept, implement_interface)
accepts_interfaces = (IProgress,)
--- a/web/views/management.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/management.py Wed Jun 03 19:42:23 2009 +0200
@@ -13,17 +13,16 @@
from cubicweb.common.utils import UStringIO
from cubicweb.common.view import AnyRsetView, StartupView, EntityView
-from cubicweb.common.uilib import (html_traceback, rest_traceback, html_escape,
- toggle_link)
+from cubicweb.common.uilib import html_traceback, rest_traceback
from cubicweb.common.selectors import (yes, one_line_rset,
- accept_rset_selector, none_rset,
- chainfirst, chainall)
+ accept_rset, none_rset,
+ chainfirst, chainall)
from cubicweb.web import INTERNAL_FIELD_VALUE, eid_param, stdmsgs
from cubicweb.web.widgets import StaticComboBoxWidget
from cubicweb.web.form import FormMixIn
_ = unicode
-
+
def begin_form(w, entity, redirectvid, redirectpath=None, msg=None):
w(u'<form method="post" action="%s">\n' % entity.req.build_url('edit'))
w(u'<fieldset>\n')
@@ -42,10 +41,10 @@
"""display security information for a given entity"""
id = 'security'
title = _('security')
-
+
def cell_call(self, row, col):
- self.req.add_js('cubicweb.edition.js')
- self.req.add_css('cubicweb.acl.css')
+ self.req.add_js('cubicweb.edition.js')
+ self.req.add_css('cubicweb.acl.css')
entity = self.entity(row, col)
w = self.w
_ = self.req._
@@ -90,7 +89,7 @@
w(u'<td>%s</td>' % u'<br/>'.join(expr.expression for expr in rqlexprs))
w(u'</tr>\n')
w(u'</table>')
-
+
def owned_by_edit_form(self, entity):
self.w('<h3>%s</h3>' % self.req._('ownership'))
begin_form(self.w, entity, 'security', msg= _('ownerships have been changed'))
@@ -169,7 +168,7 @@
wdg = newperm.get_widget('label')
w(u'<td>%s</td>\n' % wdg.edit_render(newperm))
wdg = newperm.get_widget('require_group')
- w(u'<td>%s</td>\n' % wdg.edit_render(newperm))
+ w(u'<td>%s</td>\n' % wdg.edit_render(newperm))
w(u'<td>%s</td></tr>\n' % self.button_ok())
w(u'</table>')
w(u'</fieldset></form>\n')
@@ -178,12 +177,12 @@
return (u'<input class="validateButton" type="submit" name="submit" value="%s"/>'
% self.req._(stdmsgs.BUTTON_OK))
-
+
class ErrorView(AnyRsetView):
"""default view when no result has been found"""
__selectors__ = (yes,)
id = 'error'
-
+
def page_title(self):
"""returns a title according to the result set - used for the
title in the HTML header
@@ -192,11 +191,11 @@
def call(self):
req = self.req.reset_headers()
- _ = req._
+ _ = req._; w = self.w
ex = req.data.get('ex')#_("unable to find exception information"))
excinfo = req.data.get('excinfo')
title = _('an error occured')
- self.w(u'<h2>%s</h2>' % title)
+ w(u'<h2>%s</h2>' % title)
if 'errmsg' in req.data:
ex = req.data['errmsg']
exclass = None
@@ -205,53 +204,53 @@
ex = exc_message(ex, req.encoding)
if excinfo is not None and self.config['print-traceback']:
if exclass is None:
- self.w(u'<div class="tb">%s</div>'
+ w(u'<div class="tb">%s</div>'
% html_escape(ex).replace("\n","<br />"))
else:
- self.w(u'<div class="tb">%s: %s</div>'
+ w(u'<div class="tb">%s: %s</div>'
% (exclass, html_escape(ex).replace("\n","<br />")))
- self.w(u'<hr />')
- self.w(u'<div class="tb">%s</div>' % html_traceback(excinfo, ex, ''))
+ w(u'<hr />')
+ w(u'<div class="tb">%s</div>' % html_traceback(excinfo, ex, ''))
else:
- self.w(u'<div class="tb">%s</div>' % (html_escape(ex).replace("\n","<br />")))
+ w(u'<div class="tb">%s</div>' % (html_escape(ex).replace("\n","<br />")))
# if excinfo is not None, it's probably not a bug
if excinfo is None:
return
vcconf = self.config.vc_config()
- self.w(u"<div>")
+ w(u"<div>")
eversion = vcconf.get('cubicweb', _('no version information'))
# NOTE: tuple wrapping needed since eversion is itself a tuple
- self.w(u"<b>CubicWeb version:</b> %s<br/>\n" % (eversion,))
+ w(u"<b>CubicWeb version:</b> %s<br/>\n" % (eversion,))
for pkg in self.config.cubes():
pkgversion = vcconf.get(pkg, _('no version information'))
- self.w(u"<b>Package %s version:</b> %s<br/>\n" % (pkg, pkgversion))
- self.w(u"</div>")
+ w(u"<b>Package %s version:</b> %s<br/>\n" % (pkg, pkgversion))
+ w(u"</div>")
# creates a bug submission link if SUBMIT_URL is set
submiturl = self.config['submit-url']
if submiturl:
binfo = text_error_description(ex, excinfo, req, eversion,
[(pkg, vcconf.get(pkg, _('no version information')))
for pkg in self.config.cubes()])
- self.w(u'<form action="%s" method="post">\n' % html_escape(submiturl))
- self.w(u'<fieldset>\n')
- self.w(u'<textarea class="hidden" name="description">%s</textarea>' % html_escape(binfo))
- self.w(u'<input type="hidden" name="description_format" value="text/rest"/>')
- self.w(u'<input type="hidden" name="__bugreporting" value="1"/>')
- self.w(u'<input type="submit" value="%s"/>' % _('Submit bug report'))
- self.w(u'</fieldset>\n')
- self.w(u'</form>\n')
+ w(u'<form action="%s" method="post">\n' % html_escape(submiturl))
+ w(u'<fieldset>\n')
+ w(u'<textarea class="hidden" name="description">%s</textarea>' % html_escape(binfo))
+ w(u'<input type="hidden" name="description_format" value="text/rest"/>')
+ w(u'<input type="hidden" name="__bugreporting" value="1"/>')
+ w(u'<input type="submit" value="%s"/>' % _('Submit bug report'))
+ w(u'</fieldset>\n')
+ w(u'</form>\n')
submitmail = self.config['submit-mail']
if submitmail:
binfo = text_error_description(ex, excinfo, req, eversion,
[(pkg, vcconf.get(pkg, _('no version information')))
for pkg in self.config.cubes()])
- self.w(u'<form action="%s" method="post">\n' % req.build_url('reportbug'))
- self.w(u'<fieldset>\n')
- self.w(u'<input type="hidden" name="description" value="%s"/>' % html_escape(binfo))
- self.w(u'<input type="hidden" name="__bugreporting" value="1"/>')
- self.w(u'<input type="submit" value="%s"/>' % _('Submit bug report by mail'))
- self.w(u'</fieldset>\n')
- self.w(u'</form>\n')
+ w(u'<form action="%s" method="post">\n' % req.build_url('reportbug'))
+ w(u'<fieldset>\n')
+ w(u'<input type="hidden" name="description" value="%s"/>' % html_escape(binfo))
+ w(u'<input type="hidden" name="__bugreporting" value="1"/>')
+ w(u'<input type="submit" value="%s"/>' % _('Submit bug report by mail'))
+ w(u'</fieldset>\n')
+ w(u'</form>\n')
def exc_message(ex, encoding):
@@ -262,7 +261,7 @@
return unicode(str(ex), encoding, 'replace')
except:
return unicode(repr(ex), encoding, 'replace')
-
+
def text_error_description(ex, excinfo, req, eversion, cubes):
binfo = rest_traceback(excinfo, html_escape(ex))
binfo += u'\n\n:URL: %s\n' % req.url()
@@ -284,23 +283,48 @@
_('components')
_('contentnavigation')
+
+def make_togglable_link(nodeid, label, cookiename):
+ """builds a HTML link that switches the visibility & remembers it"""
+ action = u"javascript: toggle_and_remember_visibility('%s', '%s')" % \
+ (nodeid, cookiename)
+ return u'<a href="%s">%s</a>' % (action, label)
+
+def css_class(someclass):
+ return someclass and 'class="%s"' % someclass or ''
+
class SystemEpropertiesForm(FormMixIn, StartupView):
controller = 'edit'
id = 'systemepropertiesform'
title = _('site configuration')
require_groups = ('managers',)
category = 'startupview'
-
+
def linkable(self):
return True
-
+
def url(self):
"""return the url associated with this view. We can omit rql here"""
return self.build_url('view', vid=self.id)
-
+
+ def _cookie_name(self, somestr):
+ return str('%s_property_%s' % (self.config.appid, somestr))
+
+ def _group_status(self, group, default=u'hidden'):
+ cookies = self.req.get_cookie()
+ cookiename = self._cookie_name(group)
+ cookie = cookies.get(cookiename)
+ if cookie is None:
+ cookies[cookiename] = default
+ self.req.set_cookie(cookies, cookiename, maxage=None)
+ status = default
+ else:
+ status = cookie.value
+ return status
+
def call(self, **kwargs):
"""The default view representing the application's index"""
- self.req.add_js('cubicweb.edition.js')
+ self.req.add_js(('cubicweb.edition.js', 'cubicweb.preferences.js'))
self.req.add_css('cubicweb.preferences.css')
vreg = self.vreg
values = self.defined_keys
@@ -322,7 +346,7 @@
for group, objects in groupedopts.items():
for oid, keys in objects.items():
groupedopts[group][oid] = self.form(keys, True)
-
+
w = self.w
req = self.req
_ = req._
@@ -330,17 +354,21 @@
w(self.error_message())
for label, group, form in sorted((_(g), g, f)
for g, f in mainopts.iteritems()):
+ status = css_class(self._group_status(group)) #'hidden' (collapsed), or '' (open) ?
w(u'<h2 class="propertiesform">%s</h2>\n' %
- (toggle_link('fieldset_' + group, label)))
- w(u'<div id="fieldset_%s" class="hidden">' % group)
+ (make_togglable_link('fieldset_' + group, label,
+ self._cookie_name(group))))
+ w(u'<div id="fieldset_%s" %s>' % (group, status))
w(u'<fieldset class="subentity">')
w(form)
w(u'</fieldset></div>')
for label, group, objects in sorted((_(g), g, o)
for g, o in groupedopts.iteritems()):
+ status = css_class(self._group_status(group))
w(u'<h2 class="propertiesform">%s</h2>\n' %
- (toggle_link('fieldset_' + group, label)))
- w(u'<div id="fieldset_%s" class="hidden">' % group)
+ (make_togglable_link('fieldset_' + group, label,
+ self._cookie_name(group))))
+ w(u'<div id="fieldset_%s" %s>' % (group, status))
for label, oid, form in sorted((self.req.__('%s_%s' % (group, o)), o, f)
for o, f in objects.iteritems()):
w(u'<fieldset class="subentity">')
@@ -352,21 +380,19 @@
w(form)
w(u'</fieldset>')
w(u'</div>')
-
-
@property
@cached
def eprops_rset(self):
return self.req.execute('Any P,K,V WHERE P is EProperty, P pkey K, P value V, NOT P for_user U')
-
+
@property
def defined_keys(self):
values = {}
for i, entity in enumerate(self.eprops_rset.entities()):
values[entity.pkey] = i
return values
-
+
def entity_for_key(self, key):
values = self.defined_keys
if key in values:
@@ -391,11 +417,11 @@
w(u'<input type="hidden" name="__redirectparams" value="%s"/>\n'
% html_escape(params))
w(u'<input type="hidden" name="__redirectpath" value="%s"/>\n' % path)
- #w(u'<input type="hidden" name="__redirectrql" value=""/>\n')
+ #w(u'<input type="hidden" name="__redirectrql" value=""/>\n')
w(u'<input type="hidden" name="__message" value="%s"/>\n'
% self.req._('changes applied'))
w(u'<table><tr><td>\n')
-
+
w(u'<table>\n')
for key in keys:
w(u'<tr>\n')
@@ -409,7 +435,7 @@
w(u'</fieldset>\n')
w(u'</form>\n')
return stream.getvalue()
-
+
def form_row(self, w, key, splitlabel):
entity = self.entity_for_key(key)
eid = entity.eid
@@ -434,13 +460,13 @@
w(u'<input type="hidden" name="%s" value="%s"/>' % (eid_param('pkey', eid), key))
w(u'<input type="hidden" name="%s" value="%s"/>' % (eid_param('edits-pkey', eid), ''))
-
+
class EpropertiesForm(SystemEpropertiesForm):
id = 'epropertiesform'
- title = _('preferences')
+ title = _('preferences')
require_groups = ('users', 'managers') # we don't want guests to be able to come here
__selectors__ = chainfirst(none_rset,
- chainall(one_line_rset, accept_rset_selector)),
+ chainall(one_line_rset, accept_rset)),
accepts = ('EUser',)
@classmethod
@@ -449,7 +475,7 @@
row = 0
score = super(EpropertiesForm, cls).accept_rset(req, rset, row, col)
# check current user is the rset user or he is in the managers group
- if score and (req.user.eid == rset[row][col or 0]
+ if score and (req.user.eid == rset[row][col or 0]
or req.user.matching_groups('managers')):
return score
return 0
@@ -459,7 +485,7 @@
if self.rset is None:
return self.req.user
return self.rset.get_entity(self.row or 0, self.col or 0)
-
+
@property
@cached
def eprops_rset(self):
@@ -476,9 +502,9 @@
% (eid_param('edits-for_user', eid), INTERNAL_FIELD_VALUE))
w(u'<input type="hidden" name="%s" value="%s"/>'
% (eid_param('for_user', eid), self.user.eid))
-
-
-
+
+
+
class ProcessInformationView(StartupView):
id = 'info'
--- a/web/views/massmailing.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/massmailing.py Wed Jun 03 19:42:23 2009 +0200
@@ -11,14 +11,14 @@
from cubicweb.interfaces import IEmailable
from cubicweb.common.view import EntityView
-from cubicweb.common.selectors import interface_selector, in_group_selector
+from cubicweb.common.selectors import implement_interface, match_user_group
from cubicweb.web.action import EntityAction
from cubicweb.web import stdmsgs
class SendEmailAction(EntityAction):
category = 'mainactions'
- __selectors__ = (interface_selector, in_group_selector)
+ __selectors__ = (implement_interface, match_user_group)
accepts_interfaces = (IEmailable,) # XXX should check email is set as well
require_groups = ('managers', 'users')
@@ -35,7 +35,7 @@
class MassMailingForm(EntityView):
id = 'massmailing'
- __selectors__ = (interface_selector, in_group_selector)
+ __selectors__ = (implement_interface, match_user_group)
accepts_interfaces = (IEmailable,)
require_groups = ('managers', 'users')
--- a/web/views/navigation.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/navigation.py Wed Jun 03 19:42:23 2009 +0200
@@ -11,9 +11,9 @@
from logilab.mtconverter import html_escape
from cubicweb.interfaces import IPrevNext
-from cubicweb.common.selectors import (paginated_rset, sortedrset_selector,
- primaryview_selector, contextprop_selector,
- one_line_rset, interface_selector)
+from cubicweb.common.selectors import (paginated_rset, sorted_rset,
+ primary_view, match_context_prop,
+ one_line_rset, implement_interface)
from cubicweb.common.uilib import cut
from cubicweb.web.component import EntityVComponent, NavigationComponent
@@ -36,20 +36,22 @@
while start < rset.rowcount:
stop = min(start + page_size - 1, rset.rowcount - 1)
blocklist.append(self.page_link(basepath, params, start, stop,
- u'%s - %s' % (start+1, stop+1)))
+ self.index_display(start, stop)))
start = stop + 1
w(u'<div class="pagination">')
w(u'%s ' % self.previous_link(params))
w(u'[ %s ]' % u' | '.join(blocklist))
w(u' %s' % self.next_link(params))
w(u'</div>')
+
+ def index_display(self, start, stop):
+ return u'%s - %s' % (start+1, stop+1)
-
class SortedNavigation(NavigationComponent):
"""sorted navigation apply if navigation is needed (according to page size)
and if the result set is sorted
"""
- __selectors__ = (paginated_rset, sortedrset_selector)
+ __selectors__ = (paginated_rset, sorted_rset)
# number of considered chars to build page links
nb_chars = 5
@@ -142,9 +144,11 @@
self.w(u'</div>')
-def limit_rset_using_paged_nav(self, req, rset, w, forcedisplay=False, show_all_option=True):
+def limit_rset_using_paged_nav(self, req, rset, w, forcedisplay=False,
+ show_all_option=True, page_size = None):
showall = forcedisplay or req.form.get('__force_display') is not None
- nav = not showall and self.vreg.select_component('navigation', req, rset)
+ nav = not showall and self.vreg.select_component('navigation', req, rset,
+ page_size=page_size)
if nav:
# get boundaries before component rendering
start, stop = nav.page_boundaries()
@@ -176,8 +180,8 @@
# itself
title = _('contentnavigation_prevnext')
help = _('contentnavigation_prevnext_description')
- __selectors__ = (one_line_rset, primaryview_selector,
- contextprop_selector, interface_selector)
+ __selectors__ = (one_line_rset, primary_view,
+ match_context_prop, implement_interface)
accepts_interfaces = (IPrevNext,)
context = 'navbottom'
order = 10
--- a/web/views/old_calendar.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/old_calendar.py Wed Jun 03 19:42:23 2009 +0200
@@ -11,7 +11,7 @@
from cubicweb.interfaces import ICalendarViews
from cubicweb.common.utils import date_range
-from cubicweb.common.selectors import interface_selector
+from cubicweb.common.selectors import implement_interface
from cubicweb.common.registerers import priority_registerer
from cubicweb.common.view import EntityView
@@ -33,7 +33,7 @@
class _CalendarView(EntityView):
"""base calendar view containing helpful methods to build calendar views"""
__registerer__ = priority_registerer
- __selectors__ = (interface_selector,)
+ __selectors__ = (implement_interface,)
accepts_interfaces = (ICalendarViews,)
need_navigation = False
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/web/views/owl.py Wed Jun 03 19:42:23 2009 +0200
@@ -0,0 +1,211 @@
+from logilab.mtconverter import TransformError, xml_escape
+
+from cubicweb.common.view import StartupView
+from cubicweb.common.view import EntityView
+
+_ = unicode
+
+OWL_CARD_MAP = {'1': '<rdf:type rdf:resource="&owl;FunctionalProperty"/>',
+ '?': '<owl:maxCardinality rdf:datatype="&xsd;int">1</owl:maxCardinality>',
+ '+': '<owl:minCardinality rdf:datatype="&xsd;int">1</owl:minCardinality>',
+ '*': ''
+ }
+
+OWL_TYPE_MAP = {'String': 'xsd:string',
+ 'Datetime': 'xsd:dateTime',
+ 'Bytes': 'xsd:byte',
+ 'Float': 'xsd:float',
+ 'Boolean': 'xsd:boolean',
+ 'Int': 'xsd:int',
+ 'Date':'xsd:date',
+ 'Time': 'xsd:time',
+ 'Password': 'xsd:byte',
+ 'Decimal' : 'xsd:decimal',
+ 'Interval': 'xsd:duration'
+ }
+
+OWL_OPENING_ROOT = u'''<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE rdf:RDF [
+ <!ENTITY owl "http://www.w3.org/2002/07/owl#" >
+ <!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" >
+]>
+<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
+ xmlns:owl="http://www.w3.org/2002/07/owl#"
+ xmlns="http://logilab.org/owl/ontologies/%(appid)s#"
+ xmlns:%(appid)s="http://logilab.org/owl/ontologies/%(appid)s#"
+ xmlns:base="http://logilab.org/owl/ontologies/%(appid)s">
+
+ <owl:Ontology rdf:about="">
+ <rdfs:comment>
+ %(appid)s Cubicweb OWL Ontology
+ </rdfs:comment>
+ </owl:Ontology>'''
+
+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"""
+ id = 'owl'
+ title = _('owl')
+ templatable = False
+ content_type = 'application/xml' # 'text/xml'
+
+ def call(self, writeprefix=True):
+ skipmeta = int(self.req.form.get('skipmeta', True))
+ if writeprefix:
+ self.w(OWL_OPENING_ROOT % {'appid': self.schema.name})
+ self.visit_schema(skipmeta=skipmeta)
+ if writeprefix:
+ self.w(OWL_CLOSING_ROOT)
+
+ def visit_schema(self, skiprels=DEFAULT_SKIP_RELS, skipmeta=True):
+ """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.w(u'<!-- classes definition -->')
+ for eschema in entities:
+ self.visit_entityschema(eschema, skiprels)
+ self.w(u'<!-- property definition -->')
+ self.visit_property_schema(eschema, skiprels)
+ self.w(u'<!-- datatype property -->')
+ self.visit_property_object_schema(eschema)
+
+ def visit_entityschema(self, eschema, skiprels=()):
+ """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')):
+ continue
+ for oeschema in targetschemas:
+ label = rschema.type
+ if role == 'subject':
+ card = rschema.rproperty(eschema, oeschema, 'cardinality')[0]
+ else:
+ card = rschema.rproperty(oeschema, eschema, 'cardinality')[1]
+ cardtag = OWL_CARD_MAP[card]
+ if cardtag:
+ self.w(u'''<rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#%s"/>
+ %s
+ </owl:Restriction>
+</rdfs:subClassOf>
+''' % (label, 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':
+ continue
+ self.w(u'''<rdfs:subClassOf>
+ <owl:Restriction>
+ <owl:onProperty rdf:resource="#%s"/>
+ <rdf:type rdf:resource="&owl;FunctionalProperty"/>
+ </owl:Restriction>
+</rdfs:subClassOf>'''
+ % aname)
+ self.w(u'</owl:Class>')
+
+ def visit_property_schema(self, eschema, skiprels=()):
+ """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')):
+ 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))
+
+ 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':
+ 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]))
+
+
+class OWLABOXView(EntityView):
+ '''This view represents a part of the ABOX for a given entity.'''
+
+ id = 'owlabox'
+ title = _('owlabox')
+ templatable = False
+ accepts = ('Any',)
+ content_type = 'application/xml' # 'text/xml'
+
+ def call(self):
+ self.w(OWL_OPENING_ROOT % {'appid': self.schema.name})
+ for i in xrange(self.rset.rowcount):
+ 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)
+
+
+class OWLABOXItemView(EntityView):
+ '''This view represents a part of the ABOX for a given entity.'''
+
+ id = 'owlaboxitem'
+ templatable = False
+ accepts = ('Any',)
+ content_type = 'application/xml' # 'text/xml'
+
+ def cell_call(self, row, col, skiprels=DEFAULT_SKIP_RELS):
+ 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:
+ continue
+ if not (rschema.has_local_role('read') or rschema.has_perm(self.req, 'read')):
+ continue
+ aname = rschema.type
+ if aname == 'eid':
+ continue
+ try:
+ attr = entity.printable_value(aname, format='text/plain')
+ if attr:
+ self.w(u'<%s>%s</%s>' % (aname, xml_escape(attr), aname))
+ except TransformError:
+ pass
+ 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')):
+ continue
+ if role == 'object':
+ attr = 'reverse_%s' % rschema.type
+ else:
+ attr = rschema.type
+ for x in getattr(entity, attr):
+ self.w(u'<%s>%s %s</%s>' % (attr, x.id, x.eid, attr))
+ self.w(u'</%s>'% eschema)
+
--- a/web/views/startup.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/startup.py Wed Jun 03 19:42:23 2009 +0200
@@ -2,7 +2,7 @@
apply to a result set.
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -26,6 +26,7 @@
def call(self, **kwargs):
"""The default view representing the application's management"""
+ self.req.add_css('cubicweb.manageview.css')
self.w(u'<div>\n')
if not self.display_folders():
self._main_index()
--- a/web/views/tableview.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/tableview.py Wed Jun 03 19:42:23 2009 +0200
@@ -2,7 +2,7 @@
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -14,8 +14,8 @@
from cubicweb.common.utils import make_uid
from cubicweb.common.uilib import toggle_action, limitsize, jsonize, htmlescape
from cubicweb.common.view import EntityView, AnyRsetView
-from cubicweb.common.selectors import (nonempty_rset, req_form_params_selector,
- accept_rset_selector)
+from cubicweb.common.selectors import (nonempty_rset, match_form_params,
+ accept_rset)
from cubicweb.web.htmlwidgets import (TableWidget, TableColumn, MenuWidget,
PopupBoxMenu, BoxLink)
from cubicweb.web.facet import prepare_facets_rqlst, filter_hiddens
@@ -24,8 +24,29 @@
id = 'table'
title = _('table')
finalview = 'final'
+
+ def form_filter(self, divid, displaycols, displayactions, displayfilter,
+ hidden=True):
+ rqlst = self.rset.syntax_tree()
+ # union not yet supported
+ if len(rqlst.children) != 1:
+ return ()
+ rqlst.save_state()
+ mainvar, baserql = prepare_facets_rqlst(rqlst, self.rset.args)
+ wdgs = [facet.get_widget() for facet in self.vreg.possible_vobjects(
+ 'facets', self.req, self.rset, context='tablefilter',
+ filtered_variable=mainvar)]
+ wdgs = [wdg for wdg in wdgs if wdg is not None]
+ rqlst.recover()
+ if wdgs:
+ self._generate_form(divid, baserql, wdgs, hidden,
+ vidargs={'displaycols': displaycols,
+ 'displayactions': displayactions,
+ 'displayfilter': displayfilter})
+ return self.show_hide_actions(divid, not hidden)
+ return ()
- def generate_form(self, divid, baserql, facets, hidden=True, vidargs={}):
+ def _generate_form(self, divid, baserql, fwidgets, hidden=True, vidargs={}):
"""display a form to filter table's content. This should only
occurs when a context eid is given
"""
@@ -36,15 +57,13 @@
html_escape(dumps([divid, 'table', False, vidargs])))
self.w(u'<fieldset id="%sForm" class="%s">' % (divid, hidden and 'hidden' or ''))
self.w(u'<input type="hidden" name="divid" value="%s" />' % divid)
- filter_hiddens(self.w, facets=','.join(facet.id for facet in facets), baserql=baserql)
+ filter_hiddens(self.w, facets=','.join(wdg.facet.id for wdg in fwidgets), baserql=baserql)
self.w(u'<table class="filter">\n')
self.w(u'<tr>\n')
- for facet in facets:
- wdg = facet.get_widget()
- if wdg is not None:
- self.w(u'<td>')
- wdg.render(w=self.w)
- self.w(u'</td>\n')
+ for wdg in fwidgets:
+ self.w(u'<td>')
+ wdg.render(w=self.w)
+ self.w(u'</td>\n')
self.w(u'</tr>\n')
self.w(u'</table>\n')
self.w(u'</fieldset>\n')
@@ -72,7 +91,7 @@
return displaycols
def call(self, title=None, subvid=None, displayfilter=None, headers=None,
- displaycols=None, displayactions=None, actions=(),
+ displaycols=None, displayactions=None, actions=(), divid=None,
cellvids=None, cellattrs=None):
"""Dumps a table displaying a composite query
@@ -84,7 +103,7 @@
rset = self.rset
req = self.req
req.add_js('jquery.tablesorter.js')
- req.add_css('cubicweb.tablesorter.css')
+ req.add_css(('cubicweb.tablesorter.css', 'cubicweb.tableview.css'))
rqlst = rset.syntax_tree()
# get rql description first since the filter form may remove some
# necessary information
@@ -93,7 +112,7 @@
hidden = True
if not subvid and 'subvid' in req.form:
subvid = req.form.pop('subvid')
- divid = req.form.get('divid') or 'rs%s' % make_uid(id(rset))
+ divid = divid or req.form.get('divid') or 'rs%s' % make_uid(id(rset))
actions = list(actions)
if mainindex is None:
displayfilter, displayactions = False, False
@@ -117,22 +136,8 @@
if title:
self.w(u'<h2 class="tableTitle">%s</h2>\n' % title)
if displayfilter:
- rqlst.save_state()
- try:
- mainvar, baserql = prepare_facets_rqlst(rqlst, rset.args)
- except NotImplementedError:
- # UNION query
- facets = None
- else:
- facets = list(self.vreg.possible_vobjects('facets', req, rset,
- context='tablefilter',
- filtered_variable=mainvar))
- self.generate_form(divid, baserql, facets, hidden,
- vidargs={'displaycols': displaycols,
- 'displayfilter': displayfilter,
- 'displayactions': displayactions})
- actions += self.show_hide_actions(divid, not hidden)
- rqlst.recover()
+ actions += self.form_filter(divid, displaycols, displayfilter,
+ displayactions)
elif displayfilter:
actions += self.show_hide_actions(divid, True)
self.w(u'<div id="%s"' % divid)
@@ -208,7 +213,6 @@
else:
column.append_renderer(subvid or 'incontext', colindex)
-
if cellattrs and colindex in cellattrs:
for name, value in cellattrs[colindex].iteritems():
column.add_attr(name,value)
@@ -249,7 +253,7 @@
class CellView(EntityView):
- __selectors__ = (nonempty_rset, accept_rset_selector)
+ __selectors__ = (nonempty_rset, accept_rset)
id = 'cell'
accepts = ('Any',)
@@ -285,13 +289,13 @@
displayed with default restrictions set
"""
id = 'initialtable'
- __selectors__ = nonempty_rset, req_form_params_selector
+ __selectors__ = nonempty_rset, match_form_params
form_params = ('actualrql',)
# should not be displayed in possible view since it expects some specific
# parameters
title = None
- def call(self, title=None, subvid=None, headers=None,
+ def call(self, title=None, subvid=None, headers=None, divid=None,
displaycols=None, displayactions=None):
"""Dumps a table displaying a composite query"""
actrql = self.req.form['actualrql']
@@ -299,6 +303,8 @@
displaycols = self.displaycols(displaycols)
if displayactions is None and 'displayactions' in self.req.form:
displayactions = True
+ if divid is None and 'divid' in self.req.form:
+ divid = self.req.form['divid']
self.w(u'<div class="section">')
if not title and 'title' in self.req.form:
# pop title so it's not displayed by the table view as well
@@ -307,33 +313,19 @@
self.w(u'<h2>%s</h2>\n' % title)
mainindex = self.main_var_index()
if mainindex is not None:
- rqlst = self.rset.syntax_tree()
- # union not yet supported
- if len(rqlst.children) == 1:
- rqlst.save_state()
- mainvar, baserql = prepare_facets_rqlst(rqlst, self.rset.args)
- facets = list(self.vreg.possible_vobjects('facets', self.req, self.rset,
- context='tablefilter',
- filtered_variable=mainvar))
-
- if facets:
- divid = self.req.form.get('divid', 'filteredTable')
- self.generate_form(divid, baserql, facets,
- vidargs={'displaycols': displaycols,
- 'displayactions': displayactions,
- 'displayfilter': True})
- actions = self.show_hide_actions(divid, False)
- rqlst.recover()
+ actions = self.form_filter(divid, displaycols, displayactions, True)
+ else:
+ actions = ()
if not subvid and 'subvid' in self.req.form:
subvid = self.req.form.pop('subvid')
self.view('table', self.req.execute(actrql),
'noresult', w=self.w, displayfilter=False, subvid=subvid,
displayactions=displayactions, displaycols=displaycols,
- actions=actions, headers=headers)
+ actions=actions, headers=headers, divid=divid)
self.w(u'</div>\n')
-class EditableInitiableTableView(InitialTableView):
+class EditableInitialTableTableView(InitialTableView):
id = 'editable-initialtable'
finalview = 'editable-final'
--- a/web/views/tabs.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/tabs.py Wed Jun 03 19:42:23 2009 +0200
@@ -1,73 +1,167 @@
"""base classes to handle tabbed views
:organization: Logilab
-:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
+from logilab.common.decorators import monkeypatch
from logilab.mtconverter import html_escape
from cubicweb import NoSelectableObject, role
+from cubicweb.common.view import EntityView
from cubicweb.common.selectors import has_related_entities
-from cubicweb.common.view import EntityView
+from cubicweb.common.utils import HTMLHead
+from cubicweb.common.uilib import rql_for_eid
+
+from cubicweb.web.views.basecontrollers import JSonController
+
+
+class LazyViewMixin(object):
+ """provides two convenience methods for the tab machinery
+ can also be used to lazy-load arbitrary views
+ caveat : lazyview is not recursive, i.e : you can't (successfully)
+ lazyload a view that in turns does the same
+ """
+
+ def _prepare_bindings(self, vid, reloadable):
+ self.req.html_headers.add_onload(u"""
+ jQuery('#lazy-%(vid)s').bind('%(event)s', function(event) {
+ load_now('#lazy-%(vid)s', '#%(vid)s-hole', %(reloadable)s);
+ });""" % {'event': 'load_%s' % vid, 'vid': vid,
+ 'reloadable' : str(reloadable).lower()})
-class TabsMixIn(object):
-
- def active_tab(self, default):
- cookie = self.req.get_cookie()
- activetab = cookie.get('active_tab')
+ def lazyview(self, vid, rql=None, eid=None, rset=None, static=False,
+ reloadable=False, show_spinbox=True, w=None):
+ """a lazy version of wview
+ first version only support lazy viewing for an entity at a time
+ """
+ assert rql or eid or rset or static, \
+ 'lazyview wants at least : rql, or an eid, or an rset -- or call it with static=True'
+ w = w or self.w
+ self.req.add_js('cubicweb.lazy.js')
+ urlparams = {'vid' : vid, 'mode' : 'html'}
+ if rql:
+ urlparams['rql'] = rql
+ elif eid:
+ urlparams['rql'] = rql_for_eid(eid)
+ elif rset:
+ urlparams['rql'] = rset.printable_rql()
+ w(u'<div id="lazy-%s" cubicweb:loadurl="%s">' % (
+ vid, html_escape(self.build_url('json', **urlparams))))
+ if show_spinbox:
+ w(u'<img src="data/loading.gif" id="%s-hole" alt="%s"/>'
+ % (vid, self.req._('loading')))
+ w(u'</div>')
+ self._prepare_bindings(vid, reloadable)
+
+ def forceview(self, vid):
+ """trigger an event that will force immediate loading of the view
+ on dom readyness
+ """
+ self.req.add_js('cubicweb.lazy.js')
+ self.req.html_headers.add_onload("trigger_load('%s');" % vid)
+
+
+class TabsMixin(LazyViewMixin):
+
+ @property
+ def cookie_name(self):
+ return str('%s_active_tab' % self.config.appid)
+
+ def active_tab(self, tabs, default):
+ cookies = self.req.get_cookie()
+ cookiename = self.cookie_name
+ activetab = cookies.get(cookiename)
if activetab is None:
- cookie['active_tab'] = default
- self.req.set_cookie(cookie, 'active_tab')
- return default
- return activetab.value
+ cookies[cookiename] = default
+ self.req.set_cookie(cookies, cookiename)
+ tab = default
+ else:
+ tab = activetab.value
+ return tab in tabs and tab or default
- def render_tabs(self, tabs, default, **kwargs):
+ def prune_tabs(self, tabs):
+ selected_tabs = []
+ for tab in tabs:
+ try:
+ self.vreg.select_view(tab, self.req, self.rset)
+ selected_tabs.append(tab)
+ except NoSelectableObject:
+ continue
+ return selected_tabs
+
+ def render_tabs(self, tabs, default, entity):
self.req.add_css('ui.tabs.css')
- self.req.add_js( ('ui.core.js', 'ui.tabs.js', 'cubicweb.tabs.js') )
- active_tab = self.active_tab(default)
- self.req.html_headers.add_post_inline_script(u"""
- jQuery(document).ready(function() {
- jQuery('#entity-tabs > ul').tabs( { selected: %(tabindex)s });
- set_tab('%(vid)s');
- });
- """ % {'tabindex' : tabs.index(active_tab),
- 'vid' : active_tab})
+ self.req.add_js(('ui.core.js', 'ui.tabs.js',
+ 'cubicweb.ajax.js', 'cubicweb.tabs.js', 'cubicweb.lazy.js'))
+ # tabbed views do no support concatenation
+ # hence we delegate to the default tab
+ if self.req.form.get('vid') == 'primary':
+ entity.view(default)
+ return
+ # prune tabs : not all are to be shown
+ tabs = self.prune_tabs(tabs)
+ # select a tab
+ active_tab = self.active_tab(tabs, default)
# build the html structure
w = self.w
- w(u'<div id="entity-tabs">')
+ w(u'<div id="entity-tabs-%s">' % entity.eid)
w(u'<ul>')
- tabviews = []
for tab in tabs:
- try:
- tabview = self.vreg.select_view(tab, self.req, self.rset, **kwargs)
- except NoSelectableObject:
- continue
- tabviews.append(tabview)
w(u'<li>')
w(u'<a href="#as-%s">' % tab)
- w(u'<span onclick="set_tab(\'%s\')">' % tab)
+ w(u'<span onclick="set_tab(\'%s\', \'%s\')">' % (tab, self.cookie_name))
w(self.req._(tab))
w(u'</span>')
w(u'</a>')
w(u'</li>')
w(u'</ul>')
w(u'</div>')
- # XXX ajaxify !
- for tabview in tabviews:
- w(u'<div id="as-%s">' % tabview.id)
- tabview.dispatch(w=self.w, **kwargs)
- w(u'</div>')
+ for tab in tabs:
+ w(u'<div id="as-%s">' % tab)
+ self.lazyview(tab, eid=entity.eid)
+ w(u'</div>')
+ # call the set_tab() JS function *after* each tab is generated
+ # because the callback binding needs to be done before
+ self.req.html_headers.add_onload(u"""
+ jQuery('#entity-tabs-%(eeid)s > ul').tabs( { selected: %(tabindex)s });
+ set_tab('%(vid)s', '%(cookiename)s');
+ """ % {'tabindex' : tabs.index(active_tab),
+ 'vid' : active_tab,
+ 'eeid' : entity.eid,
+ 'cookiename' : self.cookie_name})
+
-
-class EntityRelationTab(EntityView):
+class EntityRelatedTab(EntityView):
+ """A view you should inherit from leftmost,
+ to wrap another actual view displaying entity related stuff.
+ Such a view _must_ provide the rtype, target and vid attributes :
+
+ Example :
+
+ class ProjectScreenshotsView(EntityRelationView):
+ '''display project's screenshots'''
+ id = title = _('projectscreenshots')
+ accepts = ('Project',)
+ rtype = 'screenshot'
+ target = 'object'
+ vid = 'gallery'
+ __selectors__ = EntityRelationView.__selectors__ + (one_line_rset,)
+
+ This is the view we want to have in a tab, only if there is something to show.
+ Then, just define as below, and declare this being the tab content :
+
+ class ProjectScreenshotTab(EntityRelatedTab, ProjectScreenshotsView):
+ id = 'screenshots_tab'
+ """
__selectors__ = EntityView.__selectors__ + (has_related_entities,)
vid = 'list'
def cell_call(self, row, col):
- rset = self.rset.get_entity(row, col).related(self.rtype, role(self))
+ rset = self.entity(row, col).related(self.rtype, role(self))
self.w(u'<div class="mainInfo">')
self.wview(self.vid, rset, 'noresult')
self.w(u'</div>')
--- a/web/views/timeline.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/timeline.py Wed Jun 03 19:42:23 2009 +0200
@@ -14,7 +14,7 @@
from cubicweb.interfaces import ICalendarable
from cubicweb.common.view import EntityView, StartupView
-from cubicweb.common.selectors import interface_selector
+from cubicweb.common.selectors import implement_interface
#
@@ -28,7 +28,7 @@
templatable = False
content_type = 'application/json'
- __selectors__ = (interface_selector,)
+ __selectors__ = (implement_interface,)
accepts_interfaces = (ICalendarable,)
date_fmt = '%Y/%m/%d'
@@ -103,7 +103,7 @@
class TimelineView(TimelineViewMixIn, EntityView):
"""builds a cubicweb timeline widget node"""
id = 'timeline'
- __selectors__ = (interface_selector,)
+ __selectors__ = (implement_interface,)
accepts_interfaces = (ICalendarable,)
need_navigation = False
def call(self, tlunit=None):
--- a/web/views/timetable.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/timetable.py Wed Jun 03 19:42:23 2009 +0200
@@ -9,7 +9,7 @@
from cubicweb.interfaces import ITimetableViews
from cubicweb.common.utils import date_range
-from cubicweb.common.selectors import interface_selector
+from cubicweb.common.selectors import implement_interface
from cubicweb.common.view import AnyRsetView
@@ -25,7 +25,7 @@
class TimeTableView(AnyRsetView):
id = 'timetable'
title = _('timetable')
- __selectors__ = (interface_selector,)
+ __selectors__ = (implement_interface,)
accepts_interfaces = (ITimetableViews,)
need_navigation = False
--- a/web/views/treeview.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/treeview.py Wed Jun 03 19:42:23 2009 +0200
@@ -1,53 +1,62 @@
-from logilab.mtconverter import html_escape
+"""Set of tree-building widgets, based on jQuery treeview plugin
+:organization: Logilab
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+__docformat__ = "restructuredtext en"
+import uuid
+
+from logilab.mtconverter import html_escape
from cubicweb.interfaces import ITree
-from cubicweb.common.selectors import interface_selector, yes
+from cubicweb.common.selectors import implement_interface, yes
from cubicweb.common.view import EntityView
-from cubicweb.web.views.baseviews import OneLineView
+def treecookiename(treeid):
+ return str('treestate-%s' % treeid)
class TreeView(EntityView):
id = 'treeview'
accepts = ('Any',)
- fstree = False
itemvid = 'treeitemview'
-
- def call(self, subvid=None):
- if subvid is None and 'subvid' in self.req.form:
- subvid = self.req.form.pop('subvid') # consume it
+ css_classes = 'treeview widget'
+ title = _('tree view')
+
+ def call(self, subvid=None, treeid=None, initial_load=True):
if subvid is None:
- subvid = 'oneline'
- self.req.add_css('jquery.treeview.css')
- self.req.add_js(('cubicweb.ajax.js', 'jquery.treeview.js', 'cubicweb.widgets.js'))
- css_classes = 'treeview widget'
- if self.fstree:
- css_classes += ' filetree'
- # XXX noautoload is a quick hack to avoid treeview to be rebuilt
- # after a json query and avoid double toggling bugs.
- # Need to find a way to do that cleanly.
- if 'noautoload' in self.req.form:
- self.w(u'<ul class="%s" cubicweb:wdgtype="TreeView">' % css_classes)
- else:
- self.w(u'<ul class="%s" cubicweb:loadtype="auto" cubicweb:wdgtype="TreeView">'
- % css_classes)
+ if 'subvid' in self.req.form:
+ subvid = self.req.form.pop('subvid') # consume it
+ else:
+ subvid = 'oneline'
+ if treeid is None:
+ if 'treeid' in self.req.form:
+ treeid = self.req.form.pop('treeid')
+ else:
+ treeid = uuid.uuid1().hex
+ self.warning('Tree state won\'t be properly restored after next reload')
+ if initial_load:
+ self.req.add_css('jquery.treeview.css')
+ self.req.add_js(('cubicweb.ajax.js', 'jquery.treeview.js'))
+ self.req.html_headers.add_onload(u"""
+ jQuery("#tree-%s").treeview({toggle: toggleTree,
+ prerendered: true});""" % treeid)
+ self.w(u'<ul id="tree-%s" class="%s">' % (treeid, self.css_classes))
for rowidx in xrange(len(self.rset)):
self.wview(self.itemvid, self.rset, row=rowidx, col=0,
- vid=subvid, parentvid=self.id)
+ vid=subvid, parentvid=self.id, treeid=treeid)
self.w(u'</ul>')
-
class FileTreeView(TreeView):
"""specific version of the treeview to display file trees
"""
id = 'filetree'
- fstree = True
+ css_classes = 'treeview widget filetree'
+ title = _('file tree view')
- def call(self, subvid=None):
- super(FileTreeView, self).call(subvid='filetree-oneline')
+ def call(self, subvid=None, treeid=None, initial_load=True):
+ super(FileTreeView, self).call(treeid=treeid, subvid='filetree-oneline', initial_load=initial_load)
-
-
-class FileItemInnerView(OneLineView):
+class FileItemInnerView(EntityView):
"""inner view used by the TreeItemView instead of oneline view
This view adds an enclosing <span> with some specific CSS classes
@@ -58,10 +67,10 @@
def cell_call(self, row, col):
entity = self.entity(row, col)
if ITree.is_implemented_by(entity.__class__) and not entity.is_leaf():
- self.w(u'<span class="folder">%s</span>' % entity.view('oneline'))
+ self.w(u'<div class="folder">%s</div>\n' % entity.view('oneline'))
else:
# XXX define specific CSS classes according to mime types
- self.w(u'<span class="file">%s</span>' % entity.view('oneline'))
+ self.w(u'<div class="file">%s</div>\n' % entity.view('oneline'))
class DefaultTreeViewItemView(EntityView):
@@ -69,53 +78,104 @@
"""
id = 'treeitemview'
accepts = ('Any',)
-
- def cell_call(self, row, col, vid='oneline', parentvid='treeview'):
+
+ def cell_call(self, row, col, vid='oneline', parentvid='treeview', treeid=None):
+ assert treeid is not None
entity = self.entity(row, col)
itemview = self.view(vid, self.rset, row=row, col=col)
if row == len(self.rset) - 1:
self.w(u'<li class="last">%s</li>' % itemview)
else:
- self.w(u'<li><span>%s</span></li>' % itemview)
+ self.w(u'<li>%s</li>' % itemview)
class TreeViewItemView(EntityView):
"""specific treeitem view for entities which implement ITree
-
+
(each item should be exandable if it's not a tree leaf)
"""
id = 'treeitemview'
# XXX append yes to make sure we get an higher score than
# the default treeitem view
- __selectors__ = (interface_selector, yes)
+ __selectors__ = (implement_interface, yes)
accepts_interfaces = (ITree,)
-
- def cell_call(self, row, col, vid='oneline', parentvid='treeview'):
+
+ def open_state(self, eeid, treeid):
+ cookies = self.req.get_cookie()
+ treestate = cookies.get(treecookiename(treeid))
+ if treestate:
+ return str(eeid) in treestate.value.split(';')
+ return False
+
+ def cell_call(self, row, col, treeid, vid='oneline', parentvid='treeview'):
+ w = self.w
entity = self.entity(row, col)
- cssclasses = []
+ liclasses = []
is_leaf = False
- if row == len(self.rset) - 1:
- is_leaf = True
+ is_last = row == len(self.rset) - 1
+ is_open = self.open_state(entity.eid, treeid)
if not hasattr(entity, 'is_leaf') or entity.is_leaf():
- if is_leaf : cssclasses.append('last')
- self.w(u'<li class="%s">' % u' '.join(cssclasses))
+ if is_last:
+ liclasses.append('last')
+ w(u'<li class="%s">' % u' '.join(liclasses))
else:
rql = entity.children_rql() % {'x': entity.eid}
url = html_escape(self.build_url('json', rql=rql, vid=parentvid,
pageid=self.req.pageid,
- subvid=vid,
- noautoload=True))
- cssclasses.append('expandable')
- divclasses = ['hitarea expandable-hitarea']
- if is_leaf :
- cssclasses.append('lastExpandable')
- divclasses.append('lastExpandable-hitarea')
- self.w(u'<li cubicweb:loadurl="%s" class="%s">' % (url, u' '.join(cssclasses)))
- self.w(u'<div class="%s"> </div>' % u' '.join(divclasses))
-
+ treeid=treeid,
+ subvid=vid))
+ divclasses = ['hitarea']
+ if is_open:
+ liclasses.append('collapsable')
+ divclasses.append('collapsable-hitarea')
+ else:
+ liclasses.append('expandable')
+ divclasses.append('closed-hitarea expandable-hitarea')
+ if is_last:
+ if is_open:
+ liclasses.append('lastCollapsable')
+ divclasses.append('lastCollapsable-hitarea')
+ else:
+ liclasses.append('lastExpandable')
+ divclasses.append('lastExpandable-hitarea')
+ if is_open:
+ w(u'<li class="%s">' % u' '.join(liclasses))
+ else:
+ w(u'<li cubicweb:loadurl="%s" class="%s">' % (url, u' '.join(liclasses)))
+ if is_leaf:
+ divtail = ''
+ else:
+ divtail = ''' onclick="async_remote_exec('node_clicked', '%s', '%s')"''' % \
+ (treeid, entity.eid)
+ w(u'<div class="%s"%s></div>' % (u' '.join(divclasses), divtail))
+
# add empty <ul> because jquery's treeview plugin checks for
# sublists presence
- self.w(u'<ul class="placeholder"><li>place holder</li></ul>')
+ if not is_open:
+ w(u'<ul class="placeholder"><li>place holder</li></ul>')
+ # the local node info
self.wview(vid, self.rset, row=row, col=col)
- self.w(u'</li>')
+ if is_open: # recurse if needed
+ self.wview(parentvid, self.req.execute(rql), treeid=treeid, initial_load=False)
+ w(u'</li>')
+
+from logilab.common.decorators import monkeypatch
+from cubicweb.web.views.basecontrollers import JSonController
+@monkeypatch(JSonController)
+def js_node_clicked(self, treeid, nodeeid):
+ """add/remove eid in treestate cookie"""
+ cookies = self.req.get_cookie()
+ statename = treecookiename(treeid)
+ treestate = cookies.get(statename)
+ if treestate is None:
+ cookies[statename] = nodeeid
+ self.req.set_cookie(cookies, statename)
+ else:
+ marked = set(filter(None, treestate.value.split(';')))
+ if nodeeid in marked:
+ marked.remove(nodeeid)
+ else:
+ marked.add(nodeeid)
+ cookies[statename] = ';'.join(marked)
+ self.req.set_cookie(cookies, statename)
--- a/web/views/wdoc.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/views/wdoc.py Wed Jun 03 19:42:23 2009 +0200
@@ -15,7 +15,7 @@
from logilab.common.changelog import ChangeLog
from logilab.mtconverter import CHARSET_DECL_RGX
-from cubicweb.common.selectors import req_form_params_selector
+from cubicweb.common.selectors import match_form_params
from cubicweb.common.view import StartupView
from cubicweb.common.uilib import rest_publish
from cubicweb.web import NotFound
@@ -85,7 +85,7 @@
# help views ##################################################################
class InlineHelpView(StartupView):
- __selectors__ = (req_form_params_selector,)
+ __selectors__ = (match_form_params,)
form_params = ('fid',)
id = 'wdoc'
title = _('site documentation')
@@ -163,7 +163,7 @@
class InlineHelpImageView(StartupView):
- __selectors__ = (req_form_params_selector,)
+ __selectors__ = (match_form_params,)
form_params = ('fid',)
id = 'wdocimages'
binary = True
--- a/web/webconfig.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/webconfig.py Wed Jun 03 19:42:23 2009 +0200
@@ -1,7 +1,7 @@
"""common web configuration for twisted/modpython applications
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -349,6 +349,6 @@
stream.close()
def static_file_del(self, rpath):
- if static_file_exists(rpath):
+ if self.static_file_exists(rpath):
os.remove(join(self.static_directory, rpath))
--- a/web/webctl.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/webctl.py Wed Jun 03 19:42:23 2009 +0200
@@ -2,12 +2,12 @@
web configuration
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
-from cubicweb.toolsutils import CommandHandler
+from cubicweb.toolsutils import CommandHandler, confirm
class WebCreateHandler(CommandHandler):
@@ -22,7 +22,10 @@
print '** repository server configuration'
print '-' * 72
config.input_config('pyro-client', inputlevel)
-
+ if confirm('allow anonymous access', False):
+ config.global_set_option('anonymous-user', 'anon')
+ config.global_set_option('anonymous-password', 'anon')
+
def postcreate(self):
"""hooks called once application's initialization has been completed"""
--- a/web/widgets.py Thu Jan 15 10:13:25 2009 +0100
+++ b/web/widgets.py Wed Jun 03 19:42:23 2009 +0200
@@ -732,12 +732,13 @@
formatstr = req.property_value(self.format_key)
return now().strftime(formatstr)
- def add_localized_infos(self, req):
+ @classmethod
+ def add_localized_infos(cls, req):
"""inserts JS variables defining localized months and days"""
# import here to avoid dependancy from cubicweb-common to simplejson
_ = req._
- monthnames = [_(mname) for mname in self.monthnames]
- daynames = [_(dname) for dname in self.daynames]
+ monthnames = [_(mname) for mname in cls.monthnames]
+ daynames = [_(dname) for dname in cls.daynames]
req.html_headers.define_var('MONTHNAMES', monthnames)
req.html_headers.define_var('DAYNAMES', daynames)