# HG changeset patch # User Sylvain Thénault # Date 1252677454 -7200 # Node ID bd0126d17e83583802f1e2b3ef1a61010c4948aa # Parent edfe43ceaa3549219aae50ad9aa5886ac8f43572# Parent 613064b49331bc3f2ed0fe55e7af7acac4e667a6 backport 3.5 diff -r edfe43ceaa35 -r bd0126d17e83 .hgtags --- a/.hgtags Thu Sep 10 08:13:22 2009 +0200 +++ b/.hgtags Fri Sep 11 15:57:34 2009 +0200 @@ -64,3 +64,5 @@ 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 edfe43ceaa35 -r bd0126d17e83 __pkginfo__.py diff -r edfe43ceaa35 -r bd0126d17e83 common/uilib.py --- a/common/uilib.py Thu Sep 10 08:13:22 2009 +0200 +++ b/common/uilib.py Fri Sep 11 15:57:34 2009 +0200 @@ -31,7 +31,7 @@ return 'Any X WHERE X eid %s' % eid -def printable_value(req, attrtype, value, props=None, displaytime=True): +def printable_value(req, attrtype, value, props=None): """return a displayable value (i.e. unicode string)""" if value is None or attrtype == 'Bytes': return u'' @@ -46,8 +46,6 @@ if attrtype == 'Time': return ustrftime(value, req.property_value('ui.time-format')) if attrtype == 'Datetime': - if not displaytime: - return ustrftime(value, req.property_value('ui.date-format')) return ustrftime(value, req.property_value('ui.datetime-format')) if attrtype == 'Boolean': if value: diff -r edfe43ceaa35 -r bd0126d17e83 cwctl.py --- a/cwctl.py Thu Sep 10 08:13:22 2009 +0200 +++ b/cwctl.py Fri Sep 11 15:57:34 2009 +0200 @@ -153,6 +153,7 @@ else: self.run_arg(appid) + # base commands ############################################################### class ListCommand(Command): @@ -366,7 +367,7 @@ # instance commands ######################################################## -class StartInstanceCommand(InstanceCommand): +class StartInstanceCommand(InstanceCommandFork): """Start the given instances. If no instance is given, start them all. ... @@ -398,17 +399,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'] @@ -416,8 +415,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): @@ -470,8 +471,7 @@ print 'instance %s stopped' % appid -class RestartInstanceCommand(StartInstanceCommand, - StopInstanceCommand): +class RestartInstanceCommand(StartInstanceCommand): """Restart the given instances. ... @@ -490,14 +490,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) @@ -507,9 +505,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): @@ -560,9 +557,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 @@ -618,10 +613,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 @@ -668,7 +659,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 @@ -691,7 +682,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 edfe43ceaa35 -r bd0126d17e83 cwvreg.py --- a/cwvreg.py Thu Sep 10 08:13:22 2009 +0200 +++ b/cwvreg.py Fri Sep 11 15:57:34 2009 +0200 @@ -138,6 +138,7 @@ 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] diff -r edfe43ceaa35 -r bd0126d17e83 debian/changelog --- a/debian/changelog Thu Sep 10 08:13:22 2009 +0200 +++ b/debian/changelog Fri Sep 11 15:57:34 2009 +0200 @@ -1,3 +1,15 @@ +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 diff -r edfe43ceaa35 -r bd0126d17e83 doc/book/en/development/entityclasses/load-sort.rst --- a/doc/book/en/development/entityclasses/load-sort.rst Thu Sep 10 08:13:22 2009 +0200 +++ b/doc/book/en/development/entityclasses/load-sort.rst Fri Sep 11 15:57:34 2009 +0200 @@ -16,18 +16,30 @@ `None` if we do not want to sort on the attribute given in the parameter. By default, the entities are sorted according to their creation date. -* The class method `fetch_unrelated_order(attr, var)` is similar to the - method `fetch_order` except that it is essentially used to control - the sorting of drop-down lists enabling relations creation in - the editing view of an entity. +* The class method `fetch_unrelated_order(attr, var)` is similar to + the method `fetch_order` except that it is essentially used to + control the sorting of drop-down lists enabling relations creation + in the editing view of an entity. The default implementation uses + the modification date. Here's how to adapt it for one entity (sort + on the name attribute): :: + + class MyEntity(AnyEntity): + fetch_attrs = ('modification_date', 'name') + + @classmethod + def fetch_unrelated_order(cls, attr, var): + if attr == 'name': + return '%s ASC' % var + return None + The function `fetch_config(fetchattrs, mainattr=None)` simplifies the definition of the attributes to load and the sorting by returning a -list of attributes to pre-load (considering automatically the attributes -of `AnyEntity`) and a sorting function based on the main attribute -(the second parameter if specified otherwisethe first attribute from -the list `fetchattrs`). -This function is defined in `cubicweb.entities`. +list of attributes to pre-load (considering automatically the +attributes of `AnyEntity`) and a sorting function based on the main +attribute (the second parameter if specified, otherwise the first +attribute from the list `fetchattrs`). This function is defined in +`cubicweb.entities`. For example: :: diff -r edfe43ceaa35 -r bd0126d17e83 entity.py --- a/entity.py Thu Sep 10 08:13:22 2009 +0200 +++ b/entity.py Fri Sep 11 15:57:34 2009 +0200 @@ -321,7 +321,7 @@ return value def printable_value(self, attr, value=_marker, attrtype=None, - format='text/html', displaytime=True): + format='text/html'): """return a displayable value (i.e. unicode string) which may contains html tags """ @@ -351,7 +351,7 @@ return self.mtc_transform(value.getvalue(), attrformat, format, encoding) return u'' - value = printable_value(self.req, attrtype, value, props, displaytime) + value = printable_value(self.req, attrtype, value, props) if format == 'text/html': value = xml_escape(value) return value diff -r edfe43ceaa35 -r bd0126d17e83 etwist/server.py --- a/etwist/server.py Thu Sep 10 08:13:22 2009 +0200 +++ b/etwist/server.py Fri Sep 11 15:57:34 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 edfe43ceaa35 -r bd0126d17e83 etwist/twctl.py --- a/etwist/twctl.py Thu Sep 10 08:13:22 2009 +0200 +++ b/etwist/twctl.py Fri Sep 11 15:57:34 2009 +0200 @@ -17,7 +17,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 edfe43ceaa35 -r bd0126d17e83 server/querier.py --- a/server/querier.py Thu Sep 10 08:13:22 2009 +0200 +++ b/server/querier.py Fri Sep 11 15:57:34 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 edfe43ceaa35 -r bd0126d17e83 server/serverctl.py --- a/server/serverctl.py Thu Sep 10 08:13:22 2009 +0200 +++ b/server/serverctl.py Fri Sep 11 15:57:34 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 edfe43ceaa35 -r bd0126d17e83 skeleton/migration/postcreate.py --- a/skeleton/migration/postcreate.py Thu Sep 10 08:13:22 2009 +0200 +++ b/skeleton/migration/postcreate.py Fri Sep 11 15:57:34 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 edfe43ceaa35 -r bd0126d17e83 web/test/data/bootstrap_cubes --- a/web/test/data/bootstrap_cubes Thu Sep 10 08:13:22 2009 +0200 +++ b/web/test/data/bootstrap_cubes Fri Sep 11 15:57:34 2009 +0200 @@ -1,1 +1,1 @@ -file, blog, tag +file, blog, tag, folder diff -r edfe43ceaa35 -r bd0126d17e83 web/test/unittest_breadcrumbs.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/test/unittest_breadcrumbs.py Fri Sep 11 15:57:34 2009 +0200 @@ -0,0 +1,17 @@ +from cubicweb.devtools.testlib import WebTest + +class BreadCrumbsTC(WebTest): + + def test_base(self): + f1 = self.add_entity('Folder', name=u'par&ent') + f2 = self.add_entity('Folder', name=u'chi&ld') + self.execute('SET F2 filed_under F1 WHERE F1 eid %(f1)s, F2 eid %(f2)s', + {'f1' : f1.eid, 'f2' : f2.eid}) + self.commit() + childrset = self.execute('Folder F WHERE F eid %s' % f2.eid) + self.assertEquals(childrset.get_entity(0,0).view('breadcrumbs'), + 'chi&ld' % f1.eid) + ibc = self.vreg['components'].select('breadcrumbs', self.request(), rset=childrset) + self.assertEquals(ibc.render(), + """ > folder_plural > par&ent >  +chi&ld""" % f2.eid) diff -r edfe43ceaa35 -r bd0126d17e83 web/test/unittest_form.py --- a/web/test/unittest_form.py Thu Sep 10 08:13:22 2009 +0200 +++ b/web/test/unittest_form.py Fri Sep 11 15:57:34 2009 +0200 @@ -54,6 +54,7 @@ unrelated = [reid for rview, reid in form2.object_relation_vocabulary('tags')] self.failIf(t.eid in unrelated, unrelated) + def test_form_field_vocabulary_new_entity(self): e = self.vreg['etypes'].etype_class('CWUser')(self.request()) form = EntityFieldsForm(e.req, None, entity=e) diff -r edfe43ceaa35 -r bd0126d17e83 web/test/unittest_urlrewrite.py --- a/web/test/unittest_urlrewrite.py Thu Sep 10 08:13:22 2009 +0200 +++ b/web/test/unittest_urlrewrite.py Fri Sep 11 15:57:34 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 edfe43ceaa35 -r bd0126d17e83 web/uicfg.py --- a/web/uicfg.py Thu Sep 10 08:13:22 2009 +0200 +++ b/web/uicfg.py Fri Sep 11 15:57:34 2009 +0200 @@ -166,6 +166,7 @@ else: self.setdefault(eschema, 'application') + indexview_etype_section = InitializableDict(EmailAddress='subobject', CWUser='system', CWGroup='system', diff -r edfe43ceaa35 -r bd0126d17e83 web/views/basecomponents.py --- a/web/views/basecomponents.py Thu Sep 10 08:13:22 2009 +0200 +++ b/web/views/basecomponents.py Fri Sep 11 15:57:34 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 edfe43ceaa35 -r bd0126d17e83 web/views/basetemplates.py --- a/web/views/basetemplates.py Thu Sep 10 08:13:22 2009 +0200 +++ b/web/views/basetemplates.py Fri Sep 11 15:57:34 2009 +0200 @@ -479,8 +479,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 edfe43ceaa35 -r bd0126d17e83 web/views/baseviews.py --- a/web/views/baseviews.py Thu Sep 10 08:13:22 2009 +0200 +++ b/web/views/baseviews.py Fri Sep 11 15:57:34 2009 +0200 @@ -66,7 +66,7 @@ _('%d minutes') _('%d seconds') - def cell_call(self, row, col, props=None, displaytime=False, format='text/html'): + def cell_call(self, row, col, props=None, format='text/html'): etype = self.rset.description[row][col] value = self.rset.rows[row][col] @@ -98,7 +98,7 @@ else: self.w(self.req.__('%%d%sseconds' % space) % int(value.seconds)) return - self.wdata(printable_value(self.req, etype, value, props, displaytime=displaytime)) + self.wdata(printable_value(self.req, etype, value, props)) # XXX deprecated diff -r edfe43ceaa35 -r bd0126d17e83 web/views/csvexport.py --- a/web/views/csvexport.py Thu Sep 10 08:13:22 2009 +0200 +++ b/web/views/csvexport.py Fri Sep 11 15:57:34 2009 +0200 @@ -51,7 +51,7 @@ row=rowindex, col=colindex) else: content = self.view('final', rset, - displaytime=True, format='text/plain', + format='text/plain', row=rowindex, col=colindex) csvrow.append(content) writer.writerow(csvrow) diff -r edfe43ceaa35 -r bd0126d17e83 web/views/editcontroller.py --- a/web/views/editcontroller.py Thu Sep 10 08:13:22 2009 +0200 +++ b/web/views/editcontroller.py Fri Sep 11 15:57:34 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 value and attrtype == 'Int': - try: - value = int(value) - except ValueError: - raise ValidationError(entity.eid, - {attr: self.req._("invalid integer value")}) - elif value and 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 edfe43ceaa35 -r bd0126d17e83 web/views/editviews.py --- a/web/views/editviews.py Thu Sep 10 08:13:22 2009 +0200 +++ b/web/views/editviews.py Fri Sep 11 15:57:34 2009 +0200 @@ -198,9 +198,9 @@ """same as FinalView but enables inplace-edition when possible""" id = 'editable-final' - def cell_call(self, row, col, props=None, displaytime=False): + def cell_call(self, row, col, props=None): entity, rtype = self.rset.related_entity(row, col) if entity is not None: self.w(entity.view('reledit', rtype=rtype)) else: - super(EditableFinalView, self).cell_call(row, col, props, displaytime) + super(EditableFinalView, self).cell_call(row, col, props) diff -r edfe43ceaa35 -r bd0126d17e83 web/views/ibreadcrumbs.py --- a/web/views/ibreadcrumbs.py Thu Sep 10 08:13:22 2009 +0200 +++ b/web/views/ibreadcrumbs.py Fri Sep 11 15:57:34 2009 +0200 @@ -56,9 +56,9 @@ def wpath_part(self, part, contextentity, last=False): if isinstance(part, Entity): if last and part.eid == contextentity.eid: - part.view('breadcrumbtext', w=self.w) + self.w(xml_escape(part.view('breadcrumbtext'))) else: - part.view('breadcrumbs', w=self.w) + self.w(part.view('breadcrumbs')) elif isinstance(part, tuple): url, title = part textsize = self.req.property_value('navigation.short-line-size') @@ -99,8 +99,9 @@ def cell_call(self, row, col): entity = self.rset.get_entity(row, col) desc = xml_escape(uilib.cut(entity.dc_description(), 50)) - self.w(tags.a(entity.view('breadcrumbtext'), href=entity.absolute_url(), - title=desc)) + # XXX remember camember : tags.a autoescapes ! + self.w(tags.a(entity.view('breadcrumbtext'), + href=entity.absolute_url(), title=desc)) class BreadCrumbTextView(EntityView): diff -r edfe43ceaa35 -r bd0126d17e83 web/views/xmlrss.py --- a/web/views/xmlrss.py Thu Sep 10 08:13:22 2009 +0200 +++ b/web/views/xmlrss.py Fri Sep 11 15:57:34 2009 +0200 @@ -95,8 +95,8 @@ val = self.view('textincontext', rset, row=rowindex, col=colindex) else: - val = self.view('final', rset, displaytime=True, - row=rowindex, col=colindex, format='text/plain') + val = self.view('final', rset, row=rowindex, + col=colindex, format='text/plain') w(simple_sgml_tag(tag, val, **attrs)) w(u' \n') w(u'\n' % self.xml_root)