# HG changeset patch # User Sylvain Thénault # Date 1252677315 -7200 # Node ID 613064b49331bc3f2ed0fe55e7af7acac4e667a6 # Parent e7ae807554d9d901e249fc7e7b039d82d9601182# Parent e916f1e856c83aced0fe73f7ae9068e37edcc38c backport stable branch diff -r e7ae807554d9 -r 613064b49331 .hgtags --- 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 diff -r e7ae807554d9 -r 613064b49331 __pkginfo__.py diff -r e7ae807554d9 -r 613064b49331 _exceptions.py --- 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): diff -r e7ae807554d9 -r 613064b49331 cwctl.py --- 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. ... @@ -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. ... @@ -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 diff -r e7ae807554d9 -r 613064b49331 cwvreg.py --- 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'] diff -r e7ae807554d9 -r 613064b49331 debian/changelog --- 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 Fri, 11 Sep 2009 14:27:39 +0200 + +cubicweb (3.4.8-1) unstable; urgency=low + + * new upstream release + + -- Sylvain Thénault Thu, 10 Sep 2009 15:27:17 +0200 + +cubicweb (3.4.7-1) unstable; urgency=low + + * new upstream release + + -- Sylvain Thénault Wed, 09 Sep 2009 14:08:41 +0200 + cubicweb (3.4.6-1) unstable; urgency=low * new upstream release diff -r e7ae807554d9 -r 613064b49331 doc/book/en/B0015-define-permissions.en.txt --- 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 " diff -r e7ae807554d9 -r 613064b49331 doc/book/en/development/datamodel/definition.rst --- 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 " diff -r e7ae807554d9 -r 613064b49331 entity.py --- 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: diff -r e7ae807554d9 -r 613064b49331 etwist/server.py --- 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) diff -r e7ae807554d9 -r 613064b49331 etwist/twctl.py --- 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) diff -r e7ae807554d9 -r 613064b49331 i18n/en.po --- 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 "" diff -r e7ae807554d9 -r 613064b49331 i18n/es.po --- 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" diff -r e7ae807554d9 -r 613064b49331 i18n/fr.po --- 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" diff -r e7ae807554d9 -r 613064b49331 server/querier.py --- 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) diff -r e7ae807554d9 -r 613064b49331 server/serverctl.py --- 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): diff -r e7ae807554d9 -r 613064b49331 server/session.py --- 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): diff -r e7ae807554d9 -r 613064b49331 skeleton/migration/postcreate.py --- 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', "") + diff -r e7ae807554d9 -r 613064b49331 sobjects/supervising.py --- 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 diff -r e7ae807554d9 -r 613064b49331 test/unittest_entity.py --- 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): diff -r e7ae807554d9 -r 613064b49331 web/data/cubicweb.edition.js --- 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) { diff -r e7ae807554d9 -r 613064b49331 web/data/cubicweb.facets.js --- 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) diff -r e7ae807554d9 -r 613064b49331 web/data/cubicweb.python.js --- 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;i1chi&ld') + 'chi&ld' % f1.eid) ibc = self.vreg['components'].select('breadcrumbs', self.request(), rset=childrset) self.assertEquals(ibc.render(), - """ > folder_plural > par&ent >  -chi&ld""") + """ > folder_plural > par&ent >  +chi&ld""" % f2.eid) diff -r e7ae807554d9 -r 613064b49331 web/test/unittest_urlrewrite.py --- 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__': diff -r e7ae807554d9 -r 613064b49331 web/uicfg.py --- 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, diff -r e7ae807554d9 -r 613064b49331 web/views/basecomponents.py --- 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'%s' % ( - self.req.base_url(), title)) + self.req.base_url(), xml_escape(title))) class SeeAlsoVComponent(component.RelatedObjectsVComponent): diff -r e7ae807554d9 -r 613064b49331 web/views/basecontrollers.py --- 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) diff -r e7ae807554d9 -r 613064b49331 web/views/basetemplates.py --- 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'
' % (id, klass)) if title: - self.w(u'
%s
' - % (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'
%s
' % stitle) self.w(u'
\n') if message: diff -r e7ae807554d9 -r 613064b49331 web/views/editcontroller.py --- 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) diff -r e7ae807554d9 -r 613064b49331 web/views/ibreadcrumbs.py diff -r e7ae807554d9 -r 613064b49331 web/views/tableview.py --- 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'
' % (divid, hidden and 'hidden' or '')) self.w(u'' % divid) - filter_hiddens(self.w, facets=','.join(wdg.facet.id for wdg in fwidgets), baserql=baserql) + self.w(u'') + filter_hiddens(self.w, facets=','.join(wdg.facet.id for wdg in fwidgets), + baserql=baserql) self.w(u'\n') self.w(u'\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'