--- a/.hgtags Fri Jul 30 13:18:36 2010 +0200
+++ b/.hgtags Mon Aug 02 15:37:45 2010 +0200
@@ -145,3 +145,5 @@
8a23821dc1383e14a7e92a931b91bc6eed4d0af7 cubicweb-debian-version-3.9.2-1
900772fd9caaf068eb2fdd4544b03efec91901e6 cubicweb-version-3.9.3
ab1f9686ff3e0843b570b98f89fb5ccc8d7dec8c cubicweb-debian-version-3.9.3-1
+6cebb361dcb27ded654426b4c82f6401c862e034 cubicweb-version-3.9.4
+8d32d82134dc1d8eb0ce230191f34fd49084a168 cubicweb-debian-version-3.9.4-1
--- a/__pkginfo__.py Fri Jul 30 13:18:36 2010 +0200
+++ b/__pkginfo__.py Mon Aug 02 15:37:45 2010 +0200
@@ -22,7 +22,7 @@
modname = distname = "cubicweb"
-numversion = (3, 9, 3)
+numversion = (3, 9, 4)
version = '.'.join(str(num) for num in numversion)
description = "a repository of entities / relations for knowledge management"
--- a/debian/changelog Fri Jul 30 13:18:36 2010 +0200
+++ b/debian/changelog Mon Aug 02 15:37:45 2010 +0200
@@ -1,3 +1,9 @@
+cubicweb (3.9.4-1) unstable; urgency=low
+
+ * new upstream release
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr> Mon, 02 Aug 2010 14:25:38 +0200
+
cubicweb (3.9.3-1) unstable; urgency=low
* new upstream release
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/coding_standards_css.rst Mon Aug 02 15:37:45 2010 +0200
@@ -0,0 +1,33 @@
+CSS Coding Standards
+--------------------
+
+(Draft, to be continued)
+
+:Naming: camelCase
+
+Indentation rules
+~~~~~~~~~~~~~~~~~
+- 2 espaces avant les propriétés
+
+- pas d'espace avant les ":", un espace après
+
+- 1 seul espace entre les différentes valeurs pour une même propriété
+
+
+Documentation
+~~~~~~~~~~~~~
+Please keep rules semantically linked grouped together, with a comment about
+what they are for.
+
+Recommendation
+~~~~~~~~~~~~~~
+- Try to use existing classes rather than introduce new ones
+
+- Keep things as simple as possible while in the framework
+
+- Think about later customization by application
+
+- Avoid introducing a new CSS file for a few lines of CSS, at least while the
+ framework doesn't include packing functionalities
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/coding_standards_js.rst Mon Aug 02 15:37:45 2010 +0200
@@ -0,0 +1,37 @@
+Javascript Coding Standards
+---------------------------
+
+(Draft, to be continued)
+
+:Naming: camelCase, except for CONSTANTS
+
+Indentation rules
+~~~~~~~~~~~~~~~~~
+- espace avant accolade ouvrante
+
+- retour à la ligne après accolade ouvrante (éventuellement pas
+ de retour à la ligne s'il y a tout sur la même ligne, mais ce n'est
+ pas le cas ici.
+
+- no tabs
+
+
+Documentation
+~~~~~~~~~~~~~
+XXX explain comment format for documentation generation
+
+
+Coding
+~~~~~~
+- Don't forget 'var' before variable definition, and semi-colon (';') after **each** statement.
+- Check the firebug console for deprecation warnings
+
+
+API usage
+~~~~~~~~~
+- unless intended, use jQuery('container') rather than jqNode('container')
+
+
+See also
+~~~~~~~~
+http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml
\ No newline at end of file
--- a/i18n/en.po Fri Jul 30 13:18:36 2010 +0200
+++ b/i18n/en.po Mon Aug 02 15:37:45 2010 +0200
@@ -534,7 +534,7 @@
msgid "OR"
msgstr ""
-msgid "Parent classes:"
+msgid "Parent class:"
msgstr ""
msgid "Password"
@@ -1486,6 +1486,9 @@
msgid "context where this component should be displayed"
msgstr ""
+msgid "context where this facet should be displayed, leave empty for both"
+msgstr ""
+
msgid "control subject entity's relations order"
msgstr ""
@@ -1966,12 +1969,18 @@
msgid "display order of the component"
msgstr ""
+msgid "display order of the facet"
+msgstr ""
+
msgid "display the box or not"
msgstr ""
msgid "display the component or not"
msgstr ""
+msgid "display the facet or not"
+msgstr ""
+
msgid ""
"distinct label to distinguate between other permission entity of the same "
"name"
@@ -2017,6 +2026,9 @@
msgid "embed"
msgstr ""
+msgid "embedded html"
+msgstr ""
+
msgid "embedding this url is forbidden"
msgstr ""
--- a/i18n/es.po Fri Jul 30 13:18:36 2010 +0200
+++ b/i18n/es.po Mon Aug 02 15:37:45 2010 +0200
@@ -542,7 +542,7 @@
msgid "OR"
msgstr "O"
-msgid "Parent classes:"
+msgid "Parent class:"
msgstr ""
msgid "Password"
@@ -1519,6 +1519,9 @@
msgid "context where this component should be displayed"
msgstr "Contexto en el cual el componente debe aparecer en el sistema"
+msgid "context where this facet should be displayed, leave empty for both"
+msgstr ""
+
msgid "control subject entity's relations order"
msgstr "Controla el orden de relaciones de la entidad sujeto"
@@ -2009,12 +2012,18 @@
msgid "display order of the component"
msgstr "Orden de aparición del componente"
+msgid "display order of the facet"
+msgstr ""
+
msgid "display the box or not"
msgstr "Mostrar la caja o no"
msgid "display the component or not"
msgstr "Mostrar el componente o no"
+msgid "display the facet or not"
+msgstr ""
+
msgid ""
"distinct label to distinguate between other permission entity of the same "
"name"
@@ -2062,6 +2071,9 @@
msgid "embed"
msgstr "Incrustrado"
+msgid "embedded html"
+msgstr ""
+
msgid "embedding this url is forbidden"
msgstr "La inclusión de este url esta prohibida"
--- a/i18n/fr.po Fri Jul 30 13:18:36 2010 +0200
+++ b/i18n/fr.po Mon Aug 02 15:37:45 2010 +0200
@@ -553,8 +553,8 @@
msgid "OR"
msgstr "OU"
-msgid "Parent classes:"
-msgstr "Classes parentes :"
+msgid "Parent class:"
+msgstr "Classe parente"
msgid "Password"
msgstr "Mot de passe"
@@ -1540,6 +1540,9 @@
msgid "context where this component should be displayed"
msgstr "contexte où ce composant doit être affiché"
+msgid "context where this facet should be displayed, leave empty for both"
+msgstr ""
+
msgid "control subject entity's relations order"
msgstr "contrôle l'ordre des relations de l'entité sujet"
@@ -2044,12 +2047,18 @@
msgid "display order of the component"
msgstr "ordre d'affichage du composant"
+msgid "display order of the facet"
+msgstr "ordre d'affichage de la facette"
+
msgid "display the box or not"
msgstr "afficher la boîte ou non"
msgid "display the component or not"
msgstr "afficher le composant ou non"
+msgid "display the facet or not"
+msgstr "afficher la facette ou non"
+
msgid ""
"distinct label to distinguate between other permission entity of the same "
"name"
@@ -2097,6 +2106,9 @@
msgid "embed"
msgstr "embarqué"
+msgid "embedded html"
+msgstr "HTML contenu"
+
msgid "embedding this url is forbidden"
msgstr "l'inclusion de cette url est interdite"
--- a/server/sources/rql2sql.py Fri Jul 30 13:18:36 2010 +0200
+++ b/server/sources/rql2sql.py Mon Aug 02 15:37:45 2010 +0200
@@ -101,15 +101,12 @@
subquery. This function check this and rewrite the rql syntax tree if
necessary (in place). Return a boolean telling if the tree has been modified
"""
- torewrite = set()
modified = False
for varname in tuple(unstable):
var = select.defined_vars[varname]
if not var.stinfo.get('optrelations'):
continue
- modified = True
unstable.remove(varname)
- torewrite.add(var)
newselect = Select()
newselect.need_distinct = False
myunion = Union()
@@ -139,10 +136,17 @@
var.stinfo['rhsrelations'].add(newrel)
if rel.optional in ('right', 'both'):
var.add_optional_relation(newrel)
+ if not select.where and not modified:
+ # oops, generated the same thing as the original select....
+ # restore original query, else we'll indefinitly loop
+ for var, rel in towrap_rels:
+ select.add_restriction(rel)
+ continue
+ modified = True
# extract subquery solutions
mysolutions = [sol.copy() for sol in solutions]
cleanup_solutions(newselect, mysolutions)
- newselect.set_possible_types(solutions)
+ newselect.set_possible_types(mysolutions)
# full sub-query
aliases = [VariableRef(select.get_variable(avar.name, i))
for i, avar in enumerate(newselect.selection)]
--- a/server/test/unittest_querier.py Fri Jul 30 13:18:36 2010 +0200
+++ b/server/test/unittest_querier.py Mon Aug 02 15:37:45 2010 +0200
@@ -836,7 +836,7 @@
rset = self.execute('Any X, NOW - CD WHERE X is Personne, X creation_date CD')
self.failUnlessEqual(rset.description[0][1], 'Interval')
- def test_select_subquery_aggregat(self):
+ def test_select_subquery_aggregat_1(self):
# percent users by groups
self.execute('SET X in_group G WHERE G name "users"')
rset = self.execute('Any GN, COUNT(X)*100/T GROUPBY GN ORDERBY 2,1'
@@ -845,6 +845,17 @@
self.assertEquals(rset.rows, [[u'guests', 50], [u'managers', 50], [u'users', 100]])
self.assertEquals(rset.description, [('String', 'Int'), ('String', 'Int'), ('String', 'Int')])
+ def test_select_subquery_aggregat_2(self):
+ expected = self.execute('Any X, 0, COUNT(T) GROUPBY X '
+ 'WHERE X is Workflow, T transition_of X').rows
+ rset = self.execute('''
+Any P1,B,E WHERE P1 identity P2 WITH
+ P1,B BEING (Any P,COUNT(T) GROUPBY P WHERE P is Workflow, T is Transition,
+ T? transition_of P, T type "auto"),
+ P2,E BEING (Any P,COUNT(T) GROUPBY P WHERE P is Workflow, T is Transition,
+ T? transition_of P, T type "normal")''')
+ self.assertEquals(sorted(rset.rows), sorted(expected))
+
def test_select_subquery_const(self):
rset = self.execute('Any X WITH X BEING ((Any NULL) UNION (Any "toto"))')
self.assertEquals(rset.rows, [[None], ['toto']])
--- a/tags.py Fri Jul 30 13:18:36 2010 +0200
+++ b/tags.py Mon Aug 02 15:37:45 2010 +0200
@@ -48,6 +48,7 @@
tr = tag('tr')
th = tag('th')
td = tag('td')
+iframe = tag('iframe')
def select(name, id=None, multiple=False, options=[], **attrs):
if multiple:
--- a/web/test/unittest_viewselector.py Fri Jul 30 13:18:36 2010 +0200
+++ b/web/test/unittest_viewselector.py Mon Aug 02 15:37:45 2010 +0200
@@ -418,17 +418,27 @@
def test_score_entity_selector(self):
image = self.request().create_entity('File', data_name=u'bim.png', data=Binary('bim'))
- # image primary view priority
+ # image/ehtml primary view priority
req = self.request()
rset = req.execute('File X WHERE X data_name "bim.png"')
self.assertIsInstance(self.vreg['views'].select('image', req, rset=rset),
idownloadable.ImageView)
- fileobj = self.request().create_entity('File', data_name=u'bim.txt', data=Binary('bim'))
- # image primary view priority
+ self.assertRaises(NoSelectableObject, self.vreg['views'].select, 'ehtml', req, rset=rset)
+
+ fileobj = self.request().create_entity('File', data_name=u'bim.html', data=Binary('<html>bam</html'))
+ # image/ehtml primary view priority
+ req = self.request()
+ rset = req.execute('File X WHERE X data_name "bim.html"')
+ self.assertIsInstance(self.vreg['views'].select('ehtml', req, rset=rset),
+ idownloadable.EHTMLView)
+ self.assertRaises(NoSelectableObject, self.vreg['views'].select, 'image', req, rset=rset)
+
+ fileobj = self.request().create_entity('File', data_name=u'bim.txt', data=Binary('boum'))
+ # image/ehtml primary view priority
req = self.request()
rset = req.execute('File X WHERE X data_name "bim.txt"')
self.assertRaises(NoSelectableObject, self.vreg['views'].select, 'image', req, rset=rset)
-
+ self.assertRaises(NoSelectableObject, self.vreg['views'].select, 'ehtml', req, rset=rset)
def _test_view(self, vid, rql, args):
--- a/web/views/idownloadable.py Fri Jul 30 13:18:36 2010 +0200
+++ b/web/views/idownloadable.py Mon Aug 02 15:37:45 2010 +0200
@@ -121,6 +121,10 @@
self.wview('image', entity.cw_rset, row=entity.cw_row, col=entity.cw_col,
link=True, klass='contentimage')
super(IDownloadablePrimaryView, self).render_entity_attributes(entity)
+ elif contenttype.endswith('html'):
+ self.wview('downloadlink', entity.cw_rset, title=self._cw._('download'), row=entity.cw_row)
+ self.wview('ehtml', entity.cw_rset, row=entity.cw_row, col=entity.cw_col,
+ height='600px', width='100%')
else:
super(IDownloadablePrimaryView, self).render_entity_attributes(entity)
self.wview('downloadlink', entity.cw_rset, title=self._cw._('download'), row=entity.cw_row)
@@ -156,11 +160,10 @@
(url, name, durl, self._cw._('download')))
-class ImageView(EntityView):
- __regid__ = 'image'
- __select__ = has_mimetype('image/')
+class AbstractEmbeddedView(EntityView):
+ __abstract__ = True
- title = _('image')
+ _embedding_tag = None
def call(self, **kwargs):
rset = self.cw_rset
@@ -172,13 +175,29 @@
def cell_call(self, row, col, link=False, **kwargs):
entity = self.cw_rset.get_entity(row, col)
adapter = entity.cw_adapt_to('IDownloadable')
- imgtag = tags.img(src=adapter.download_url(),
- alt=(self._cw._('download %s') % adapter.download_file_name()),
- **kwargs)
+ tag = self._embedding_tag(src=adapter.download_url(),
+ alt=(self._cw._('download %s') % adapter.download_file_name()),
+ **kwargs)
if link:
- self.w(u'<a href="%s">%s</a>' % (entity.absolute_url(vid='download'),
- imgtag))
+ self.w(u'<a href="%s">%s</a>' % (adapter.download_url(), tag))
else:
- self.w(imgtag)
+ self.w(tag)
+class ImageView(AbstractEmbeddedView):
+ __regid__ = 'image'
+ __select__ = has_mimetype('image/')
+
+ title = _('image')
+ _embedding_tag = tags.img
+
+
+class EHTMLView(AbstractEmbeddedView):
+ __regid__ = 'ehtml'
+ __select__ = has_mimetype('text/html')
+
+ title = _('embedded html')
+ _embedding_tag = tags.iframe
+
+
+