--- a/.hgtags Fri Sep 11 12:42:37 2009 +0200
+++ b/.hgtags Fri Sep 11 15:55:15 2009 +0200
@@ -62,3 +62,7 @@
7fd294cbf6ff3cf34475cc50e972f650a34ae6e8 cubicweb-debian-version-3.4.5-1
921fdbf8b3038dc27a2ec5398a0fbcbc5b9ba4be cubicweb-version-3.4.6
52dba800ca4d4b82c47f3befb824bd91ef015368 cubicweb-debian-version-3.4.6-1
+0e549b299f0b357837ea620c561aa843f46de17a cubicweb-version-3.4.7
+ebb92e62eb040a070deb1f2d2434734cfac3af01 cubicweb-debian-version-3.4.7-1
+ba43e084e8841f62c3b4c2449b26a7546233e5fb cubicweb-version-3.4.8
+97273eeaaead11c0f422dc5a4fe2d4f14fc6a2dd cubicweb-debian-version-3.4.8-1
--- a/_exceptions.py Fri Sep 11 12:42:37 2009 +0200
+++ b/_exceptions.py Fri Sep 11 15:55:15 2009 +0200
@@ -117,7 +117,7 @@
class NoSelectableObject(RegistryException):
"""some views with the given vid have been found but no
- one is applyable to the result set
+ one is applicable to the result set
"""
class UnknownProperty(RegistryException):
--- a/cwctl.py Fri Sep 11 12:42:37 2009 +0200
+++ b/cwctl.py Fri Sep 11 15:55:15 2009 +0200
@@ -152,6 +152,7 @@
else:
self.run_arg(appid)
+
# base commands ###############################################################
class ListCommand(Command):
@@ -365,7 +366,7 @@
# instance commands ########################################################
-class StartInstanceCommand(InstanceCommand):
+class StartInstanceCommand(InstanceCommandFork):
"""Start the given instances. If no instance is given, start them all.
<instance>...
@@ -397,17 +398,15 @@
def start_instance(self, appid):
"""start the instance's server"""
- # use get() since start may be used from other commands (eg upgrade)
- # without all options defined
- debug = self.get('debug')
- force = self.get('force')
- loglevel = self.get('loglevel')
+ debug = self['debug']
+ force = self['force']
+ loglevel = self['loglevel']
config = cwcfg.config_for(appid)
if loglevel is not None:
loglevel = 'LOG_%s' % loglevel.upper()
config.global_set_option('log-threshold', loglevel)
config.init_log(loglevel, debug=debug, force=True)
- if self.get('profile'):
+ if self['profile']:
config.global_set_option('profile', self.config.profile)
helper = self.config_helper(config, cmdname='start')
pidf = config['pid-file']
@@ -415,8 +414,10 @@
msg = "%s seems to be running. Remove %s by hand if necessary or use \
the --force option."
raise ExecutionError(msg % (appid, pidf))
- helper.start_command(config, debug)
- return True
+ helper.start_server(config, debug)
+ if not debug:
+ # in debug mode, we reach this point once the instance is stopped...
+ print 'instance %s %s' % (appid, self.actionverb)
class StopInstanceCommand(InstanceCommand):
@@ -469,8 +470,7 @@
print 'instance %s stopped' % appid
-class RestartInstanceCommand(StartInstanceCommand,
- StopInstanceCommand):
+class RestartInstanceCommand(StartInstanceCommand):
"""Restart the given instances.
<instance>...
@@ -489,14 +489,12 @@
print ('some specific start order is specified, will first stop all '
'instances then restart them.')
# get instances in startorder
- stopped = []
for appid in args:
if askconfirm:
print '*'*72
if not ASK.confirm('%s instance %r ?' % (self.name, appid)):
continue
- self.stop_instance(appid)
- stopped.append(appid)
+ StopInstanceCommand().stop_instance(appid)
forkcmd = [w for w in sys.argv if not w in args]
forkcmd[1] = 'start'
forkcmd = ' '.join(forkcmd)
@@ -506,9 +504,8 @@
sys.exit(status)
def restart_instance(self, appid):
- self.stop_instance(appid)
- if self.start_instance(appid):
- print 'instance %s %s' % (appid, self.actionverb)
+ StopInstanceCommand().stop_instance(appid)
+ self.start_instance(appid)
class ReloadConfigurationCommand(RestartInstanceCommand):
@@ -559,9 +556,7 @@
print "running with pid %s" % (pid)
-class UpgradeInstanceCommand(InstanceCommandFork,
- StartInstanceCommand,
- StopInstanceCommand):
+class UpgradeInstanceCommand(InstanceCommandFork):
"""Upgrade an instance after cubicweb and/or component(s) upgrade.
For repository update, you will be prompted for a login / password to use
@@ -617,10 +612,6 @@
}),
)
- def ordered_instances(self):
- # need this since mro return StopInstanceCommand implementation
- return InstanceCommand.ordered_instances(self)
-
def upgrade_instance(self, appid):
print '\n' + underline_title('Upgrading the instance %s' % appid)
from logilab.common.changelog import Version
@@ -667,7 +658,7 @@
print '-> migration needed from %s to %s for %s' % (fromversion, toversion, cube)
# only stop once we're sure we have something to do
if not (cwcfg.mode == 'dev' or self.config.nostartstop):
- self.stop_instance(appid)
+ StopCommand().stop_instance(appid)
# run cubicweb/componants migration scripts
mih.migrate(vcconf, reversed(toupgrade), self.config)
# rewrite main configuration file
@@ -690,7 +681,7 @@
print
print '-> instance migrated.'
if not (cwcfg.mode == 'dev' or self.config.nostartstop):
- self.start_instance(appid)
+ StartCommand().start_instance(appid)
print
--- a/cwvreg.py Fri Sep 11 12:42:37 2009 +0200
+++ b/cwvreg.py Fri Sep 11 15:55:15 2009 +0200
@@ -130,19 +130,23 @@
baseschemas = [eschema] + eschema.ancestors()
# browse ancestors from most specific to most generic and try to find an
# associated custom entity class
+ cls = None
for baseschema in baseschemas:
try:
btype = ETYPE_NAME_MAP[baseschema]
except KeyError:
btype = str(baseschema)
- try:
- objects = self[btype]
- assert len(objects) == 1, objects
- cls = objects[0]
- break
- except ObjectNotFound:
- pass
- else:
+ if cls is None:
+ try:
+ objects = self[btype]
+ assert len(objects) == 1, objects
+ cls = objects[0]
+ except ObjectNotFound:
+ pass
+ else:
+ # ensure parent classes are built first
+ self.etype_class(btype)
+ if cls is None:
# no entity class for any of the ancestors, fallback to the default
# one
objects = self['Any']
--- a/debian/changelog Fri Sep 11 12:42:37 2009 +0200
+++ b/debian/changelog Fri Sep 11 15:55:15 2009 +0200
@@ -1,3 +1,21 @@
+cubicweb (3.4.9-1) unstable; urgency=low
+
+ * new upstream release
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr> Fri, 11 Sep 2009 14:27:39 +0200
+
+cubicweb (3.4.8-1) unstable; urgency=low
+
+ * new upstream release
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr> Thu, 10 Sep 2009 15:27:17 +0200
+
+cubicweb (3.4.7-1) unstable; urgency=low
+
+ * new upstream release
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr> Wed, 09 Sep 2009 14:08:41 +0200
+
cubicweb (3.4.6-1) unstable; urgency=low
* new upstream release
--- a/doc/book/en/B0015-define-permissions.en.txt Fri Sep 11 12:42:37 2009 +0200
+++ b/doc/book/en/B0015-define-permissions.en.txt Fri Sep 11 15:55:15 2009 +0200
@@ -114,7 +114,7 @@
require_group = SubjectRelation('EGroup', cardinality='+*',
description=_('groups to which the permission is granted'))
require_state = SubjectRelation('State',
- description=_("entity'state in which the permission is applyable"))
+ description=_("entity'state in which the permission is applicable"))
# can be used on any entity
require_permission = ObjectRelation('**', cardinality='*1', composite='subject',
description=_("link a permission to the entity. This "
--- a/doc/book/en/development/datamodel/definition.rst Fri Sep 11 12:42:37 2009 +0200
+++ b/doc/book/en/development/datamodel/definition.rst Fri Sep 11 15:55:15 2009 +0200
@@ -390,7 +390,7 @@
require_group = SubjectRelation('CWGroup', cardinality='+*',
description=_('groups to which the permission is granted'))
require_state = SubjectRelation('State',
- description=_("entity'state in which the permission is applyable"))
+ description=_("entity's state in which the permission is applicable"))
# can be used on any entity
require_permission = ObjectRelation('**', cardinality='*1', composite='subject',
description=_("link a permission to the entity. This "
--- a/entity.py Fri Sep 11 12:42:37 2009 +0200
+++ b/entity.py Fri Sep 11 15:55:15 2009 +0200
@@ -682,14 +682,16 @@
self.set_related_cache(rtype, role, rset)
return self.related(rtype, role, limit, entities)
- def related_rql(self, rtype, role='subject'):
+ def related_rql(self, rtype, role='subject', targettypes=None):
rschema = self.schema[rtype]
if role == 'subject':
- targettypes = rschema.objects(self.e_schema)
+ if targettypes is None:
+ targettypes = rschema.objects(self.e_schema)
restriction = 'E eid %%(x)s, E %s X' % rtype
card = greater_card(rschema, (self.e_schema,), targettypes, 0)
else:
- targettypes = rschema.subjects(self.e_schema)
+ if targettypes is None:
+ targettypes = rschema.subjects(self.e_schema)
restriction = 'E eid %%(x)s, X %s E' % rtype
card = greater_card(rschema, targettypes, (self.e_schema,), 1)
if len(targettypes) > 1:
--- a/etwist/server.py Fri Sep 11 12:42:37 2009 +0200
+++ b/etwist/server.py Fri Sep 11 15:55:15 2009 +0200
@@ -16,12 +16,6 @@
import hotshot
from twisted.application import strports
-try:
- from twisted.scripts._twistd_unix import daemonize
-except ImportError:
- def daemonize():
- raise NotImplementedError('not yet for win32')
-
from twisted.internet import reactor, task, threads
from twisted.internet.defer import maybeDeferred
from twisted.web2 import channel, http, server, iweb
@@ -35,6 +29,36 @@
from cubicweb.etwist.request import CubicWebTwistedRequestAdapter
+def daemonize(uid):
+ # XXX unix specific
+ # XXX factorize w/ code in cw.server.server and cw.server.serverctl
+ # (start-repository command)
+ if uid is not None:
+ try:
+ uid = int(uid)
+ except ValueError:
+ from pwd import getpwnam
+ uid = getpwnam(uid).pw_uid
+ os.setuid(uid)
+ # See http://www.erlenstar.demon.co.uk/unix/faq_toc.html#TOC16
+ if os.fork(): # launch child and...
+ return -1
+ os.setsid()
+ if os.fork(): # launch child and...
+ os._exit(0) # kill off parent again.
+ # move to the root to avoit mount pb
+ os.chdir('/')
+ # set paranoid umask
+ os.umask(077)
+ null = os.open('/dev/null', os.O_RDWR)
+ for i in range(3):
+ try:
+ os.dup2(null, i)
+ except OSError, e:
+ if e.errno != errno.EBADF:
+ raise
+ os.close(null)
+ return None
def start_task(interval, func):
lc = task.LoopingCall(func)
@@ -373,7 +397,9 @@
logger = getLogger('cubicweb.twisted')
logger.info('instance started on %s', baseurl)
if not debug:
- daemonize()
+ if daemonize(config['uid']):
+ # child process
+ return
if config['pid-file']:
# ensure the directory where the pid-file should be set exists (for
# instance /var/run/cubicweb may be deleted on computer restart)
--- a/etwist/twctl.py Fri Sep 11 12:42:37 2009 +0200
+++ b/etwist/twctl.py Fri Sep 11 15:55:15 2009 +0200
@@ -18,7 +18,7 @@
cmdname = 'start'
cfgname = 'twisted'
- def start_command(self, config, debug):
+ def start_server(self, config, debug):
from cubicweb.etwist import server
server.run(config, debug)
--- a/i18n/en.po Fri Sep 11 12:42:37 2009 +0200
+++ b/i18n/en.po Fri Sep 11 15:55:15 2009 +0200
@@ -608,7 +608,9 @@
msgid "You can use any of the following substitutions in your text"
msgstr ""
-msgid "You have no access to this view or it's not applyable to current data"
+msgid ""
+"You have no access to this view or it can not be used to display the current "
+"data."
msgstr ""
msgid ""
@@ -1646,12 +1648,13 @@
msgid "download"
msgstr ""
+#, python-format
+msgid "download %s"
+msgstr ""
+
msgid "download icon"
msgstr ""
-msgid "download image"
-msgstr ""
-
msgid "download schema as owl"
msgstr ""
@@ -2052,6 +2055,12 @@
msgid "invalid date"
msgstr ""
+msgid "invalid float value"
+msgstr ""
+
+msgid "invalid integer value"
+msgstr ""
+
msgid "is"
msgstr ""
--- a/i18n/es.po Fri Sep 11 12:42:37 2009 +0200
+++ b/i18n/es.po Fri Sep 11 15:55:15 2009 +0200
@@ -625,8 +625,10 @@
"Puede realizar cualquiera de las siguientes sustituciones en el contenido de "
"su email."
-msgid "You have no access to this view or it's not applyable to current data"
-msgstr "No tiene acceso a esta vista o No es aplicable a los datos actuales"
+msgid ""
+"You have no access to this view or it can not be used to display the current "
+"data."
+msgstr "No tiene acceso a esta vista o No se puede utilizare para los datos actuales."
msgid ""
"You're not authorized to access this page. If you think you should, please "
@@ -1708,12 +1710,13 @@
msgid "download"
msgstr "Descargar"
+#, python-format
+msgid "download %s"
+msgstr ""
+
msgid "download icon"
msgstr "ícono de descarga"
-msgid "download image"
-msgstr ""
-
msgid "download schema as owl"
msgstr "Descargar esquema en OWL"
@@ -2128,6 +2131,12 @@
msgid "invalid date"
msgstr "Esta fecha no es válida"
+msgid "invalid float value"
+msgstr ""
+
+msgid "invalid integer value"
+msgstr ""
+
msgid "is"
msgstr "es"
@@ -3183,3 +3192,7 @@
msgid "you should probably delete that property"
msgstr "deberia probablamente suprimir esta propriedad"
+
+#~ msgid ""
+#~ "You have no access to this view or it's not applyable to current data"
+#~ msgstr "No tiene acceso a esta vista o No es aplicable a los datos actuales"
--- a/i18n/fr.po Fri Sep 11 12:42:37 2009 +0200
+++ b/i18n/fr.po Fri Sep 11 15:55:15 2009 +0200
@@ -624,9 +624,10 @@
"Vous pouvez utiliser n'importe quelle substitution parmi la liste suivante "
"dans le contenu de votre courriel."
-msgid "You have no access to this view or it's not applyable to current data"
-msgstr ""
-"Vous n'avez pas accès à cette vue ou elle ne s'applique pas aux données"
+msgid ""
+"You have no access to this view or it can not be used to display the current "
+"data."
+msgstr "Vous n'avez pas accès à cette vue ou elle ne peut pas afficher ces données."
msgid ""
"You're not authorized to access this page. If you think you should, please "
@@ -1721,12 +1722,13 @@
msgid "download"
msgstr "télécharger"
+#, python-format
+msgid "download %s"
+msgstr "télécharger %s"
+
msgid "download icon"
msgstr "icône de téléchargement"
-msgid "download image"
-msgstr "image de téléchargement"
-
msgid "download schema as owl"
msgstr "télécharger le schéma OWL"
@@ -2141,6 +2143,12 @@
msgid "invalid date"
msgstr "cette date n'est pas valide"
+msgid "invalid float value"
+msgstr "nombre flottant non valide"
+
+msgid "invalid integer value"
+msgstr "nombre entier non valide"
+
msgid "is"
msgstr "de type"
@@ -3199,3 +3207,11 @@
msgid "you should probably delete that property"
msgstr "vous devriez probablement supprimer cette propriété"
+
+#~ msgid ""
+#~ "You have no access to this view or it's not applyable to current data"
+#~ msgstr ""
+#~ "Vous n'avez pas accès à cette vue ou elle ne s'applique pas aux données"
+
+#~ msgid "download image"
+#~ msgstr "image de téléchargement"
--- a/server/querier.py Fri Sep 11 12:42:37 2009 +0200
+++ b/server/querier.py Fri Sep 11 15:55:15 2009 +0200
@@ -508,7 +508,7 @@
if repo.schema.rschema(rtype).inlined:
entity = session.entity_from_eid(subj)
entity[rtype] = obj
- repo.glob_update_entity(session, entity)
+ repo.glob_update_entity(session, entity, set((rtype,)))
else:
repo.glob_add_relation(session, subj, rtype, obj)
--- a/server/serverctl.py Fri Sep 11 12:42:37 2009 +0200
+++ b/server/serverctl.py Fri Sep 11 15:55:15 2009 +0200
@@ -210,12 +210,12 @@
cmdname = 'start'
cfgname = 'repository'
- def start_command(self, ctlconf, debug):
+ def start_server(self, ctlconf, debug):
command = ['cubicweb-ctl start-repository ']
if debug:
command.append('--debug')
command.append(self.config.appid)
- return ' '.join(command)
+ os.system(' '.join(command))
class RepositoryStopHandler(CommandHandler):
--- a/server/session.py Fri Sep 11 12:42:37 2009 +0200
+++ b/server/session.py Fri Sep 11 15:55:15 2009 +0200
@@ -81,7 +81,7 @@
def hijack_user(self, user):
"""return a fake request/session using specified user"""
session = Session(user, self.repo)
- session._threaddata = self._threaddata
+ session._threaddata = self.actual_session()._threaddata
return session
def _change_relation(self, cb, fromeid, rtype, toeid):
--- a/skeleton/migration/postcreate.py Fri Sep 11 12:42:37 2009 +0200
+++ b/skeleton/migration/postcreate.py Fri Sep 11 15:55:15 2009 +0200
@@ -1,4 +1,4 @@
-# postcreate script. You could setup a workflow here for example
+# postcreate script. You could setup site properties or a workflow here for example
"""
:organization: Logilab
@@ -7,3 +7,6 @@
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
"""
+# Example of site property change
+#set_property('ui.site-title', "<sitename>")
+
--- a/sobjects/supervising.py Fri Sep 11 12:42:37 2009 +0200
+++ b/sobjects/supervising.py Fri Sep 11 15:55:15 2009 +0200
@@ -23,6 +23,8 @@
accepts = ('Any',)
def call(self, session, *args):
+ if session.is_super_session or session.repo.config.repairing:
+ return # ignore changes triggered by hooks or maintainance shell
dest = self.config['supervising-addrs']
if not dest: # no supervisors, don't do this for nothing...
return
--- a/test/unittest_entity.py Fri Sep 11 12:42:37 2009 +0200
+++ b/test/unittest_entity.py Fri Sep 11 15:55:15 2009 +0200
@@ -182,15 +182,16 @@
from cubicweb.entities import fetch_config
Personne = self.vreg['etypes'].etype_class('Personne')
Note = self.vreg['etypes'].etype_class('Note')
+ self.failUnless(issubclass(self.vreg['etypes'].etype_class('SubNote'), Note))
Personne.fetch_attrs, Personne.fetch_order = fetch_config(('nom', 'type'))
Note.fetch_attrs, Note.fetch_order = fetch_config(('type',))
- aff = self.add_entity('Personne', nom=u'pouet')
- self.assertEquals(aff.related_rql('evaluee'),
+ p = self.add_entity('Personne', nom=u'pouet')
+ self.assertEquals(p.related_rql('evaluee'),
'Any X,AA,AB ORDERBY AA ASC WHERE E eid %(x)s, E evaluee X, '
'X type AA, X modification_date AB')
Personne.fetch_attrs, Personne.fetch_order = fetch_config(('nom', ))
# XXX
- self.assertEquals(aff.related_rql('evaluee'),
+ self.assertEquals(p.related_rql('evaluee'),
'Any X,AA ORDERBY Z DESC WHERE X modification_date Z, E eid %(x)s, E evaluee X, X modification_date AA')
def test_entity_unrelated(self):
--- a/web/data/cubicweb.edition.js Fri Sep 11 12:42:37 2009 +0200
+++ b/web/data/cubicweb.edition.js Fri Sep 11 15:55:15 2009 +0200
@@ -255,6 +255,11 @@
updateInlinedEntitiesCounters(rtype);
reorderTabindex();
form.trigger('inlinedform-added');
+ // if the inlined form contains a file input, we must force
+ // the form enctype to multipart/form-data
+ if (form.find('input:file').length) {
+ form.closest('form').attr('enctype', 'multipart/form-data');
+ }
postAjaxLoad(dom);
});
d.addErrback(function (xxx) {
--- a/web/data/cubicweb.facets.js Fri Sep 11 12:42:37 2009 +0200
+++ b/web/data/cubicweb.facets.js Fri Sep 11 15:55:15 2009 +0200
@@ -66,6 +66,7 @@
extraparams['divid'] = divid;
copyParam(zipped, extraparams, 'divid');
copyParam(zipped, extraparams, 'subvid');
+ copyParam(zipped, extraparams, 'fromformfilter');
// paginate used to know if the filter box is acting, in which case we
// want to reload action box to match current selection (we don't want
// this from a table filter)
--- a/web/data/cubicweb.python.js Fri Sep 11 12:42:37 2009 +0200
+++ b/web/data/cubicweb.python.js Fri Sep 11 15:55:15 2009 +0200
@@ -83,10 +83,10 @@
var skip0 = new RegExp('^0*[0-9]+');
var parsed = {};
for (var i1=0,i2=0;i1<format.length;i1++,i2++) {
- var c1 = format[i1];
- var c2 = datestring[i2];
+ var c1 = format.charAt(i1);
+ var c2 = datestring.charAt(i2);
if (c1 == '%') {
- c1 = format[++i1];
+ c1 = format.charAt(++i1);
var data = _DATE_FORMAT_REGXES[c1].exec(datestring.substring(i2));
if (!data.length) {
return null;
--- a/web/test/unittest_breadcrumbs.py Fri Sep 11 12:42:37 2009 +0200
+++ b/web/test/unittest_breadcrumbs.py Fri Sep 11 15:55:15 2009 +0200
@@ -10,8 +10,8 @@
self.commit()
childrset = self.execute('Folder F WHERE F eid %s' % f2.eid)
self.assertEquals(childrset.get_entity(0,0).view('breadcrumbs'),
- '<a href="http://testing.fr/cubicweb/folder/715" title="">chi&ld</a>')
+ '<a href="http://testing.fr/cubicweb/folder/%s" title="">chi&ld</a>' % f1.eid)
ibc = self.vreg['components'].select('breadcrumbs', self.request(), rset=childrset)
self.assertEquals(ibc.render(),
- """<span id="breadcrumbs" class="pathbar"> > <a href="http://testing.fr/cubicweb/Folder">folder_plural</a> > <a href="http://testing.fr/cubicweb/folder/714" title="">par&ent</a> > 
-chi&ld</span>""")
+ """<span id="breadcrumbs" class="pathbar"> > <a href="http://testing.fr/cubicweb/Folder">folder_plural</a> > <a href="http://testing.fr/cubicweb/folder/%s" title="">par&ent</a> > 
+chi&ld</span>""" % f2.eid)
--- a/web/test/unittest_urlrewrite.py Fri Sep 11 12:42:37 2009 +0200
+++ b/web/test/unittest_urlrewrite.py Fri Sep 11 15:55:15 2009 +0200
@@ -106,6 +106,73 @@
self.assertEquals(len(rset), 1)
self.assertEquals(rset[0][0], self.p1.eid)
+ def test_inheritance_precedence(self):
+ RQL1 = 'Any C WHERE C is CWEType'
+ RQL2 = 'Any C WHERE C is CWUser'
+
+ class BaseRewriter(SchemaBasedRewriter):
+ rules = [
+ (rgx('/collector(.*)'),
+ rgx_action(rql=RQL1,
+ form=dict(vid='baseindex')),
+ ),
+ ]
+ class Rewriter(BaseRewriter):
+ rules = [
+ (rgx('/collector/something(/?)'),
+ rgx_action(rql=RQL2,
+ form=dict(vid='index')),
+ ),
+ ]
+
+ rewriter = Rewriter()
+ req = self.request()
+ pmid, rset = rewriter.rewrite(req, '/collector')
+ self.assertEquals(rset.rql, RQL1)
+ self.assertEquals(req.form, {'vid' : "baseindex"})
+ pmid, rset = rewriter.rewrite(req, '/collector/something')
+ self.assertEquals(rset.rql, RQL2)
+ self.assertEquals(req.form, {'vid' : "index"})
+ pmid, rset = rewriter.rewrite(req, '/collector/something/')
+ self.assertEquals(req.form, {'vid' : "index"})
+ self.assertEquals(rset.rql, RQL2)
+ pmid, rset = rewriter.rewrite(req, '/collector/somethingelse/')
+ self.assertEquals(rset.rql, RQL1)
+ self.assertEquals(req.form, {'vid' : "baseindex"})
+
+ def test_inheritance_precedence_same_rgx(self):
+ RQL1 = 'Any C WHERE C is CWEType'
+ RQL2 = 'Any C WHERE C is CWUser'
+
+ class BaseRewriter(SchemaBasedRewriter):
+ rules = [
+ (rgx('/collector(.*)'),
+ rgx_action(rql=RQL1,
+ form=dict(vid='baseindex')),
+ ),
+ ]
+ class Rewriter(BaseRewriter):
+ rules = [
+ (rgx('/collector(.*)'),
+ rgx_action(rql=RQL2,
+ form=dict(vid='index')),
+ ),
+ ]
+
+ rewriter = Rewriter()
+ req = self.request()
+ pmid, rset = rewriter.rewrite(req, '/collector')
+ self.assertEquals(rset.rql, RQL2)
+ self.assertEquals(req.form, {'vid' : "index"})
+ pmid, rset = rewriter.rewrite(req, '/collector/something')
+ self.assertEquals(rset.rql, RQL2)
+ self.assertEquals(req.form, {'vid' : "index"})
+ pmid, rset = rewriter.rewrite(req, '/collector/something/')
+ self.assertEquals(req.form, {'vid' : "index"})
+ self.assertEquals(rset.rql, RQL2)
+ pmid, rset = rewriter.rewrite(req, '/collector/somethingelse/')
+ self.assertEquals(rset.rql, RQL2)
+ self.assertEquals(req.form, {'vid' : "index"})
if __name__ == '__main__':
--- a/web/uicfg.py Fri Sep 11 12:42:37 2009 +0200
+++ b/web/uicfg.py Fri Sep 11 15:55:15 2009 +0200
@@ -166,23 +166,28 @@
def init_autoform_section(rtag, sschema, rschema, oschema, role):
if rtag.get(sschema, rschema, oschema, role) is None:
- if role == 'subject':
- card = rschema.rproperty(sschema, oschema, 'cardinality')[0]
- composed = rschema.rproperty(sschema, oschema, 'composite') == 'object'
- else:
- card = rschema.rproperty(sschema, oschema, 'cardinality')[1]
- composed = rschema.rproperty(sschema, oschema, 'composite') == 'subject'
- if sschema.is_metadata(rschema):
+ if autoform_is_inlined.get(sschema, rschema, oschema, role):
+ section = 'generated'
+ elif sschema.is_metadata(rschema):
section = 'metadata'
- elif card in '1+':
- if not rschema.is_final() and composed:
- section = 'generated'
+ else:
+ if role == 'subject':
+ card = rschema.rproperty(sschema, oschema, 'cardinality')[0]
+ composed = rschema.rproperty(sschema, oschema, 'composite') == 'object'
else:
- section = 'primary'
- elif rschema.is_final():
- section = 'secondary'
- else:
- section = 'generic'
+ card = rschema.rproperty(sschema, oschema, 'cardinality')[1]
+ composed = rschema.rproperty(sschema, oschema, 'composite') == 'subject'
+ if card in '1+':
+ if not rschema.is_final() and composed:
+ # XXX why? probably because we want it unlined, though this
+ # is not the case by default
+ section = 'generated'
+ else:
+ section = 'primary'
+ elif rschema.is_final():
+ section = 'secondary'
+ else:
+ section = 'generic'
rtag.tag_relation((sschema, rschema, oschema, role), section)
autoform_section = RelationTags('autoform_section', init_autoform_section,
--- a/web/views/basecomponents.py Fri Sep 11 12:42:37 2009 +0200
+++ b/web/views/basecomponents.py Fri Sep 11 15:55:15 2009 +0200
@@ -149,7 +149,7 @@
title = self.req.property_value('ui.site-title')
if title:
self.w(u'<span id="appliName"><a href="%s">%s</a></span>' % (
- self.req.base_url(), title))
+ self.req.base_url(), xml_escape(title)))
class SeeAlsoVComponent(component.RelatedObjectsVComponent):
--- a/web/views/basecontrollers.py Fri Sep 11 12:42:37 2009 +0200
+++ b/web/views/basecontrollers.py Fri Sep 11 15:55:15 2009 +0200
@@ -129,7 +129,8 @@
if rset:
req.set_message(req._("The view %s can not be applied to this query") % vid)
else:
- req.set_message(req._("You have no access to this view or it's not applyable to current data"))
+ req.set_message(req._("You have no access to this view or it can not "
+ "be used to display the current data."))
self.warning("the view %s can not be applied to this query", vid)
vid = vid_from_rset(req, rset, self.schema)
view = self.vreg['views'].select(vid, req, rset=rset)
--- a/web/views/basetemplates.py Fri Sep 11 12:42:37 2009 +0200
+++ b/web/views/basetemplates.py Fri Sep 11 15:55:15 2009 +0200
@@ -480,8 +480,12 @@
self.req.add_css('cubicweb.login.css')
self.w(u'<div id="%s" class="%s">' % (id, klass))
if title:
- self.w(u'<div id="loginTitle">%s</div>'
- % (self.req.property_value('ui.site-title') or u' '))
+ stitle = self.req.property_value('ui.site-title')
+ if stitle:
+ stitle = xml_escape(stitle)
+ else:
+ stitle = u' '
+ self.w(u'<div id="loginTitle">%s</div>' % stitle)
self.w(u'<div id="loginContent">\n')
if message:
--- a/web/views/editcontroller.py Fri Sep 11 12:42:37 2009 +0200
+++ b/web/views/editcontroller.py Fri Sep 11 15:55:15 2009 +0200
@@ -194,19 +194,7 @@
# NOTE: raising ValidationError here is not a good solution because
# we can't gather all errors at once. Hopefully, the new 3.6.x
# form handling will fix that
- if attrtype == 'Int':
- try:
- value = int(value)
- except ValueError:
- raise ValidationError(entity.eid,
- {attr: self.req._("invalid integer value")})
- elif attrtype == 'Float':
- try:
- value = float(value)
- except ValueError:
- raise ValidationError(entity.eid,
- {attr: self.req._("invalid float value")})
- elif attrtype == 'Boolean':
+ if attrtype == 'Boolean':
value = bool(value)
elif attrtype == 'Decimal':
value = Decimal(value)
@@ -248,6 +236,18 @@
# no specified value, skip
return
elif value is not None:
+ if attrtype == 'Int':
+ try:
+ value = int(value)
+ except ValueError:
+ raise ValidationError(entity.eid,
+ {attr: self.req._("invalid integer value")})
+ elif attrtype == 'Float':
+ try:
+ value = float(value)
+ except ValueError:
+ raise ValidationError(entity.eid,
+ {attr: self.req._("invalid float value")})
if attrtype in ('Date', 'Datetime', 'Time'):
try:
value = self.parse_datetime(value, attrtype)
--- a/web/views/tableview.py Fri Sep 11 12:42:37 2009 +0200
+++ b/web/views/tableview.py Fri Sep 11 15:55:15 2009 +0200
@@ -51,6 +51,7 @@
"""display a form to filter table's content. This should only
occurs when a context eid is given
"""
+ self.req.add_css('cubicweb.facets.css')
self.req.add_js( ('cubicweb.ajax.js', 'cubicweb.facets.js'))
# drop False / None values from vidargs
vidargs = dict((k, v) for k, v in vidargs.iteritems() if v)
@@ -58,7 +59,9 @@
xml_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(wdg.facet.id for wdg in fwidgets), baserql=baserql)
+ self.w(u'<input type="hidden" name="fromformfilter" value="1" />')
+ 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 wdg in fwidgets:
@@ -138,7 +141,6 @@
actions += self.form_filter(divid, displaycols, displayfilter,
displayactions)
elif displayfilter:
- req.add_css('cubicweb.facets.css')
actions += self.show_hide_actions(divid, True)
self.w(u'<div id="%s"' % divid)
if displayactions: