--- a/appobject.py Tue May 05 12:07:42 2009 +0200
+++ b/appobject.py Tue May 05 17:13:37 2009 +0200
@@ -8,8 +8,6 @@
from datetime import datetime, timedelta
-from simplejson import dumps
-
from logilab.common.decorators import classproperty
from logilab.common.deprecation import obsolete
@@ -244,6 +242,7 @@
"""register the given user callback and return an url to call it ready to be
inserted in html
"""
+ from simplejson import dumps
self.req.add_js('cubicweb.ajax.js')
cbname = self.req.register_onetime_callback(cb, *args)
msg = dumps(msg or '')
@@ -256,7 +255,7 @@
"""render a precompiled page template with variables in the given
dictionary as context
"""
- from cubicweb.common.tal import CubicWebContext
+ from cubicweb.ext.tal import CubicWebContext
context = CubicWebContext()
context.update({'self': self, 'rset': self.rset, '_' : self.req._,
'req': self.req, 'user': self.req.user})
--- a/common/tags.py Tue May 05 12:07:42 2009 +0200
+++ b/common/tags.py Tue May 05 17:13:37 2009 +0200
@@ -36,8 +36,9 @@
attrs['multiple'] = 'multiple'
if id:
attrs['id'] = id
- html = [u'<select name="%s" %s>' % (
- name, ' '.join('%s="%s"' % kv for kv in attrs.items()))]
+ attrs['name'] = name
+ html = [u'<select %s>' % ' '.join('%s="%s"' % kv
+ for kv in sorted(attrs.items()))]
html += options
html.append(u'</select>')
return u'\n'.join(html)
--- a/common/test/unittest_rest.py Tue May 05 12:07:42 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-from logilab.common.testlib import unittest_main
-from cubicweb.devtools.apptest import EnvBasedTC
-
-from cubicweb.common.rest import rest_publish
-
-class RestTC(EnvBasedTC):
- def context(self):
- return self.execute('CWUser X WHERE X login "admin"').get_entity(0, 0)
-
- def test_eid_role(self):
- context = self.context()
- self.assertEquals(rest_publish(context, ':eid:`%s`' % context.eid),
- '<p><a class="reference" href="http://testing.fr/cubicweb/euser/admin">#%s</a></p>\n' % context.eid)
- self.assertEquals(rest_publish(context, ':eid:`%s:some text`' % context.eid),
- '<p><a class="reference" href="http://testing.fr/cubicweb/euser/admin">some text</a></p>\n')
-
- def test_card_role_create(self):
- self.assertEquals(rest_publish(self.context(), ':card:`index`'),
- '<p><a class="reference" href="http://testing.fr/cubicweb/view?etype=Card&wikiid=index&vid=creation">index</a></p>\n')
-
- def test_card_role_link(self):
- self.add_entity('Card', wikiid=u'index', title=u'Site index page', synopsis=u'yo')
- self.assertEquals(rest_publish(self.context(), ':card:`index`'),
- '<p><a class="reference" href="http://testing.fr/cubicweb/card/index">index</a></p>\n')
-
- def test_bad_rest_no_crash(self):
- data = rest_publish(self.context(), '''
-| card | implication |
---------------------------
-| 1-1 | N1 = N2 |
-| 1-? | N1 <= N2 |
-| 1-+ | N1 >= N2 |
-| 1-* | N1>0 => N2>0 |
---------------------------
-| ?-? | N1 # N2 |
-| ?-+ | N1 >= N2 |
-| ?-* | N1 # N2 |
---------------------------
-| +-+ | N1>0 => N2>0 et |
-| | N2>0 => N1>0 |
-| +-* | N1>+ => N2>0 |
---------------------------
-| *-* | N1#N2 |
---------------------------
-
-''')
-
-if __name__ == '__main__':
- unittest_main()
--- a/common/test/unittest_uilib.py Tue May 05 12:07:42 2009 +0200
+++ b/common/test/unittest_uilib.py Tue May 05 17:13:37 2009 +0200
@@ -21,7 +21,7 @@
for text, expected in data:
got = uilib.remove_html_tags(text)
self.assertEquals(got, expected)
-
+
def test_fallback_safe_cut(self):
self.assertEquals(uilib.fallback_safe_cut(u'ab <a href="hello">cd</a>', 4), u'ab c...')
self.assertEquals(uilib.fallback_safe_cut(u'ab <a href="hello">cd</a>', 5), u'ab <a href="hello">cd</a>')
@@ -29,7 +29,7 @@
self.assertEquals(uilib.fallback_safe_cut(u'ab <a href="hello">&d</a> ef', 5), u'ab &d...')
self.assertEquals(uilib.fallback_safe_cut(u'ab <a href="hello">ìd</a>', 4), u'ab ì...')
self.assertEquals(uilib.fallback_safe_cut(u'& <a href="hello">&d</a> ef', 4), u'& &d...')
-
+
def test_lxml_safe_cut(self):
self.assertEquals(uilib.safe_cut(u'aaa<div>aaad</div> ef', 4), u'<p>aaa</p><div>a...</div>')
self.assertEquals(uilib.safe_cut(u'aaa<div>aaad</div> ef', 7), u'<p>aaa</p><div>aaad</div>...')
@@ -75,18 +75,6 @@
got = uilib.text_cut(text, 30)
self.assertEquals(got, expected)
- def test_ajax_replace_url(self):
- # NOTE: for the simplest use cases, we could use doctest
- arurl = uilib.ajax_replace_url
- self.assertEquals(arurl('foo', 'Person P'),
- "javascript: replacePageChunk('foo', 'Person%20P');")
- self.assertEquals(arurl('foo', 'Person P', 'oneline'),
- "javascript: replacePageChunk('foo', 'Person%20P', 'oneline');")
- self.assertEquals(arurl('foo', 'Person P', 'oneline', name='bar', age=12),
- 'javascript: replacePageChunk(\'foo\', \'Person%20P\', \'oneline\', {"age": 12, "name": "bar"});')
- self.assertEquals(arurl('foo', 'Person P', name='bar', age=12),
- 'javascript: replacePageChunk(\'foo\', \'Person%20P\', \'null\', {"age": 12, "name": "bar"});')
-
tree = ('root', (
('child_1_1', (
('child_2_1', ()), ('child_2_2', (
@@ -116,18 +104,18 @@
for child in tuple[1]:
n.append(make_tree(child))
return n
-
+
class UIlibHTMLGenerationTC(TestCase):
""" a basic tree node, caracterised by an id"""
def setUp(self):
- """ called before each test from this class """
+ """ called before each test from this class """
self.o = make_tree(tree)
def test_generated_html(self):
s = uilib.render_HTML_tree(self.o, selected_node="child_2_2")
self.assertTextEqual(s, generated_html)
-
-
+
+
if __name__ == '__main__':
unittest_main()
--- a/common/uilib.py Tue May 05 12:07:42 2009 +0200
+++ b/common/uilib.py Tue May 05 17:13:37 2009 +0200
@@ -10,11 +10,9 @@
__docformat__ = "restructuredtext en"
import csv
-import decimal
import re
-from datetime import datetime, date, timedelta
from urllib import quote as urlquote
-from cStringIO import StringIO
+from StringIO import StringIO
from logilab.mtconverter import html_escape, html_unescape
@@ -216,7 +214,7 @@
except KeyError:
pass
value += u' ' + u' '.join(u'%s="%s"' % (attr, html_escape(unicode(value)))
- for attr, value in attrs.items()
+ for attr, value in sorted(attrs.items())
if value is not None)
if content:
if escapecontent:
@@ -239,31 +237,6 @@
"""builds a HTML link that uses the js toggleVisibility function"""
return u'<a href="%s">%s</a>' % (toggle_action(nodeid), label)
-def ajax_replace_url(nodeid, rql, vid=None, swap=False, **extraparams):
- """builds a replacePageChunk-like url
- >>> ajax_replace_url('foo', 'Person P')
- "javascript: replacePageChunk('foo', 'Person%20P');"
- >>> ajax_replace_url('foo', 'Person P', 'oneline')
- "javascript: replacePageChunk('foo', 'Person%20P', 'oneline');"
- >>> ajax_replace_url('foo', 'Person P', 'oneline', name='bar', age=12)
- "javascript: replacePageChunk('foo', 'Person%20P', 'oneline', {'age':12, 'name':'bar'});"
- >>> ajax_replace_url('foo', 'Person P', name='bar', age=12)
- "javascript: replacePageChunk('foo', 'Person%20P', 'null', {'age':12, 'name':'bar'});"
- """
- params = [repr(nodeid), repr(urlquote(rql))]
- if extraparams and not vid:
- params.append("'null'")
- elif vid:
- params.append(repr(vid))
- if extraparams:
- import simplejson
- params.append(simplejson.dumps(extraparams))
- if swap:
- params.append('true')
- return "javascript: replacePageChunk(%s);" % ', '.join(params)
-
-
-from StringIO import StringIO
def ureport_as_html(layout):
from logilab.common.ureports import HTMLWriter
@@ -507,23 +480,6 @@
return newfunc
-def jsonize(function):
- import simplejson
- def newfunc(*args, **kwargs):
- ret = function(*args, **kwargs)
- if isinstance(ret, decimal.Decimal):
- ret = float(ret)
- elif isinstance(ret, (date, datetime)):
- ret = ret.strftime('%Y-%m-%d %H:%M')
- elif isinstance(ret, timedelta):
- ret = (ret.days * 24*60*60) + ret.seconds
- try:
- return simplejson.dumps(ret)
- except TypeError:
- return simplejson.dumps(repr(ret))
- return newfunc
-
-
def htmlescape(function):
def newfunc(*args, **kwargs):
ret = function(*args, **kwargs)
--- a/cwconfig.py Tue May 05 12:07:42 2009 +0200
+++ b/cwconfig.py Tue May 05 17:13:37 2009 +0200
@@ -677,7 +677,7 @@
return join(self.instance_data_dir(), self.appid)
def init_cubes(self, cubes):
- assert self._cubes is None
+ assert self._cubes is None, self._cubes
self._cubes = self.reorder_cubes(cubes)
# load cubes'__init__.py file first
for cube in cubes:
--- a/cwvreg.py Tue May 05 12:07:42 2009 +0200
+++ b/cwvreg.py Tue May 05 17:13:37 2009 +0200
@@ -113,31 +113,7 @@
def register_objects(self, path, force_reload=None):
"""overriden to remove objects requiring a missing interface"""
if super(CubicWebRegistry, self).register_objects(path, force_reload):
- # clear etype cache if you don't want to run into deep weirdness
- clear_cache(self, 'etype_class')
- # we may want to keep interface dependent objects (e.g.for i18n
- # catalog generation)
- if self.config.cleanup_interface_sobjects:
- # remove vobjects that don't support any available interface
- implemented_interfaces = set()
- for etype in self.schema.entities():
- cls = self.etype_class(etype)
- for iface in cls.__implements__:
- implemented_interfaces.update(iface.__mro__)
- implemented_interfaces.update(cls.__mro__)
- for obj, ifaces in self._needs_iface.items():
- ifaces = frozenset(isinstance(iface, basestring)
- and iface in self.schema
- and self.etype_class(iface)
- or iface
- for iface in ifaces)
- if not ('Any' in ifaces or ifaces & implemented_interfaces):
- self.debug('kicking vobject %s (no implemented '
- 'interface among %s)', obj, ifaces)
- self.unregister(obj)
- # clear needs_iface so we don't try to remove some not-anymore-in
- # objects on automatic reloading
- self._needs_iface.clear()
+ self.initialization_completed()
# print registry content
for registry, objects in self.items():
self.debug('available in registry %s: %s', registry,
@@ -146,6 +122,34 @@
for appobject in appobjects:
appobject.vreg_initialization_completed()
+ def initialization_completed(self):
+ # clear etype cache if you don't want to run into deep weirdness
+ clear_cache(self, 'etype_class')
+ # we may want to keep interface dependent objects (e.g.for i18n
+ # catalog generation)
+ if self.config.cleanup_interface_sobjects:
+ # remove vobjects that don't support any available interface
+ implemented_interfaces = set()
+ if 'Any' in self.get('etypes', ()):
+ for etype in self.schema.entities():
+ cls = self.etype_class(etype)
+ for iface in cls.__implements__:
+ implemented_interfaces.update(iface.__mro__)
+ implemented_interfaces.update(cls.__mro__)
+ for obj, ifaces in self._needs_iface.items():
+ ifaces = frozenset(isinstance(iface, basestring)
+ and iface in self.schema
+ and self.etype_class(iface)
+ or iface
+ for iface in ifaces)
+ if not ('Any' in ifaces or ifaces & implemented_interfaces):
+ self.debug('kicking vobject %s (no implemented '
+ 'interface among %s)', obj, ifaces)
+ self.unregister(obj)
+ # clear needs_iface so we don't try to remove some not-anymore-in
+ # objects on automatic reloading
+ self._needs_iface.clear()
+
@cached
def etype_class(self, etype):
"""return an entity class for the given entity type.
--- a/debian/control Tue May 05 12:07:42 2009 +0200
+++ b/debian/control Tue May 05 17:13:37 2009 +0200
@@ -60,8 +60,8 @@
Package: cubicweb-web
Architecture: all
XB-Python-Version: ${python:Versions}
-Depends: ${python:Depends}, cubicweb-common (= ${source:Version}), python-docutils, python-vobject, python-elementtree
-Recommends: fckeditor
+Depends: ${python:Depends}, cubicweb-common (= ${source:Version}), python-simplejson (>= 1.3), python-elementtree
+Recommends: python-docutils, python-vobject, fckeditor
Description: web interface library for the CubicWeb framework
CubicWeb is a semantic web application framework.
.
@@ -75,8 +75,8 @@
Package: cubicweb-common
Architecture: all
XB-Python-Version: ${python:Versions}
-Depends: ${python:Depends}, python-logilab-mtconverter (>= 0.6.0), python-simpletal (>= 4.0), graphviz, gettext, python-lxml, python-logilab-common (>= 0.39.0), python-yams (>= 0.21.0), python-rql (>= 0.22.0), python-simplejson (>= 1.3)
-Recommends: python-psyco
+Depends: ${python:Depends}, graphviz, gettext, python-logilab-mtconverter (>= 0.6.0), python-logilab-common (>= 0.39.0), python-yams (>= 0.22.0), python-rql (>= 0.22.0)
+Recommends: python-simpletal (>= 4.0), python-lxml
Conflicts: cubicweb-core
Replaces: cubicweb-core
Description: common library for the CubicWeb framework
--- a/devtools/apptest.py Tue May 05 12:07:42 2009 +0200
+++ b/devtools/apptest.py Tue May 05 17:13:37 2009 +0200
@@ -239,7 +239,7 @@
"""remote call simulation"""
dump = simplejson.dumps
args = [dump(arg) for arg in args]
- req = self.request(mode='remote', fname=fname, pageid='123', arg=args)
+ req = self.request(fname=fname, pageid='123', arg=args)
ctrl = self.env.app.select_controller('json', req)
return ctrl.publish(), req
--- a/devtools/devctl.py Tue May 05 12:07:42 2009 +0200
+++ b/devtools/devctl.py Tue May 05 17:13:37 2009 +0200
@@ -91,11 +91,10 @@
cleanup_sys_modules(libconfig)
if cubedir:
config = DevCubeConfiguration(cube)
- schema = config.load_schema()
else:
config = libconfig
- schema = config.load_schema()
libconfig = None
+ schema = config.load_schema(remove_unused_rtypes=False)
vreg = CubicWebRegistry(config)
# set_schema triggers objects registrations
vreg.set_schema(schema)
@@ -110,7 +109,7 @@
w('# singular and plural forms for each entity type\n')
w('\n')
if libconfig is not None:
- libschema = libconfig.load_schema()
+ libschema = libconfig.load_schema(remove_unused_rtypes=False)
entities = [e for e in schema.entities() if not e in libschema]
else:
entities = schema.entities()
@@ -154,13 +153,15 @@
for rschema in rschemas:
if rschema.is_final():
continue
+ if libconfig is not None:
+ librschema = libschema.get(rschema)
for teschema in rschema.targets(eschema, role):
- if libconfig is not None:
+ if libconfig is not None and librschema is not None:
if role == 'subject':
- subjtype, objtype = etype, tetype
+ subjtype, objtype = eschema, teschema
else:
- subjtype, objtype = tetype, etype
- if libschema.rschema(rtype).has_rdef(subjtype, objtype):
+ subjtype, objtype = teschema, eschema
+ if librschema.has_rdef(subjtype, objtype):
continue
if actionbox.relation_mode(rschema, eschema, teschema, role) == 'create':
if role == 'subject':
--- a/doc/book/en/A000-introduction.en.txt Tue May 05 12:07:42 2009 +0200
+++ b/doc/book/en/A000-introduction.en.txt Tue May 05 17:13:37 2009 +0200
@@ -6,8 +6,8 @@
Part I - Introduction to `CubicWeb`
===================================
-This first part of the book will offer different reading path to
-present you with the `CubicWeb` framework, provide a tutorial to get a quick
+This first part of the book will present different reading path to
+discover the `CubicWeb` framework, provide a tutorial to get a quick
overview of its features and list its key concepts.
--- a/doc/book/en/B0-data-model.en.txt Tue May 05 12:07:42 2009 +0200
+++ b/doc/book/en/B0-data-model.en.txt Tue May 05 17:13:37 2009 +0200
@@ -7,6 +7,7 @@
:maxdepth: 1
B0010-define-schema.en.txt
+ B0015-define-permissions.en.txt
B0020-define-workflows.en.txt
B0030-data-as-objects.en.txt
B0040-migration.en.txt
--- a/doc/book/en/B0012-schema-definition.en.txt Tue May 05 12:07:42 2009 +0200
+++ b/doc/book/en/B0012-schema-definition.en.txt Tue May 05 17:13:37 2009 +0200
@@ -35,18 +35,18 @@
`````````````````````````````
All `CubicWeb` built-in types are available : `String`, `Int`, `Float`,
-`Decimal`, `Boolean`, `Date`, `Datetime`, `Time`, `Interval`, `Byte`
+`Decimal`, `Boolean`, `Date`, `Datetime`, `Time`, `Interval`, `Byte`
and `Password`.
They are implicitely imported (as well as the special the function "_"
for translation :ref:`internationalization`).
An attribute is defined in the schema as follows::
-
+
attr_name = attr_type(properties*)
where `attr_type` is one of the type listed above and `properties` is
a list of the attribute needs to statisfy (see :ref:`properties`
-for more details).
+for more details).
Meta-data
@@ -55,22 +55,22 @@
Each entity type has at least the following meta-relations :
- `eid` (`Int`)
-
+
- `creation_date` (`Datetime`)
-
+
- `modification_date` (`Datetime`)
-
+
- `created_by` (`CWUser`) (which user created the entity)
-
- - `owned_by` (`CWUser`) (to whom the entity belongs; by default the
+
+ - `owned_by` (`CWUser`) (to whom the entity belongs; by default the
creator but not necessary, and it could have multiple owners)
-
+
- `is` (`CWEType`) (of which type the entity is)
* relations can be defined by using `ObjectRelation` or `SubjectRelation`.
The first argument of `SubjectRelation` or `ObjectRelation` gives respectively
- the object/subject entity type of the relation. This could be :
+ the object/subject entity type of the relation. This could be :
* a string corresponding to an entity type
@@ -79,7 +79,7 @@
* special string such as follows :
- "**" : all types of entities
- - "*" : all types of non-meta entities
+ - "*" : all types of non-meta entities
- "@" : all types of meta entities but not system entities (e.g. used for
the basic schema description)
@@ -91,7 +91,7 @@
.. _properties:
-* optional properties for attributes and relations :
+* optional properties for attributes and relations :
- `description` : a string describing an attribute or a relation. By default
this string will be used in the editing form of the entity, which means
@@ -103,7 +103,7 @@
- `cardinality` : a two character string which specify the cardinality of the
relation. The first character defines the cardinality of the relation on
- the subject, and the second on the object. When a relation can have
+ the subject, and the second on the object. When a relation can have
multiple subjects or objects, the cardinality applies to all,
not on a one-to-one basis (so it must be consistent...). The possible
values are inspired from regular expression syntax :
@@ -116,24 +116,24 @@
- `meta` : boolean indicating that the relation is a meta-relation (false by
default)
-* optional properties for attributes :
+* optional properties for attributes :
- `required` : boolean indicating if the attribute is required (false by default)
- `unique` : boolean indicating if the value of the attribute has to be unique
or not within all entities of the same type (false by default)
- - `indexed` : boolean indicating if an index needs to be created for this
+ - `indexed` : boolean indicating if an index needs to be created for this
attribute in the database (false by default). This is useful only if
you know that you will have to run numerous searches on the value of this
attribute.
- `default` : default value of the attribute. In case of date types, the values
which could be used correspond to the RQL keywords `TODAY` and `NOW`.
-
+
- `vocabulary` : specify static possible values of an attribute
-* optional properties of type `String` :
+* optional properties of type `String` :
- `fulltextindexed` : boolean indicating if the attribute is part of
the full text index (false by default) (*applicable on the type `Byte`
@@ -144,11 +144,11 @@
- `maxsize` : integer providing the maximum size of the string (no limit by default)
-* optional properties for relations :
+* optional properties for relations :
- `composite` : string indicating that the subject (composite == 'subject')
is composed of the objects of the relations. For the opposite case (when
- the object is composed of the subjects of the relation), we just set
+ the object is composed of the subjects of the relation), we just set
'object' as value. The composition implies that when the relation
is deleted (so when the composite is deleted), the composed are also deleted.
@@ -159,7 +159,7 @@
* `SizeConstraint` : allows to specify a minimum and/or maximum size on
string (generic case of `maxsize`)
-* `BoundConstraint` : allows to specify a minimum and/or maximum value on
+* `BoundConstraint` : allows to specify a minimum and/or maximum value on
numeric types
* `UniqueConstraint` : identical to "unique=True"
@@ -168,7 +168,7 @@
* `RQLConstraint` : allows to specify a RQL query that has to be satisfied
by the subject and/or the object of the relation. In this query the variables
- `S` and `O` are reserved for the entities subject and object of the
+ `S` and `O` are reserved for the entities subject and object of the
relation.
* `RQLVocabularyConstraint` : similar to the previous type of constraint except
@@ -184,9 +184,9 @@
A relation is defined by a Python class heriting `RelationType`. The name
of the class corresponds to the name of the type. The class then contains
-a description of the properties of this type of relation, and could as well
+a description of the properties of this type of relation, and could as well
contain a string for the subject and a string for the object. This allows to create
-new definition of associated relations, (so that the class can have the
+new definition of associated relations, (so that the class can have the
definition properties from the relation) for example ::
class locked_by(RelationType):
@@ -217,198 +217,12 @@
`ObjectRelation`) is all we need.
-The security model
-------------------
-
-The security model of `cubicWeb` is based on `Access Control List`.
-The main principles are:
-
-* users and groups of users
-* a user belongs to at least one group of user
-* permissions (read, update, create, delete)
-* permissions are assigned to groups (and not to users)
-
-For `CubicWeb` in particular:
-
-* we associate rights at the enttities/relations schema level
-* for each entity, we distinguish four kind of permissions: read,
- add, update and delete
-* for each relation, we distinguish three king of permissions: read,
- add and delete (we can not modify a relation)
-* the basic groups are: Administrators, Users and Guests
-* by default, users belongs to the group Users
-* there is a virtual group called `Owners users` to which we
- can associate only deletion and update permissions
-* we can not add users to the `Owners users` group, they are
- implicetely added to it according to the context of the objects
- they own
-* the permissions of this group are only be checked on update/deletion
- actions if all the other groups the user belongs does not provide
- those permissions
-
-
-Permissions definition
-``````````````````````
-
-Setting permissions is done with the attribute `permissions` of entities and
-relation types. It defines a dictionary where the keys are the access types
-(action), and the values are the authorized groups or expressions.
-
-For an entity type, the possible actions are `read`, `add`, `update` and
-`delete`.
-
-For a relation type, the possible actions are `read`, `add`, and `delete`.
-
-For each access type, a tuple indicates the name of the authorized groups and/or
-one or multiple RQL expressions to satisfy to grant access. The access is
-provided once the user is in the listed groups or one of the RQL condition is
-satisfied.
-
-The standard groups are :
-
-* `guests`
-
-* `users`
-
-* `managers`
-
-* `owners` : virtual group corresponding to the entity's owner.
- This can only be used for the actions `update` and `delete` of an entity
- type.
-
-It is also possible to use specific groups if they are defined in the precreate
-of the cube (``migration/precreate.py``).
-
-
-Use of RQL expression for writing rights
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-It is possible to define RQL expression to provide update permission
-(`add`, `delete` and `update`) on relation and entity types.
-
-RQL expression for entity type permission :
-
-* you have to use the class `ERQLExpression`
-
-* the used expression corresponds to the WHERE statement of an RQL query
-
-* in this expression, the variables X and U are pre-defined references
- respectively on the current entity (on which the action is verified) and
- on the user who send the request
-
-* it is possible to use, in this expression, a special relation
- "has_<ACTION>_permission" where the subject is the user and the
- object is a any variable, meaning that the user needs to have
- permission to execute the action <ACTION> on the entities related
- to this variable
-
-For RQL expressions on a relation type, the principles are the same except
-for the following :
-
-* you have to use the class `RQLExpression` in the case of a non-final relation
-
-* in the expression, the variables S, O and U are pre-defined references
- to respectively the subject and the object of the current relation (on
- which the action is being verified) and the user who executed the query
-
-* we can also defined rights on attributes of an entity (non-final relation),
- knowing that :
+Updating your application with your new schema
+----------------------------------------------
- - to defines RQL expression, we have to use the class `ERQLExpression`
- in which X represents the entity the attribute belongs to
-
- - the permissions `add` and `delete` are equivalent. Only `add`/`read`
- are actually taken in consideration.
-
-In addition to that the entity type `CWPermission` from the standard library
-allow to build very complex and dynamic security architecture. The schema of
-this entity type is as follow : ::
-
- class CWPermission(MetaEntityType):
- """entity type that may be used to construct some advanced security configuration
- """
- name = String(required=True, indexed=True, internationalizable=True, maxsize=100)
- 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"))
- # can be used on any entity
- require_permission = ObjectRelation('**', cardinality='*1', composite='subject',
- description=_("link a permission to the entity. This "
- "permission should be used in the security "
- "definition of the entity's type to be useful."))
-
-
-Example of configuration ::
-
-
- ...
-
- class Version(EntityType):
- """a version is defining the content of a particular project's release"""
-
- permissions = {'read': ('managers', 'users', 'guests',),
- 'update': ('managers', 'logilab', 'owners',),
- 'delete': ('managers', ),
- 'add': ('managers', 'logilab',
- ERQLExpression('X version_of PROJ, U in_group G,'
- 'PROJ require_permission P, P name "add_version",'
- 'P require_group G'),)}
-
- ...
-
- class version_of(RelationType):
- """link a version to its project. A version is necessarily linked to one and only one project.
- """
- permissions = {'read': ('managers', 'users', 'guests',),
- 'delete': ('managers', ),
- 'add': ('managers', 'logilab',
- RRQLExpression('O require_permission P, P name "add_version",'
- 'U in_group G, P require_group G'),)
- }
- inlined = True
-
-This configuration indicates that an entity `CWPermission` named
-"add_version" can be associated to a project and provides rights to create
-new versions on this project to specific groups. It is important to notice that :
-
-* in such case, we have to protect both the entity type "Version" and the relation
- associating a version to a project ("version_of")
-
-* because of the genricity of the entity type `CWPermission`, we have to execute
- a unification with the groups and/or the states if necessary in the expression
- ("U in_group G, P require_group G" in the above example)
-
-Use of RQL expression for reading rights
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The principles are the same but with the following restrictions :
-
-* we can not use `RRQLExpression` on relation types for reading
-
-* special relations "has_<ACTION>_permission" can not be used
-
-
-Note on the use of RQL expression for `add` permission
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Potentially, the use of an RQL expression to add an entity or a relation
-can cause problems for the user interface, because if the expression uses
-the entity or the relation to create, then we are not able to verify the
-permissions before we actually add the entity (please note that this is
-not a problem for the RQL server at all, because the permissions checks are
-done after the creation). In such case, the permission check methods
-(check_perm, has_perm) can indicate that the user is not allowed to create
-this entity but can obtain the permission.
-To compensate this problem, it is usually necessary, for such case,
-to use an action that reflects the schema permissions but which enables
-to check properly the permissions so that it would show up if necessary.
-
-
-Updating your application with your new schema
-``````````````````````````````````````````````
-
-If you modified your schema, the update is not automatic; indeed, this is
+If you modified your schema, the update is not automatic; indeed, this is
in general not a good idea.
-Instead, you call a shell on your application, which is a
+Instead, you call a shell on your application, which is a
an interactive python shell, with an appropriate
cubicweb environment ::
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/B0015-define-permissions.en.txt Tue May 05 17:13:37 2009 +0200
@@ -0,0 +1,188 @@
+.. -*- coding: utf-8 -*-
+
+The security model
+------------------
+
+The security model of `cubicWeb` is based on `Access Control List`.
+The main principles are:
+
+* users and groups of users
+* a user belongs to at least one group of user
+* permissions (read, update, create, delete)
+* permissions are assigned to groups (and not to users)
+
+For `CubicWeb` in particular:
+
+* we associate rights at the enttities/relations schema level
+* for each entity, we distinguish four kind of permissions: read,
+ add, update and delete
+* for each relation, we distinguish three king of permissions: read,
+ add and delete (we can not modify a relation)
+* the basic groups are: Administrators, Users and Guests
+* by default, users belongs to the group Users
+* there is a virtual group called `Owners users` to which we
+ can associate only deletion and update permissions
+* we can not add users to the `Owners users` group, they are
+ implicetely added to it according to the context of the objects
+ they own
+* the permissions of this group are only be checked on update/deletion
+ actions if all the other groups the user belongs does not provide
+ those permissions
+
+
+Permissions definition
+``````````````````````
+
+Setting permissions is done with the attribute `permissions` of entities and
+relation types. It defines a dictionary where the keys are the access types
+(action), and the values are the authorized groups or expressions.
+
+For an entity type, the possible actions are `read`, `add`, `update` and
+`delete`.
+
+For a relation type, the possible actions are `read`, `add`, and `delete`.
+
+For each access type, a tuple indicates the name of the authorized groups and/or
+one or multiple RQL expressions to satisfy to grant access. The access is
+provided once the user is in the listed groups or one of the RQL condition is
+satisfied.
+
+The standard groups are :
+
+* `guests`
+
+* `users`
+
+* `managers`
+
+* `owners` : virtual group corresponding to the entity's owner.
+ This can only be used for the actions `update` and `delete` of an entity
+ type.
+
+It is also possible to use specific groups if they are defined in the precreate
+of the cube (``migration/precreate.py``).
+
+
+Use of RQL expression for writing rights
+````````````````````````````````````````
+
+It is possible to define RQL expression to provide update permission
+(`add`, `delete` and `update`) on relation and entity types.
+
+RQL expression for entity type permission :
+
+* you have to use the class `ERQLExpression`
+
+* the used expression corresponds to the WHERE statement of an RQL query
+
+* in this expression, the variables X and U are pre-defined references
+ respectively on the current entity (on which the action is verified) and
+ on the user who send the request
+
+* it is possible to use, in this expression, a special relation
+ "has_<ACTION>_permission" where the subject is the user and the
+ object is a any variable, meaning that the user needs to have
+ permission to execute the action <ACTION> on the entities related
+ to this variable
+
+For RQL expressions on a relation type, the principles are the same except
+for the following :
+
+* you have to use the class `RQLExpression` in the case of a non-final relation
+
+* in the expression, the variables S, O and U are pre-defined references
+ to respectively the subject and the object of the current relation (on
+ which the action is being verified) and the user who executed the query
+
+* we can also defined rights on attributes of an entity (non-final relation),
+ knowing that :
+
+ - to defines RQL expression, we have to use the class `ERQLExpression`
+ in which X represents the entity the attribute belongs to
+
+ - the permissions `add` and `delete` are equivalent. Only `add`/`read`
+ are actually taken in consideration.
+
+In addition to that the entity type `EPermission` from the standard library
+allow to build very complex and dynamic security architecture. The schema of
+this entity type is as follow : ::
+
+ class EPermission(MetaEntityType):
+ """entity type that may be used to construct some advanced security configuration
+ """
+ name = String(required=True, indexed=True, internationalizable=True, maxsize=100)
+ 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"))
+ # can be used on any entity
+ require_permission = ObjectRelation('**', cardinality='*1', composite='subject',
+ description=_("link a permission to the entity. This "
+ "permission should be used in the security "
+ "definition of the entity's type to be useful."))
+
+
+Example of configuration ::
+
+
+ ...
+
+ class Version(EntityType):
+ """a version is defining the content of a particular project's release"""
+
+ permissions = {'read': ('managers', 'users', 'guests',),
+ 'update': ('managers', 'logilab', 'owners',),
+ 'delete': ('managers', ),
+ 'add': ('managers', 'logilab',
+ ERQLExpression('X version_of PROJ, U in_group G,'
+ 'PROJ require_permission P, P name "add_version",'
+ 'P require_group G'),)}
+
+ ...
+
+ class version_of(RelationType):
+ """link a version to its project. A version is necessarily linked to one and only one project.
+ """
+ permissions = {'read': ('managers', 'users', 'guests',),
+ 'delete': ('managers', ),
+ 'add': ('managers', 'logilab',
+ RRQLExpression('O require_permission P, P name "add_version",'
+ 'U in_group G, P require_group G'),)
+ }
+ inlined = True
+
+This configuration indicates that an entity `EPermission` named
+"add_version" can be associated to a project and provides rights to create
+new versions on this project to specific groups. It is important to notice that :
+
+* in such case, we have to protect both the entity type "Version" and the relation
+ associating a version to a project ("version_of")
+
+* because of the genricity of the entity type `EPermission`, we have to execute
+ a unification with the groups and/or the states if necessary in the expression
+ ("U in_group G, P require_group G" in the above example)
+
+Use of RQL expression for reading rights
+````````````````````````````````````````
+
+The principles are the same but with the following restrictions :
+
+* we can not use `RRQLExpression` on relation types for reading
+
+* special relations "has_<ACTION>_permission" can not be used
+
+
+Note on the use of RQL expression for `add` permission
+``````````````````````````````````````````````````````
+Potentially, the use of an RQL expression to add an entity or a relation
+can cause problems for the user interface, because if the expression uses
+the entity or the relation to create, then we are not able to verify the
+permissions before we actually add the entity (please note that this is
+not a problem for the RQL server at all, because the permissions checks are
+done after the creation). In such case, the permission check methods
+(check_perm, has_perm) can indicate that the user is not allowed to create
+this entity but can obtain the permission.
+To compensate this problem, it is usually necessary, for such case,
+to use an action that reflects the schema permissions but which enables
+to check properly the permissions so that it would show up if necessary.
+
--- a/doc/book/en/B1020-define-views.en.txt Tue May 05 12:07:42 2009 +0200
+++ b/doc/book/en/B1020-define-views.en.txt Tue May 05 17:13:37 2009 +0200
@@ -99,7 +99,7 @@
Registerer
``````````
-[Registerers are deprecated: they will soon disappear for explicite
+[Registerers are deprecated: they will soon disappear for explicit
registration...]
A view is also customizable through its attribute ``__registerer__``.
--- a/doc/book/en/B2052-install.en.txt Tue May 05 12:07:42 2009 +0200
+++ b/doc/book/en/B2052-install.en.txt Tue May 05 17:13:37 2009 +0200
@@ -97,7 +97,7 @@
Generating translation files
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------------------------
`CubicWeb` is fully internationalized. Translation catalogs are found in
``myapp/i18n``. To compile the translation files, use the `gettext` tools
@@ -120,7 +120,7 @@
While running ``laxctl i18nupdate``, new string will be added to the catalogs.
Generating the data directory
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-----------------------------
In order to generate the ``myapp/data`` directory that holds the static
files like stylesheets and icons, you need to run the command::
@@ -128,7 +128,7 @@
$ python myapp/bin/laxctl populatedata
Generating the schema diagram
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-----------------------------
There is a view named ``schema`` that displays a diagram of the
entity-relationship graph defined by the schema. This diagram has to
@@ -136,11 +136,8 @@
$ python myapp/bin/laxctl genschema
-Application configuration
--------------------------
-
-Authentication
-~~~~~~~~~~~~~~
+Application configuration: authentication
+-----------------------------------------
You have the option of using or not google authentication for your application.
This has to be define in ``app.conf`` and ``app.yaml``.
@@ -178,9 +175,9 @@
You should be redirected to a page displaying a message `content initialized`.
Initialize the datastore
-~~~~~~~~~~~~~~~~~~~~~~~~
+------------------------
-You, then, want to visit `http://MYAPP_URL/?vid=authinfo <http://localhost:8080/?vid=authinfo>`_ .
+Visit `http://MYAPP_URL/?vid=authinfo <http://localhost:8080/?vid=authinfo>`_ .
If you selected not to use google authentication, you will be prompted to a
login form where you should initialize the administrator login (recommended
to use admin/admin at first). You will then be redirected to a page providing
--- a/doc/book/en/C050-rql.en.txt Tue May 05 12:07:42 2009 +0200
+++ b/doc/book/en/C050-rql.en.txt Tue May 05 17:13:37 2009 +0200
@@ -177,7 +177,7 @@
person called 'nice'*
::
- INSERT Person X: X name 'foo', X friend Y WHERE name 'nice'
+ INSERT Person X: X name 'foo', X friend Y WHERE Y name 'nice'
Update and relation creation queries
------------------------------------
--- a/doc/book/en/D010-faq.en.txt Tue May 05 12:07:42 2009 +0200
+++ b/doc/book/en/D010-faq.en.txt Tue May 05 17:13:37 2009 +0200
@@ -242,3 +242,11 @@
Then in the view code, use::
self.format_date(entity.date_attribute)
+
+* Can PostgreSQL and CubicWeb authentication work with kerberos ?
+
+ If you have postgresql set up to accept kerberos authentication, you can set
+ the db-host, db-name and db-user parameters in the `sources` configuration
+ file while leaving the password blank. It should be enough for your instance
+ to connect to postgresql with a kerberos ticket.
+
--- a/doc/book/en/Z013-blog-less-ten-minutes.en.txt Tue May 05 12:07:42 2009 +0200
+++ b/doc/book/en/Z013-blog-less-ten-minutes.en.txt Tue May 05 17:13:37 2009 +0200
@@ -17,7 +17,7 @@
cubicweb-ctl start -D myblog
-This is it. Your blog is ready to you. Go to http://localhost:8080 and enjoy!!
+This is it. Your blog is ready to you. Go to http://localhost:8080 and enjoy!
As a developper, you'll want to know more about how to develop new
cubes and cutomize the look of your application and this is what we
--- a/entities/test/data/bootstrap_packages Tue May 05 12:07:42 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-
--- a/entities/test/unittest_base.py Tue May 05 12:07:42 2009 +0200
+++ b/entities/test/unittest_base.py Tue May 05 17:13:37 2009 +0200
@@ -18,28 +18,27 @@
def setup_database(self):
self.member = self.create_user('member')
-
-
-
+
+
+
class MetadataTC(BaseEntityTC):
def test_creator(self):
self.login(u'member')
- card = self.add_entity('Card', title=u"hello")
+ entity = self.add_entity('Bookmark', title=u"hello", path=u'project/cubicweb')
self.commit()
- self.assertEquals(card.creator.eid, self.member.eid)
- self.assertEquals(card.dc_creator(), u'member')
+ self.assertEquals(entity.creator.eid, self.member.eid)
+ self.assertEquals(entity.dc_creator(), u'member')
def test_type(self):
- self.assertEquals(self.member.dc_type(), 'euser')
-
+ self.assertEquals(self.member.dc_type(), 'cwuser')
def test_entity_meta_attributes(self):
# XXX move to yams
self.assertEquals(self.schema['CWUser'].meta_attributes(), {})
- self.assertEquals(dict((str(k), v) for k, v in self.schema['Card'].meta_attributes().iteritems()),
- {'content_format': ('format', 'content')})
-
+ self.assertEquals(dict((str(k), v) for k, v in self.schema['State'].meta_attributes().iteritems()),
+ {'description_format': ('format', 'description')})
+
class CWUserTC(BaseEntityTC):
def test_dc_title_and_name(self):
@@ -53,9 +52,9 @@
self.assertEquals(e.dc_title(), 'member')
self.assertEquals(e.name(), u'bouah lôt')
-
+
class StateAndTransitionsTC(BaseEntityTC):
-
+
def test_transitions(self):
user = self.entity('CWUser X')
e = self.entity('State S WHERE S name "activated"')
@@ -74,7 +73,7 @@
user = self.entity('CWUser X')
self.assert_(not user.can_pass_transition('deactivate'))
self.assert_(not user.can_pass_transition('activate'))
-
+
def test_transitions_with_dest_specfied(self):
user = self.entity('CWUser X')
e = self.entity('State S WHERE S name "activated"')
@@ -85,20 +84,20 @@
self.assertEquals(trs[0].destination().name, u'deactivated')
trs = list(e.transitions(user, e.eid))
self.assertEquals(len(trs), 0)
-
+
def test_transitions_maybe_passed(self):
self.execute('INSERT RQLExpression X: X exprtype "ERQLExpression", '
'X expression "X owned_by U", T condition X '
'WHERE T name "deactivate"')
self._test_deactivated()
-
+
def test_transitions_maybe_passed_using_has_update_perm(self):
self.execute('INSERT RQLExpression X: X exprtype "ERQLExpression", '
'X expression "U has_update_permission X", T condition X '
'WHERE T name "deactivate"')
self._test_deactivated()
-
-
+
+
def _test_deactivated(self):
ueid = self.create_user('toto').eid
self.create_user('tutu')
@@ -116,12 +115,12 @@
self.assertRaises(ValidationError,
cu.execute, 'SET X in_state S WHERE X eid %(x)s, S name "activated"',
{'x': ueid}, 'x')
-
+
def test_transitions_selection(self):
"""
------------------------ tr1 -----------------
- | state1 (Card, Bookmark) | ------> | state2 (Card) |
+ | state1 (CWGroup, Bookmark) | ------> | state2 (CWGroup) |
------------------------ -----------------
| tr2 ------------------
`------> | state3 (Bookmark) |
@@ -132,11 +131,11 @@
state3 = self.add_entity('State', name=u'state3')
tr1 = self.add_entity('Transition', name=u'tr1')
tr2 = self.add_entity('Transition', name=u'tr2')
- self.execute('SET X state_of Y WHERE X eid in (%s, %s), Y is CWEType, Y name "Card"' %
+ self.execute('SET X state_of Y WHERE X eid in (%s, %s), Y is CWEType, Y name "CWGroup"' %
(state1.eid, state2.eid))
self.execute('SET X state_of Y WHERE X eid in (%s, %s), Y is CWEType, Y name "Bookmark"' %
(state1.eid, state3.eid))
- self.execute('SET X transition_of Y WHERE X eid %s, Y name "Card"' % tr1.eid)
+ self.execute('SET X transition_of Y WHERE X eid %s, Y name "CWGroup"' % tr1.eid)
self.execute('SET X transition_of Y WHERE X eid %s, Y name "Bookmark"' % tr2.eid)
self.execute('SET X allowed_transition Y WHERE X eid %s, Y eid %s' %
(state1.eid, tr1.eid))
@@ -146,36 +145,35 @@
(tr1.eid, state2.eid))
self.execute('SET X destination_state Y WHERE X eid %s, Y eid %s' %
(tr2.eid, state3.eid))
- self.execute('SET X initial_state Y WHERE Y eid %s, X name "Card"' % state1.eid)
+ self.execute('SET X initial_state Y WHERE Y eid %s, X name "CWGroup"' % state1.eid)
self.execute('SET X initial_state Y WHERE Y eid %s, X name "Bookmark"' % state1.eid)
- card = self.add_entity('Card', title=u't1')
- bookmark = self.add_entity('Bookmark', title=u'111', path=u'/view')
-
- transitions = list(state1.transitions(card))
+ group = self.add_entity('CWGroup', name=u't1')
+ transitions = list(state1.transitions(group))
self.assertEquals(len(transitions), 1)
self.assertEquals(transitions[0].name, 'tr1')
+ bookmark = self.add_entity('Bookmark', title=u'111', path=u'/view')
transitions = list(state1.transitions(bookmark))
self.assertEquals(len(transitions), 1)
self.assertEquals(transitions[0].name, 'tr2')
-
+
def test_transitions_selection2(self):
"""
------------------------ tr1 (Bookmark) -----------------------
- | state1 (Card, Bookmark) | -------------> | state2 (Card,Bookmark) |
+ | state1 (CWGroup, Bookmark) | -------------> | state2 (CWGroup,Bookmark) |
------------------------ -----------------------
- | tr2 (Card) |
+ | tr2 (CWGroup) |
`---------------------------------/
"""
state1 = self.add_entity('State', name=u'state1')
state2 = self.add_entity('State', name=u'state2')
tr1 = self.add_entity('Transition', name=u'tr1')
tr2 = self.add_entity('Transition', name=u'tr2')
- self.execute('SET X state_of Y WHERE X eid in (%s, %s), Y is CWEType, Y name "Card"' %
+ self.execute('SET X state_of Y WHERE X eid in (%s, %s), Y is CWEType, Y name "CWGroup"' %
(state1.eid, state2.eid))
self.execute('SET X state_of Y WHERE X eid in (%s, %s), Y is CWEType, Y name "Bookmark"' %
(state1.eid, state2.eid))
- self.execute('SET X transition_of Y WHERE X eid %s, Y name "Card"' % tr1.eid)
+ self.execute('SET X transition_of Y WHERE X eid %s, Y name "CWGroup"' % tr1.eid)
self.execute('SET X transition_of Y WHERE X eid %s, Y name "Bookmark"' % tr2.eid)
self.execute('SET X allowed_transition Y WHERE X eid %s, Y eid %s' %
(state1.eid, tr1.eid))
@@ -185,18 +183,17 @@
(tr1.eid, state2.eid))
self.execute('SET X destination_state Y WHERE X eid %s, Y eid %s' %
(tr2.eid, state2.eid))
- self.execute('SET X initial_state Y WHERE Y eid %s, X name "Card"' % state1.eid)
+ self.execute('SET X initial_state Y WHERE Y eid %s, X name "CWGroup"' % state1.eid)
self.execute('SET X initial_state Y WHERE Y eid %s, X name "Bookmark"' % state1.eid)
- card = self.add_entity('Card', title=u't1')
- bookmark = self.add_entity('Bookmark', title=u'111', path=u'/view')
-
- transitions = list(state1.transitions(card))
+ group = self.add_entity('CWGroup', name=u't1')
+ transitions = list(state1.transitions(group))
self.assertEquals(len(transitions), 1)
self.assertEquals(transitions[0].name, 'tr1')
+ bookmark = self.add_entity('Bookmark', title=u'111', path=u'/view')
transitions = list(state1.transitions(bookmark))
self.assertEquals(len(transitions), 1)
self.assertEquals(transitions[0].name, 'tr2')
-
+
class EmailAddressTC(BaseEntityTC):
def test_canonical_form(self):
@@ -226,12 +223,12 @@
class CWUserTC(BaseEntityTC):
-
+
def test_complete(self):
e = self.entity('CWUser X WHERE X login "admin"')
e.complete()
-
+
def test_matching_groups(self):
e = self.entity('CWUser X WHERE X login "admin"')
self.failUnless(e.matching_groups('managers'))
@@ -275,7 +272,7 @@
# clear selector cache
clear_cache(self.vreg, 'etype_class')
return self.vreg.etype_class(etype)
-
+
def test_etype_class_selection_and_specialization(self):
# no specific class for Subdivisions, the default one should be selected
eclass = self.select_eclass('SubDivision')
@@ -297,6 +294,6 @@
# check Division eclass is still selected for plain Division entities
eclass = self.select_eclass('Division')
self.assertEquals(eclass.id, 'Division')
-
+
if __name__ == '__main__':
unittest_main()
--- a/ext/rest.py Tue May 05 12:07:42 2009 +0200
+++ b/ext/rest.py Tue May 05 17:13:37 2009 +0200
@@ -76,31 +76,6 @@
register_canonical_role('eid', eid_reference_role)
-def card_reference_role(role, rawtext, text, lineno, inliner,
- options={}, content=[]):
- text = text.strip()
- try:
- wikiid, rest = text.split(u':', 1)
- except:
- wikiid, rest = text, text
- context = inliner.document.settings.context
- cardrset = context.req.execute('Card X WHERE X wikiid %(id)s',
- {'id': wikiid})
- if cardrset:
- ref = cardrset.get_entity(0, 0).absolute_url()
- else:
- schema = context.schema
- if schema.eschema('Card').has_perm(context.req, 'add'):
- ref = context.req.build_url('view', vid='creation', etype='Card', wikiid=wikiid)
- else:
- ref = '#'
- set_classes(options)
- return [nodes.reference(rawtext, utils.unescape(rest), refuri=ref,
- **options)], []
-
-register_canonical_role('card', card_reference_role)
-
-
def winclude_directive(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
"""Include a reST file as part of the content of this reST file.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ext/test/unittest_rest.py Tue May 05 17:13:37 2009 +0200
@@ -0,0 +1,40 @@
+from logilab.common.testlib import unittest_main
+from cubicweb.devtools.apptest import EnvBasedTC
+
+from cubicweb.ext.rest import rest_publish
+
+class RestTC(EnvBasedTC):
+ def context(self):
+ return self.execute('CWUser X WHERE X login "admin"').get_entity(0, 0)
+
+ def test_eid_role(self):
+ context = self.context()
+ self.assertEquals(rest_publish(context, ':eid:`%s`' % context.eid),
+ '<p><a class="reference" href="http://testing.fr/cubicweb/cwuser/admin">#%s</a></p>\n' % context.eid)
+ self.assertEquals(rest_publish(context, ':eid:`%s:some text`' % context.eid),
+ '<p><a class="reference" href="http://testing.fr/cubicweb/cwuser/admin">some text</a></p>\n')
+
+ def test_bad_rest_no_crash(self):
+ data = rest_publish(self.context(), '''
+| card | implication |
+--------------------------
+| 1-1 | N1 = N2 |
+| 1-? | N1 <= N2 |
+| 1-+ | N1 >= N2 |
+| 1-* | N1>0 => N2>0 |
+--------------------------
+| ?-? | N1 # N2 |
+| ?-+ | N1 >= N2 |
+| ?-* | N1 # N2 |
+--------------------------
+| +-+ | N1>0 => N2>0 et |
+| | N2>0 => N1>0 |
+| +-* | N1>+ => N2>0 |
+--------------------------
+| *-* | N1#N2 |
+--------------------------
+
+''')
+
+if __name__ == '__main__':
+ unittest_main()
--- a/i18n/en.po Tue May 05 12:07:42 2009 +0200
+++ b/i18n/en.po Tue May 05 17:13:37 2009 +0200
@@ -118,6 +118,10 @@
msgid "%s software version of the database"
msgstr ""
+#, python-format
+msgid "%s_perm"
+msgstr ""
+
msgid "**"
msgstr "0..n 0..n"
@@ -196,11 +200,30 @@
msgid "Bytes_plural"
msgstr "Bytes"
-msgid "CWAttribute"
-msgstr "Attribute"
-
-msgid "CWAttribute_plural"
-msgstr "Attributes"
+msgid "Date"
+msgstr "Date"
+
+msgid "Date_plural"
+msgstr "Dates"
+
+msgid "Datetime"
+msgstr "Date and time"
+
+msgid "Datetime_plural"
+msgstr "Dates and times"
+
+#, python-format
+msgid "Debug level set to %s"
+msgstr ""
+
+msgid "Decimal"
+msgstr "Decimal number"
+
+msgid "Decimal_plural"
+msgstr "Decimal numbers"
+
+msgid "Do you want to delete the following element(s) ?"
+msgstr ""
msgid "CWCache"
msgstr ""
@@ -226,12 +249,24 @@
msgid "CWEType_plural"
msgstr "Entity types"
+msgid "CWAttribute"
+msgstr "Attribute"
+
+msgid "CWAttribute_plural"
+msgstr "Attributes"
+
msgid "CWGroup"
msgstr "Group"
msgid "CWGroup_plural"
msgstr "Groups"
+msgid "CWRelation"
+msgstr "Relation"
+
+msgid "CWRelation_plural"
+msgstr "Relations"
+
msgid "CWPermission"
msgstr "Permission"
@@ -250,41 +285,13 @@
msgid "CWRType_plural"
msgstr "Relation types"
-msgid "CWRelation"
-msgstr "Relation"
-
-msgid "CWRelation_plural"
-msgstr "Relations"
-
msgid "CWUser"
msgstr "User"
msgid "CWUser_plural"
msgstr "Users"
-msgid "Date"
-msgstr "Date"
-
-msgid "Date_plural"
-msgstr "Dates"
-
-msgid "Datetime"
-msgstr "Date and time"
-
-msgid "Datetime_plural"
-msgstr "Dates and times"
-
-#, python-format
-msgid "Debug level set to %s"
-msgstr ""
-
-msgid "Decimal"
-msgstr "Decimal number"
-
-msgid "Decimal_plural"
-msgstr "Decimal numbers"
-
-msgid "Do you want to delete the following element(s) ?"
+msgid "Email body: "
msgstr ""
msgid "EmailAddress"
@@ -305,7 +312,7 @@
msgid "Float_plural"
msgstr "Floats"
-msgid "From:"
+msgid "From: "
msgstr ""
msgid "Int"
@@ -323,9 +330,6 @@
msgid "New Bookmark"
msgstr "New bookmark"
-msgid "New CWAttribute"
-msgstr "New attribute"
-
msgid "New CWCache"
msgstr ""
@@ -338,9 +342,15 @@
msgid "New CWEType"
msgstr "New entity type"
+msgid "New CWAttribute"
+msgstr "New attribute"
+
msgid "New CWGroup"
msgstr "New group"
+msgid "New CWRelation"
+msgstr "New relation"
+
msgid "New CWPermission"
msgstr "New permission"
@@ -350,9 +360,6 @@
msgid "New CWRType"
msgstr "New relation type"
-msgid "New CWRelation"
-msgstr "New relation"
-
msgid "New CWUser"
msgstr "New user"
@@ -389,13 +396,16 @@
msgid "Please note that this is only a shallow copy"
msgstr ""
+msgid "Problem occured"
+msgstr ""
+
msgid "RQLExpression"
msgstr "RQL expression"
msgid "RQLExpression_plural"
msgstr "RQL expressions"
-msgid "Recipients:"
+msgid "Recipients: "
msgstr ""
msgid "Relations"
@@ -429,7 +439,7 @@
msgid "String_plural"
msgstr "Strings"
-msgid "Subject:"
+msgid "Subject: "
msgstr ""
msgid "Submit bug report"
@@ -456,9 +466,6 @@
msgid "This Bookmark"
msgstr "This bookmark"
-msgid "This CWAttribute"
-msgstr "This attribute"
-
msgid "This CWCache"
msgstr ""
@@ -471,9 +478,15 @@
msgid "This CWEType"
msgstr "This entity type"
+msgid "This CWAttribute"
+msgstr "This attribute"
+
msgid "This CWGroup"
msgstr "This group"
+msgid "This CWRelation"
+msgstr "This relation"
+
msgid "This CWPermission"
msgstr "This permission"
@@ -483,9 +496,6 @@
msgid "This CWRType"
msgstr "This relation type"
-msgid "This CWRelation"
-msgstr "This relation"
-
msgid "This CWUser"
msgstr "This user"
@@ -659,12 +669,6 @@
msgid "actions_manage_description"
msgstr ""
-msgid "actions_managepermission"
-msgstr ""
-
-msgid "actions_managepermission_description"
-msgstr ""
-
msgid "actions_muledit"
msgstr "modify all"
@@ -737,12 +741,6 @@
msgid "add Bookmark bookmarked_by CWUser object"
msgstr "bookmark"
-msgid "add CWAttribute constrained_by CWConstraint subject"
-msgstr "constraint"
-
-msgid "add CWAttribute relation_type CWRType object"
-msgstr "attribute definition"
-
msgid "add CWEType add_permission RQLExpression subject"
msgstr "rql expression for the add permission"
@@ -755,6 +753,18 @@
msgid "add CWEType update_permission RQLExpression subject"
msgstr "rql expression for the update permission"
+msgid "add CWAttribute constrained_by CWConstraint subject"
+msgstr "constraint"
+
+msgid "add CWAttribute relation_type CWRType object"
+msgstr "attribute definition"
+
+msgid "add CWRelation constrained_by CWConstraint subject"
+msgstr "constraint"
+
+msgid "add CWRelation relation_type CWRType object"
+msgstr "relation definition"
+
msgid "add CWProperty for_user CWUser object"
msgstr "property"
@@ -767,12 +777,6 @@
msgid "add CWRType read_permission RQLExpression subject"
msgstr "rql expression for the read permission"
-msgid "add CWRelation constrained_by CWConstraint subject"
-msgstr "constraint"
-
-msgid "add CWRelation relation_type CWRType object"
-msgstr "relation definition"
-
msgid "add CWUser in_group CWGroup object"
msgstr "user"
@@ -803,9 +807,6 @@
msgid "add a Bookmark"
msgstr "add a bookmark"
-msgid "add a CWAttribute"
-msgstr "add an attribute"
-
msgid "add a CWCache"
msgstr ""
@@ -818,9 +819,15 @@
msgid "add a CWEType"
msgstr "add an entity type"
+msgid "add a CWAttribute"
+msgstr "add an attribute"
+
msgid "add a CWGroup"
msgstr "add a group"
+msgid "add a CWRelation"
+msgstr "add a relation"
+
msgid "add a CWPermission"
msgstr "add a permission"
@@ -830,9 +837,6 @@
msgid "add a CWRType"
msgstr "add a relation type"
-msgid "add a CWRelation"
-msgstr "add a relation"
-
msgid "add a CWUser"
msgstr "add a user"
@@ -896,6 +900,18 @@
msgid "allowed_transition_object"
msgstr "incoming states"
+msgid "am/pm calendar (month)"
+msgstr ""
+
+msgid "am/pm calendar (semester)"
+msgstr ""
+
+msgid "am/pm calendar (week)"
+msgstr ""
+
+msgid "am/pm calendar (year)"
+msgstr ""
+
msgid "an electronic mail address associated to a short alias"
msgstr ""
@@ -933,6 +949,9 @@
msgid "attribute"
msgstr ""
+msgid "attributes with modified permissions:"
+msgstr ""
+
msgid "august"
msgstr ""
@@ -1044,6 +1063,18 @@
msgid "calendar"
msgstr ""
+msgid "calendar (month)"
+msgstr ""
+
+msgid "calendar (semester)"
+msgstr ""
+
+msgid "calendar (week)"
+msgstr ""
+
+msgid "calendar (year)"
+msgstr ""
+
#, python-format
msgid "can't change the %s attribute"
msgstr ""
@@ -1074,6 +1105,9 @@
msgid "cardinality"
msgstr ""
+msgid "category"
+msgstr ""
+
#, python-format
msgid "changed state of %(etype)s #%(eid)s (%(title)s)"
msgstr ""
@@ -1084,6 +1118,9 @@
msgid "click on the box to cancel the deletion"
msgstr ""
+msgid "close all"
+msgstr ""
+
msgid "comment"
msgstr ""
@@ -1153,6 +1190,12 @@
msgid "components_rqlinput_description"
msgstr "the rql box in the page's header"
+msgid "components_rss_feed_url"
+msgstr ""
+
+msgid "components_rss_feed_url_description"
+msgstr ""
+
msgid "composite"
msgstr ""
@@ -1292,31 +1335,28 @@
msgid "creating Bookmark (Bookmark bookmarked_by CWUser %(linkto)s)"
msgstr "creating bookmark for %(linkto)s"
+msgid "creating CWConstraint (CWAttribute %(linkto)s constrained_by CWConstraint)"
+msgstr "creating constraint for attribute %(linkto)s"
+
+msgid "creating CWConstraint (CWRelation %(linkto)s constrained_by CWConstraint)"
+msgstr "creating constraint for relation %(linkto)s"
+
msgid "creating CWAttribute (CWAttribute relation_type CWRType %(linkto)s)"
msgstr "creating attribute %(linkto)s"
-msgid ""
-"creating CWConstraint (CWAttribute %(linkto)s constrained_by CWConstraint)"
-msgstr "creating constraint for attribute %(linkto)s"
-
-msgid ""
-"creating CWConstraint (CWRelation %(linkto)s constrained_by CWConstraint)"
-msgstr "creating constraint for relation %(linkto)s"
+msgid "creating CWRelation (CWRelation relation_type CWRType %(linkto)s)"
+msgstr "creating relation %(linkto)s"
msgid "creating CWProperty (CWProperty for_user CWUser %(linkto)s)"
msgstr "creating property for user %(linkto)s"
-msgid "creating CWRelation (CWRelation relation_type CWRType %(linkto)s)"
-msgstr "creating relation %(linkto)s"
-
msgid "creating CWUser (CWUser in_group CWGroup %(linkto)s)"
msgstr "creating a new user in group %(linkto)s"
msgid "creating EmailAddress (CWUser %(linkto)s use_email EmailAddress)"
msgstr "creating email address for user %(linkto)s"
-msgid ""
-"creating RQLExpression (CWEType %(linkto)s add_permission RQLExpression)"
+msgid "creating RQLExpression (CWEType %(linkto)s add_permission RQLExpression)"
msgstr "creating rql expression for add permission on %(linkto)s"
msgid ""
@@ -1331,8 +1371,7 @@
"creating RQLExpression (CWEType %(linkto)s update_permission RQLExpression)"
msgstr "creating rql expression for update permission on %(linkto)s"
-msgid ""
-"creating RQLExpression (CWRType %(linkto)s add_permission RQLExpression)"
+msgid "creating RQLExpression (CWRType %(linkto)s add_permission RQLExpression)"
msgstr "creating rql expression for add permission on relations %(linkto)s"
msgid ""
@@ -1501,9 +1540,6 @@
msgid "destination_state_object"
msgstr "destination of"
-msgid "detach attached file"
-msgstr ""
-
#, python-format
msgid "detach attached file %s"
msgstr ""
@@ -1582,18 +1618,9 @@
msgid "entities deleted"
msgstr ""
-msgid "entity copied"
-msgstr ""
-
-msgid "entity created"
-msgstr ""
-
msgid "entity deleted"
msgstr ""
-msgid "entity edited"
-msgstr ""
-
msgid "entity type"
msgstr ""
@@ -1700,10 +1727,6 @@
msgid "from"
msgstr ""
-#, python-format
-msgid "from %(date)s"
-msgstr ""
-
msgid "from_entity"
msgstr "from entity"
@@ -1788,7 +1811,7 @@
msgstr ""
msgid "hide meta-data"
-msgstr ""
+msgstr "hide meta entities and relations"
msgid "home"
msgstr ""
@@ -2003,6 +2026,11 @@
msgid "link a transition to one or more entity type"
msgstr ""
+msgid ""
+"link a transition to one or more rql expression allowing to go through this "
+"transition"
+msgstr ""
+
msgid "link to each item in"
msgstr ""
@@ -2018,9 +2046,6 @@
msgid "login"
msgstr ""
-msgid "login or email"
-msgstr ""
-
msgid "login_action"
msgstr "log in"
@@ -2124,6 +2149,18 @@
msgid "navigation"
msgstr ""
+msgid "navigation.combobox-limit"
+msgstr "\"related\" combo-box"
+
+msgid "navigation.page-size"
+msgstr "number of results"
+
+msgid "navigation.related-limit"
+msgstr "number of entities in the primary view "
+
+msgid "navigation.short-line-size"
+msgstr "short description"
+
msgid "navtop"
msgstr "page top"
@@ -2176,6 +2213,9 @@
msgid "object"
msgstr ""
+msgid "object_plural:"
+msgstr "objects:"
+
msgid "october"
msgstr ""
@@ -2191,6 +2231,9 @@
msgid "only select queries are authorized"
msgstr ""
+msgid "open all"
+msgstr ""
+
msgid "order"
msgstr ""
@@ -2234,6 +2277,12 @@
msgid "permission"
msgstr ""
+msgid "permissions for entities"
+msgstr ""
+
+msgid "permissions for relations"
+msgstr ""
+
msgid "permissions for this entity"
msgstr ""
@@ -2301,6 +2350,9 @@
msgid "relation_type_object"
msgstr "relation definitions"
+msgid "relations"
+msgstr ""
+
msgid "relations deleted"
msgstr ""
@@ -2310,9 +2362,6 @@
msgid "remove this Bookmark"
msgstr "remove this bookmark"
-msgid "remove this CWAttribute"
-msgstr "remove this attribute"
-
msgid "remove this CWCache"
msgstr ""
@@ -2325,9 +2374,15 @@
msgid "remove this CWEType"
msgstr "remove this entity type"
+msgid "remove this CWAttribute"
+msgstr "remove this attribute"
+
msgid "remove this CWGroup"
msgstr "remove this group"
+msgid "remove this CWRelation"
+msgstr "remove this relation"
+
msgid "remove this CWPermission"
msgstr "remove this permission"
@@ -2337,9 +2392,6 @@
msgid "remove this CWRType"
msgstr "remove this relation type"
-msgid "remove this CWRelation"
-msgstr "remove this relation"
-
msgid "remove this CWUser"
msgstr "remove this user"
@@ -2437,9 +2489,6 @@
msgid "select a"
msgstr ""
-msgid "select a key first"
-msgstr ""
-
msgid "select a relation"
msgstr ""
@@ -2496,7 +2545,7 @@
msgstr ""
msgid "show meta-data"
-msgstr ""
+msgstr "show the complete schema"
msgid "site configuration"
msgstr ""
@@ -2550,6 +2599,9 @@
msgid "subject/object cardinality"
msgstr ""
+msgid "subject_plural:"
+msgstr "subjects:"
+
msgid "sunday"
msgstr ""
@@ -2620,10 +2672,6 @@
msgid "to"
msgstr ""
-#, python-format
-msgid "to %(date)s"
-msgstr ""
-
msgid "to associate with"
msgstr ""
@@ -2642,9 +2690,6 @@
msgid "todo_by"
msgstr "to do by"
-msgid "toggle check boxes"
-msgstr ""
-
msgid "transition is not allowed"
msgstr ""
@@ -2666,6 +2711,36 @@
msgid "ui"
msgstr ""
+msgid "ui.date-format"
+msgstr "date format"
+
+msgid "ui.datetime-format"
+msgstr "date and time format"
+
+msgid "ui.default-text-format"
+msgstr "text format"
+
+msgid "ui.encoding"
+msgstr "encoding"
+
+msgid "ui.fckeditor"
+msgstr "content editor"
+
+msgid "ui.float-format"
+msgstr "float format"
+
+msgid "ui.language"
+msgstr "language"
+
+msgid "ui.main-template"
+msgstr "main template"
+
+msgid "ui.site-title"
+msgstr "site title"
+
+msgid "ui.time-format"
+msgstr "time format"
+
msgid "unaccessible"
msgstr ""
@@ -2681,6 +2756,9 @@
msgid "unknown property key"
msgstr ""
+msgid "up"
+msgstr ""
+
msgid "upassword"
msgstr "password"
@@ -2826,9 +2904,6 @@
msgid "you have been logged out"
msgstr ""
-msgid "you should probably delete that property"
-msgstr ""
-
#~ msgid "Card"
#~ msgstr "Card"
@@ -2847,17 +2922,11 @@
#~ msgid "content_format"
#~ msgstr "content format"
-#~ msgid "i18n_register_user"
-#~ msgstr "register"
-
#~ msgid "planned_delivery"
#~ msgstr "planned delivery"
#~ msgid "remove this Card"
#~ msgstr "remove this card"
-#~ msgid "trcomment"
-#~ msgstr "comment"
-
#~ msgid "wikiid"
#~ msgstr "wiki identifier"
--- a/i18n/es.po Tue May 05 12:07:42 2009 +0200
+++ b/i18n/es.po Tue May 05 17:13:37 2009 +0200
@@ -5,8 +5,8 @@
msgstr ""
"Project-Id-Version: cubicweb 2.46.0\n"
"PO-Revision-Date: 2008-11-27 07:59+0100\n"
-"Last-Translator: Celso <contact@logilab.fr>\n"
-"Language-Team: fr <contact@logilab.fr>\n"
+"Last-Translator: Celso Flores<jcelsoflores@gmail.com>\n"
+"Language-Team: es <contact@logilab.fr>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -23,8 +23,8 @@
"url: %(url)s\n"
msgstr ""
"\n"
-"%(user)s a cambiado su estado de <%(previous_state)s> hacia <%(current_state)"
-"s> por la entidad\n"
+"%(user)s ha cambiado su estado de <%(previous_state)s> hacia <%"
+"(current_state)s> por la entidad\n"
"'%(title)s'\n"
"\n"
"%(comment)s\n"
@@ -33,7 +33,7 @@
#, python-format
msgid " from state %(fromstate)s to state %(tostate)s\n"
-msgstr " de el estado %(fromstate)s hacia el estado %(tostate)s\n"
+msgstr " del estado %(fromstate)s hacia el estado %(tostate)s\n"
#, python-format
msgid "%(cstr)s constraint failed for value %(value)r"
@@ -121,7 +121,11 @@
#, python-format
msgid "%s software version of the database"
-msgstr "version sistema de la base para %s"
+msgstr "versión sistema de la base para %s"
+
+#, python-format
+msgid "%s_perm"
+msgstr ""
msgid "**"
msgstr "0..n 0..n"
@@ -181,10 +185,10 @@
msgstr "Aplicación"
msgid "Bookmark"
-msgstr "Atajo"
+msgstr "Favorito"
msgid "Bookmark_plural"
-msgstr "Atajos"
+msgstr "Favoritos"
msgid "Boolean"
msgstr "Booleano"
@@ -193,79 +197,13 @@
msgstr "Booleanos"
msgid "Browse by category"
-msgstr "Selecciona por categoría"
+msgstr "Busca por categoría"
msgid "Bytes"
-msgstr "Datos binarios"
+msgstr "Bytes"
msgid "Bytes_plural"
-msgstr "Datos binarios"
-
-msgid "CWAttribute"
-msgstr "Atributo"
-
-msgid "CWAttribute_plural"
-msgstr "Atributos"
-
-msgid "CWCache"
-msgstr "Memoria Cache"
-
-msgid "CWCache_plural"
-msgstr "Memorias Caches"
-
-msgid "CWConstraint"
-msgstr "Condición"
-
-msgid "CWConstraintType"
-msgstr "Tipo de condición"
-
-msgid "CWConstraintType_plural"
-msgstr "Tipos de condición"
-
-msgid "CWConstraint_plural"
-msgstr "Condiciones"
-
-msgid "CWEType"
-msgstr "Tipo de entidades"
-
-msgid "CWEType_plural"
-msgstr "Tipos de entidades"
-
-msgid "CWGroup"
-msgstr "Groupo"
-
-msgid "CWGroup_plural"
-msgstr "Groupos"
-
-msgid "CWPermission"
-msgstr "Autorización"
-
-msgid "CWPermission_plural"
-msgstr "Autorizaciones"
-
-msgid "CWProperty"
-msgstr "Propiedad"
-
-msgid "CWProperty_plural"
-msgstr "Propiedades"
-
-msgid "CWRType"
-msgstr "Tipo de relación"
-
-msgid "CWRType_plural"
-msgstr "Tipos de relación"
-
-msgid "CWRelation"
-msgstr "Relación"
-
-msgid "CWRelation_plural"
-msgstr "Relaciones"
-
-msgid "CWUser"
-msgstr "Usuario"
-
-msgid "CWUser_plural"
-msgstr "Usuarios"
+msgstr "Bytes"
msgid "Date"
msgstr "Fecha"
@@ -284,22 +222,91 @@
msgstr "Nivel de debug puesto a %s"
msgid "Decimal"
-msgstr "Número decimal"
+msgstr "Decimal"
msgid "Decimal_plural"
-msgstr "Números decimales"
+msgstr "Decimales"
msgid "Do you want to delete the following element(s) ?"
msgstr "Desea suprimir el(los) elemento(s) siguiente(s)"
+msgid "CWCache"
+msgstr "Cache"
+
+msgid "CWCache_plural"
+msgstr "Caches"
+
+msgid "CWConstraint"
+msgstr "Restricción"
+
+msgid "CWConstraintType"
+msgstr "Tipo de Restricción"
+
+msgid "CWConstraintType_plural"
+msgstr "Tipos de Restricción"
+
+msgid "CWConstraint_plural"
+msgstr "Restricciones"
+
+msgid "CWEType"
+msgstr "Tipo de entidad"
+
+msgid "CWEType_plural"
+msgstr "Tipos de entidades"
+
+msgid "CWAttribute"
+msgstr "Atributo"
+
+msgid "CWAttribute_plural"
+msgstr "Atributos"
+
+msgid "CWGroup"
+msgstr "Groupo"
+
+msgid "CWGroup_plural"
+msgstr "Groupos"
+
+msgid "CWRelation"
+msgstr "Relación"
+
+msgid "CWRelation_plural"
+msgstr "Relaciones"
+
+msgid "CWPermission"
+msgstr "Autorización"
+
+msgid "CWPermission_plural"
+msgstr "Autorizaciones"
+
+msgid "CWProperty"
+msgstr "Propiedad"
+
+msgid "CWProperty_plural"
+msgstr "Propiedades"
+
+msgid "CWRType"
+msgstr "Tipo de relación"
+
+msgid "CWRType_plural"
+msgstr "Tipos de relación"
+
+msgid "CWUser"
+msgstr "Usuario"
+
+msgid "CWUser_plural"
+msgstr "Usuarios"
+
+msgid "Email body: "
+msgstr "Contenido del correo electrónico : "
+
msgid "EmailAddress"
msgstr "Correo Electrónico"
msgid "EmailAddress_plural"
-msgstr "Direcciónes de Correo Electrónico"
+msgstr "Direcciones de Correo Electrónico"
msgid "Entities"
-msgstr "entidades"
+msgstr "Entidades"
msgid "Environment"
msgstr "Ambiente"
@@ -310,8 +317,8 @@
msgid "Float_plural"
msgstr "Números flotantes"
-msgid "From:"
-msgstr ""
+msgid "From: "
+msgstr "De : "
msgid "Int"
msgstr "Número entero"
@@ -326,55 +333,55 @@
msgstr "Duraciones"
msgid "New Bookmark"
-msgstr "Nuevo Atajo"
+msgstr "Agregar a Favoritos"
+
+msgid "New CWCache"
+msgstr "Agregar Cache"
+
+msgid "New CWConstraint"
+msgstr "Agregar Restricción"
+
+msgid "New CWConstraintType"
+msgstr "Agregar tipo de Restricción"
+
+msgid "New CWEType"
+msgstr "Agregar tipo de entidad"
msgid "New CWAttribute"
msgstr "Nueva definición de relación final"
-msgid "New CWCache"
-msgstr "Nueva memoria cache"
-
-msgid "New CWConstraint"
-msgstr "Nueva condición"
-
-msgid "New CWConstraintType"
-msgstr "Nuevo tipo de condición"
-
-msgid "New CWEType"
-msgstr "Nuevo tipo de entidad"
-
msgid "New CWGroup"
msgstr "Nuevo grupo"
+msgid "New CWRelation"
+msgstr "Nueva definición de relación final"
+
msgid "New CWPermission"
-msgstr "Nueva autorización"
+msgstr "Agregar autorización"
msgid "New CWProperty"
-msgstr "Nueva Propiedad"
+msgstr "Agregar Propiedad"
msgid "New CWRType"
-msgstr "Nuevo tipo de relación"
-
-msgid "New CWRelation"
-msgstr "Nueva definición de relación final"
+msgstr "Agregar tipo de relación"
msgid "New CWUser"
-msgstr "Nuevo usuario"
+msgstr "Agregar usuario"
msgid "New EmailAddress"
-msgstr "Nuevo Email"
+msgstr "Agregar Email"
msgid "New RQLExpression"
-msgstr "Nueva expresión rql"
+msgstr "Agregar expresión rql"
msgid "New State"
-msgstr "Nuevo Estado"
+msgstr "Agregar Estado"
msgid "New TrInfo"
-msgstr "Nueva Información de Transición"
+msgstr "Agregar Información de Transición"
msgid "New Transition"
-msgstr "Nueva transición"
+msgstr "Agregar transición"
msgid "No query has been executed"
msgstr "Ninguna búsqueda ha sido ejecutada"
@@ -394,20 +401,23 @@
msgid "Please note that this is only a shallow copy"
msgstr "Recuerde que no es más que una copia superficial"
+msgid "Problem occured"
+msgstr "Ha ocurrido un error"
+
msgid "RQLExpression"
msgstr "Expresión RQL"
msgid "RQLExpression_plural"
msgstr "Expresiones RQL"
-msgid "Recipients:"
-msgstr ""
+msgid "Recipients: "
+msgstr "Destinatarios : "
msgid "Relations"
msgstr "Relaciones"
msgid "Request"
-msgstr "Búsqueda"
+msgstr "Petición"
#, python-format
msgid "Schema %s"
@@ -420,7 +430,7 @@
msgstr "Servidor"
msgid "Startup views"
-msgstr "Vistas de inicio"
+msgstr "Vistas de Inicio"
msgid "State"
msgstr "Estado"
@@ -429,13 +439,13 @@
msgstr "Estados"
msgid "String"
-msgstr "Cadena de caractéres"
+msgstr "Cadena de caracteres"
msgid "String_plural"
-msgstr "Cadenas de caractéres"
-
-msgid "Subject:"
-msgstr ""
+msgstr "Cadenas de caracteres"
+
+msgid "Subject: "
+msgstr "Objeto : "
msgid "Submit bug report"
msgstr "Enviar un reporte de error (bug)"
@@ -459,26 +469,29 @@
msgstr "Este %s"
msgid "This Bookmark"
-msgstr "Este atajo"
+msgstr "Este favorito"
+
+msgid "This CWCache"
+msgstr "Este Cache"
+
+msgid "This CWConstraint"
+msgstr "Esta Restricción"
+
+msgid "This CWConstraintType"
+msgstr "Este tipo de Restricción"
+
+msgid "This CWEType"
+msgstr "Este tipo de Entidad"
msgid "This CWAttribute"
msgstr "Esta definición de relación final"
-msgid "This CWCache"
-msgstr "Esta Memoria Cache"
-
-msgid "This CWConstraint"
-msgstr "Esta condición"
-
-msgid "This CWConstraintType"
-msgstr "Este tipo de condición"
-
-msgid "This CWEType"
-msgstr "Este tipo de Entidad"
-
msgid "This CWGroup"
msgstr "Este grupo"
+msgid "This CWRelation"
+msgstr "Esta definición de relación no final"
+
msgid "This CWPermission"
msgstr "Esta autorización"
@@ -488,9 +501,6 @@
msgid "This CWRType"
msgstr "Este tipo de relación"
-msgid "This CWRelation"
-msgstr "Esta definición de relación no final"
-
msgid "This CWUser"
msgstr "Este usuario"
@@ -535,10 +545,10 @@
msgstr "Utilizado por :"
msgid "What's new?"
-msgstr "Ultimas Noticias"
+msgstr "Lo último en el sitio"
msgid "Workflow history"
-msgstr "Registro de cambios de estado"
+msgstr "Histórico del Workflow"
msgid "You are not connected to an application !"
msgstr "Usted no esta conectado a una aplicación"
@@ -553,7 +563,7 @@
"box, or edit file content online with the widget below."
msgstr ""
"Usted puede proponer un nuevo archivo utilizando el botón\n"
-"\"buscar\" aqui arriba, o eliminar el archivo ya elegido al\n"
+"\"buscar\" aquí arriba, o eliminar el archivo ya elegido al\n"
"seleccionar el cuadro \"soltar archivo adjunto\", o editar el contenido\n"
"del archivo en línea con el componente inferior."
@@ -567,7 +577,7 @@
msgid "You can use any of the following substitutions in your text"
msgstr ""
-"Puede realizar cualquiera de las siguietes sustituciones en el contenido de "
+"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"
@@ -577,8 +587,8 @@
"You're not authorized to access this page. If you think you should, please "
"contact the site administrator."
msgstr ""
-"Usted no esta autorizado a acceder a esta página. Si Usted cree aue \n"
-"es un error, favor de contactar al administrador del sitio."
+"Usted no esta autorizado a acceder a esta página. Si Usted cree que \n"
+"hay un error, favor de contactar al administrador del sitio."
#, python-format
msgid "[%s supervision] changes summary"
@@ -592,9 +602,9 @@
"be available. This query may use X and U variables that will respectivly "
"represents the current entity and the current user"
msgstr ""
-"una expresión RQL deviendo regresado resultado para que la transición pueda "
-"ser realizada. Esta expresión puede utilizar las variables X y U que "
-"representan respectivamente la entidad en transición y el usuarioactual. "
+"una expresión RQL que debe haber enviado resultados, para que la transición "
+"pueda ser realizada. Esta expresión puede utilizar las variables X y U que "
+"representan respectivamente la entidad en transición y el usuario actual. "
msgid ""
"a simple cache entity characterized by a name and a validity date. The "
@@ -602,12 +612,16 @@
"invalidate the cache (typically in hooks). Also, checkout the AppRsetObject."
"get_cache() method."
msgstr ""
+"una entidad cache simple caracterizada por un nombre y una fecha correcta. "
+"El sistema objetivo es responsable de actualizar timestamp cuand se "
+"necesario para invalidar el cache (usualmente en hooks).Recomendamos revisar "
+"el METODO AppRsetObject.get_cache()."
msgid "about this site"
-msgstr "Sobre este espacio"
+msgstr "Sobre este Espacio"
msgid "access type"
-msgstr "tipo de acceso"
+msgstr "Tipo de Acceso"
msgid "account state"
msgstr "Estado de la Cuenta"
@@ -625,65 +639,59 @@
msgstr ""
msgid "actions_cancel"
-msgstr "Anular la selección"
+msgstr "Anular"
msgid "actions_cancel_description"
msgstr ""
msgid "actions_copy"
-msgstr "copiar"
+msgstr "Copiar"
msgid "actions_copy_description"
msgstr ""
msgid "actions_delete"
-msgstr "eliminar"
+msgstr "Eliminar"
msgid "actions_delete_description"
msgstr ""
msgid "actions_download_as_owl"
-msgstr ""
+msgstr "Download como OWL"
msgid "actions_download_as_owl_description"
msgstr ""
msgid "actions_edit"
-msgstr "modificar"
+msgstr "Modificar"
msgid "actions_edit_description"
msgstr ""
msgid "actions_embed"
-msgstr "embarcar"
+msgstr "Embarcar"
msgid "actions_embed_description"
msgstr ""
msgid "actions_follow"
-msgstr "seguir"
+msgstr "Seguir"
msgid "actions_follow_description"
msgstr ""
msgid "actions_logout"
-msgstr "desconectarse"
+msgstr "Desconectarse"
msgid "actions_logout_description"
msgstr ""
msgid "actions_manage"
-msgstr "administración del sitio"
+msgstr "Administración del sitio"
msgid "actions_manage_description"
msgstr ""
-msgid "actions_managepermission"
-msgstr ""
-
-msgid "actions_managepermission_description"
-msgstr ""
-
msgid "actions_muledit"
msgstr "Edición múltiple"
@@ -691,82 +699,76 @@
msgstr ""
msgid "actions_myinfos"
-msgstr "información personal"
+msgstr "Información personal"
msgid "actions_myinfos_description"
msgstr ""
msgid "actions_myprefs"
-msgstr "preferencias del usuario"
+msgstr "Preferencias del usuario"
msgid "actions_myprefs_description"
msgstr ""
msgid "actions_prefs"
-msgstr "preferencias"
+msgstr "Preferencias"
msgid "actions_prefs_description"
msgstr ""
msgid "actions_schema"
-msgstr "ver el esquema"
+msgstr "Ver el esquema"
msgid "actions_schema_description"
msgstr ""
msgid "actions_select"
-msgstr "seleccionar"
+msgstr "Seleccionar"
msgid "actions_select_description"
msgstr ""
msgid "actions_sendemail"
-msgstr "enviar un email"
+msgstr "Enviar un email"
msgid "actions_sendemail_description"
msgstr ""
msgid "actions_siteconfig"
-msgstr "configuración del sitio"
+msgstr "Configuración del sitio"
msgid "actions_siteconfig_description"
msgstr ""
msgid "actions_view"
-msgstr "ver"
+msgstr "Ver"
msgid "actions_view_description"
msgstr ""
msgid "actions_workflow"
-msgstr "ver el workflow"
+msgstr "Ver el workflow"
msgid "actions_workflow_description"
msgstr ""
msgid "activate"
-msgstr "activar"
+msgstr "Activar"
msgid "activated"
-msgstr "activado"
+msgstr "Activado"
msgid "add"
-msgstr "agregar"
+msgstr "Agregar"
msgid "add Bookmark bookmarked_by CWUser object"
-msgstr ""
-
-msgid "add CWAttribute constrained_by CWConstraint subject"
-msgstr "condición"
-
-msgid "add CWAttribute relation_type CWRType object"
-msgstr "definición de atributo"
+msgstr "Agregar a los favoritos "
msgid "add CWEType add_permission RQLExpression subject"
-msgstr "Definir una expresión RQL de agregación"
+msgstr "Agregar una autorización"
msgid "add CWEType delete_permission RQLExpression subject"
-msgstr "Definir una expresión RQL de eliminación"
+msgstr "Eliminar una autorización"
msgid "add CWEType read_permission RQLExpression subject"
msgstr "Definir una expresión RQL de lectura"
@@ -774,130 +776,136 @@
msgid "add CWEType update_permission RQLExpression subject"
msgstr "Definir una expresión RQL de actualización"
+msgid "add CWAttribute constrained_by CWConstraint subject"
+msgstr "Restricción"
+
+msgid "add CWAttribute relation_type CWRType object"
+msgstr "Definición de atributo"
+
+msgid "add CWRelation constrained_by CWConstraint subject"
+msgstr "Restricción"
+
+msgid "add CWRelation relation_type CWRType object"
+msgstr "Definición de relación"
+
msgid "add CWProperty for_user CWUser object"
-msgstr "propiedad"
+msgstr "Agregar Propiedad"
msgid "add CWRType add_permission RQLExpression subject"
-msgstr "expresión RQL de agregación"
+msgstr "Agregar expresión RQL de agregación"
msgid "add CWRType delete_permission RQLExpression subject"
-msgstr "expresión RQL de eliminación"
+msgstr "Agregar expresión RQL de eliminación"
msgid "add CWRType read_permission RQLExpression subject"
-msgstr "expresión RQL de lectura"
-
-msgid "add CWRelation constrained_by CWConstraint subject"
-msgstr "condición"
-
-msgid "add CWRelation relation_type CWRType object"
-msgstr "definición de relación"
+msgstr "Agregar expresión RQL de lectura"
msgid "add CWUser in_group CWGroup object"
-msgstr "usuario"
+msgstr "Agregar usuario"
msgid "add CWUser use_email EmailAddress subject"
-msgstr "agregar email"
+msgstr "Agregar email"
msgid "add State allowed_transition Transition object"
-msgstr "agregar un estado en entrada"
+msgstr "Agregar un estado en entrada"
msgid "add State allowed_transition Transition subject"
-msgstr "agregar una transición en salida"
+msgstr "Agregar una transición en salida"
msgid "add State state_of CWEType object"
-msgstr "agregar un estado"
+msgstr "Agregar un estado"
msgid "add Transition condition RQLExpression subject"
-msgstr "agregar una condición"
+msgstr "Agregar una Restricción"
msgid "add Transition destination_state State object"
-msgstr "agregar una transición de entrada"
+msgstr "Agregar una transición de entrada"
msgid "add Transition destination_state State subject"
-msgstr "agregar el estado de salida"
+msgstr "Agregar el estado de salida"
msgid "add Transition transition_of CWEType object"
-msgstr "agregar una transición"
+msgstr "Agregar una transición"
msgid "add a Bookmark"
-msgstr "agregar un atajo"
-
-msgid "add a CWAttribute"
-msgstr "agregar un tipo de relación"
+msgstr "Agregar un Favorito"
msgid "add a CWCache"
-msgstr "agregar una memoria cache"
+msgstr "Agregar un cache"
msgid "add a CWConstraint"
-msgstr "agregar una condición"
+msgstr "Agregar una Restricción"
msgid "add a CWConstraintType"
-msgstr "aun tipo de condición"
+msgstr "Agregar un tipo de Restricción"
msgid "add a CWEType"
-msgstr "agregar un tipo de entidad"
+msgstr "Agregar un tipo de entidad"
+
+msgid "add a CWAttribute"
+msgstr "Agregar un tipo de relación"
msgid "add a CWGroup"
-msgstr "agregar un grupo de usuarios"
-
-msgid "add a CWPermission"
-msgstr "agregar una autorización"
-
-msgid "add a CWProperty"
-msgstr "agregar una propiedad"
-
-msgid "add a CWRType"
-msgstr "agregar un tipo de relación"
+msgstr "Agregar un grupo de usuarios"
msgid "add a CWRelation"
-msgstr "agregar una relación"
+msgstr "Agregar una relación"
+
+msgid "add a CWPermission"
+msgstr "Agregar una autorización"
+
+msgid "add a CWProperty"
+msgstr "Agregar una propiedad"
+
+msgid "add a CWRType"
+msgstr "Agregar un tipo de relación"
msgid "add a CWUser"
-msgstr "agregar un usuario"
+msgstr "Agregar un usuario"
msgid "add a EmailAddress"
-msgstr "agregar un email"
+msgstr "Agregar un email"
msgid "add a RQLExpression"
-msgstr "agregar una expresión rql"
+msgstr "Agregar una expresión rql"
msgid "add a State"
-msgstr "agregar un estado"
+msgstr "Agregar un estado"
msgid "add a TrInfo"
-msgstr "agregar una información de transición"
+msgstr "Agregar una información de transición"
msgid "add a Transition"
-msgstr "agregar una transición"
+msgstr "Agregar una transición"
msgid "add a new permission"
-msgstr "agregar una autorización"
+msgstr "Agregar una autorización"
msgid "add relation"
-msgstr "agregar una relación"
+msgstr "Agregar una relación"
msgid "add_perm"
-msgstr "agregado"
+msgstr "Agregado"
# subject and object forms for each relation type
# (no object form for final relation types)
msgid "add_permission"
-msgstr "autorización para agregar"
+msgstr "Autorización para agregar"
msgid "add_permission_object"
msgstr "tiene la autorización para agregar"
#, python-format
msgid "added %(etype)s #%(eid)s (%(title)s)"
-msgstr "agregado de la entidad %(etype)s #%(eid)s (%(title)s)"
+msgstr "Agregado %(etype)s #%(eid)s (%(title)s)"
#, python-format
msgid ""
"added relation %(rtype)s from %(frometype)s #%(fromeid)s to %(toetype)s #%"
"(toeid)s"
msgstr ""
-"agregado de la relación %(rtype)s de %(frometype)s #%(fromeid)s hacia %"
-"(toetype)s #%(toeid)s"
+"Relación agregada %(rtype)s de %(frometype)s #%(fromeid)s hacia %(toetype)s #"
+"%(toeid)s"
msgid "address"
msgstr "dirección"
@@ -917,11 +925,23 @@
msgid "allowed_transition_object"
msgstr "Estados de entrada"
+msgid "am/pm calendar (month)"
+msgstr "calendario am/pm (mes)"
+
+msgid "am/pm calendar (semester)"
+msgstr "calendario am/pm (semestre)"
+
+msgid "am/pm calendar (week)"
+msgstr "calendario am/pm (semana)"
+
+msgid "am/pm calendar (year)"
+msgstr "calendario am/pm (año)"
+
msgid "an electronic mail address associated to a short alias"
msgstr "una dirección electrónica asociada a este alias"
msgid "an error occured"
-msgstr "a ocurrido un error"
+msgstr "ha ocurrido un error"
msgid "an error occured while processing your request"
msgstr "un error ocurrió al procesar su demanda"
@@ -936,16 +956,16 @@
msgstr "y/o entre los diferentes valores"
msgid "anonymous"
-msgstr "anónimo"
+msgstr "Anónimo"
msgid "application entities"
-msgstr "entidades de la aplicación"
+msgstr "Entidades de la aplicación"
msgid "application schema"
-msgstr "esquema de la aplicación"
+msgstr "Esquema de la aplicación"
msgid "april"
-msgstr "abril"
+msgstr "Abril"
#, python-format
msgid "at least one relation %(rtype)s is required on %(etype)s (%(eid)s)"
@@ -954,121 +974,135 @@
"otra via la relación %(rtype)s"
msgid "attribute"
-msgstr "atributo"
+msgstr "Atributo"
+
+msgid "attributes with modified permissions:"
+msgstr ""
msgid "august"
-msgstr "agosto"
+msgstr "Agosto"
msgid "authentication failure"
msgstr "Usuario o contraseña incorrecta"
msgid "automatic"
-msgstr "automático"
+msgstr "Automático"
msgid "bad value"
-msgstr "valor erróneo"
+msgstr "Valor erróneo"
msgid "base url"
-msgstr "url de base"
+msgstr "Url de base"
msgid "bookmark has been removed"
-msgstr "el atajo ha sido eliminado"
+msgstr "ha sido eliminado de sus favoritos"
msgid "bookmark this page"
-msgstr "Agregue un atajo a esta página"
+msgstr "Agregar esta página a sus favoritos"
msgid "bookmark this search"
-msgstr "Guarde esta búsqueda"
+msgstr "Guardar esta búsqueda"
msgid "bookmarked_by"
-msgstr "utilizada por"
+msgstr "está en los favoritos de"
msgid "bookmarked_by_object"
-msgstr "tiene como atajo"
+msgstr "selecciona en sus favoritos a"
msgid "bookmarks"
-msgstr "atajos"
+msgstr "Favoritos"
msgid "boxes"
-msgstr "cajas"
+msgstr "Cajas"
msgid "boxes_bookmarks_box"
-msgstr "caja de atajos"
+msgstr "Caja de Favoritos"
msgid "boxes_bookmarks_box_description"
-msgstr "Caja que contiene los atajos del usuario"
+msgstr "Caja que contiene los espacios favoritos del usuario"
msgid "boxes_download_box"
-msgstr ""
+msgstr "Caja de download"
msgid "boxes_download_box_description"
-msgstr ""
+msgstr "Caja que contiene los elementos bajados"
msgid "boxes_edit_box"
-msgstr "caja de acciones"
+msgstr "Caja de acciones"
msgid "boxes_edit_box_description"
msgstr ""
-"caja aue muestra las diferentes acciones posibles sobre los datos presentes"
+"Caja que muestra las diferentes acciones posibles sobre los datos presentes"
msgid "boxes_filter_box"
-msgstr "filtrar"
+msgstr "Filtros"
msgid "boxes_filter_box_description"
-msgstr ""
-"caja permitiendo de realizar filtros sobre los resultados de una búsqueda"
+msgstr "Caja que permite realizar filtros sobre los resultados de una búsqueda"
msgid "boxes_possible_views_box"
-msgstr "caja de vistas posibles"
+msgstr "Caja de Vistas Posibles"
msgid "boxes_possible_views_box_description"
-msgstr "caja mostrando las vistas posibles para los datos actuales"
+msgstr "Caja mostrando las vistas posibles para los datos actuales"
msgid "boxes_rss"
msgstr "ícono RSS"
msgid "boxes_rss_description"
-msgstr "el ícono RSS permite recuperar las vistas RSS de los datos presentes"
+msgstr "El ícono RSS permite recuperar las vistas RSS de los datos presentes"
msgid "boxes_search_box"
-msgstr "caja de búsqueda"
+msgstr "Caja de búsqueda"
msgid "boxes_search_box_description"
-msgstr "caja con un espacio de búsqueda simple"
+msgstr "Caja con un espacio de búsqueda simple"
msgid "boxes_startup_views_box"
-msgstr "caja de las vistas de inicio"
+msgstr "Caja Vistas de inicio"
msgid "boxes_startup_views_box_description"
-msgstr "caja mostrando las vistas de inicio de la aplicación"
+msgstr "Caja mostrando las vistas de inicio de la aplicación"
msgid "bug report sent"
-msgstr "reporte de error enviado"
+msgstr "Reporte de error enviado"
msgid "button_apply"
-msgstr "aplicar"
+msgstr "Aplicar"
msgid "button_cancel"
-msgstr "anular"
+msgstr "Cancelar"
msgid "button_delete"
-msgstr "eliminar"
+msgstr "Eliminar"
msgid "button_ok"
-msgstr "validar"
+msgstr "Validar"
msgid "button_reset"
-msgstr "anular los cambios"
+msgstr "Cancelar los cambios"
msgid "by"
msgstr "por"
msgid "by relation"
-msgstr "por la relación"
+msgstr "por relación"
msgid "calendar"
msgstr "mostrar un calendario"
+msgid "calendar (month)"
+msgstr "calendario (mensual)"
+
+msgid "calendar (semester)"
+msgstr "calendario (semestral)"
+
+msgid "calendar (week)"
+msgstr "calendario (semanal)"
+
+msgid "calendar (year)"
+msgstr "calendario (anual)"
+
#, python-format
msgid "can't change the %s attribute"
msgstr "no puede modificar el atributo %s"
@@ -1090,10 +1124,10 @@
"cardinalidad %(card)s"
msgid "cancel select"
-msgstr "anular la selección"
+msgstr "Cancelar la selección"
msgid "cancel this insert"
-msgstr "anular esta inserción"
+msgstr "Cancelar esta inserción"
msgid "canonical"
msgstr "canónico"
@@ -1101,87 +1135,99 @@
msgid "cardinality"
msgstr "cardinalidad"
+msgid "category"
+msgstr ""
+
#, python-format
msgid "changed state of %(etype)s #%(eid)s (%(title)s)"
-msgstr "cambiar del estado de %(etype)s #%(eid)s (%(title)s)"
+msgstr "Cambiar del estado de %(etype)s #%(eid)s (%(title)s)"
msgid "changes applied"
-msgstr "cambios realizados"
+msgstr "Cambios realizados"
msgid "click on the box to cancel the deletion"
-msgstr "seleccione la zona de edición para anular la eliminación"
+msgstr "Seleccione la zona de edición para cancelar la eliminación"
+
+msgid "close all"
+msgstr ""
msgid "comment"
-msgstr "comentario"
+msgstr "Comentario"
msgid "comment:"
-msgstr "comentario :"
+msgstr "Comentario:"
msgid "comment_format"
-msgstr "formato"
+msgstr "Formato"
msgid "components"
-msgstr "componentes"
+msgstr "Componentes"
msgid "components_appliname"
-msgstr "título de la aplicación"
+msgstr "Título de la aplicación"
msgid "components_appliname_description"
-msgstr "muestra el título de la aplicación en el encabezado de la página"
+msgstr "Muestra el título de la aplicación en el encabezado de la página"
msgid "components_applmessages"
-msgstr "mensajes de la aplicación"
+msgstr "Mensajes de la aplicación"
msgid "components_applmessages_description"
-msgstr "muestra los mensajes de la aplicación"
+msgstr "Muestra los mensajes de la aplicación"
msgid "components_breadcrumbs"
-msgstr "hilo de Ariadna"
+msgstr "Ruta de Navegación"
msgid "components_breadcrumbs_description"
msgstr ""
-"muestra un camino que permite identificar el lugar donde se encuentra la "
+"Muestra un camino que permite identificar el lugar donde se encuentra la "
"página en el sitio"
msgid "components_etypenavigation"
-msgstr "filtro por tipo"
+msgstr "Filtro por tipo"
msgid "components_etypenavigation_description"
-msgstr "permite filtrar por tipo de entidad los resultados de búsqueda"
+msgstr "Permite filtrar por tipo de entidad los resultados de búsqueda"
msgid "components_help"
-msgstr "botón de ayuda"
+msgstr "Botón de ayuda"
msgid "components_help_description"
-msgstr "el botón de ayuda, en el encabezado de página"
+msgstr "El botón de ayuda, en el encabezado de página"
msgid "components_loggeduserlink"
-msgstr "liga usuario"
+msgstr "Liga usuario"
msgid "components_loggeduserlink_description"
msgstr ""
-"muestra un enlace hacia el formulario de conexión para los usuarios "
+"Muestra un enlace hacia el formulario de conexión para los usuarios "
"anónimos, o una caja que contiene las ligas propias a el usuarioconectado. "
msgid "components_logo"
-msgstr "logo"
+msgstr "Logo"
msgid "components_logo_description"
-msgstr "el logo de la aplicación, en el encabezado de página"
+msgstr "El logo de la aplicación, en el encabezado de página"
msgid "components_navigation"
-msgstr "navigación por página"
+msgstr "Navigación por página"
msgid "components_navigation_description"
msgstr ""
-"componente aue permite distribuir sobre varias páginas las búsquedas que "
-"arrojan mayores resultados a un número previamente elegido"
+"Componente que permite distribuir sobre varias páginas las búsquedas que "
+"arrojan mayores resultados que un número previamente elegido"
msgid "components_rqlinput"
-msgstr "barra rql"
+msgstr "Barra rql"
msgid "components_rqlinput_description"
-msgstr "la barre de demanda rql, en el encabezado de página"
+msgstr "La barra de demanda rql, en el encabezado de página"
+
+msgid "components_rss_feed_url"
+msgstr "RSS FEED URL"
+
+msgid "components_rss_feed_url_description"
+msgstr "El espacio para administrar RSS"
msgid "composite"
msgstr "composite"
@@ -1190,76 +1236,76 @@
msgstr "condición"
msgid "condition:"
-msgstr "condición :"
+msgstr "condición:"
msgid "condition_object"
msgstr "condición de"
msgid "confirm password"
-msgstr "confirmar contraseña"
+msgstr "Confirmar contraseña"
msgid "constrained_by"
-msgstr "condicionado por"
+msgstr "Restricción hecha por"
msgid "constrained_by_object"
-msgstr "condición de"
+msgstr "ha restringido"
msgid "constraint factory"
-msgstr "fabrica de condiciones"
+msgstr "FAbrica de restricciones"
msgid "constraints"
-msgstr "condiciones"
+msgstr "Restricciones"
msgid "constraints applying on this relation"
-msgstr "condiciones que se aplican a esta relación"
+msgstr "Restricciones que se aplican a esta relación"
msgid "contentnavigation"
-msgstr "composantes contextuales"
+msgstr "Componentes contextuales"
msgid "contentnavigation_breadcrumbs"
-msgstr "hilo de Ariadna"
+msgstr "Ruta de Navegación"
msgid "contentnavigation_breadcrumbs_description"
-msgstr "muestra un camino que permite localizar la página actual en el sitio"
+msgstr "Muestra un camino que permite localizar la página actual en el sitio"
msgid "contentnavigation_prevnext"
msgstr "Elemento anterior / siguiente"
msgid "contentnavigation_prevnext_description"
msgstr ""
-"muestra las ligas que permiten pasar de una entidad a otra en lasentidades "
+"Muestra las ligas que permiten pasar de una entidad a otra en lasentidades "
"que implementan la interface \"anterior/siguiente\"."
msgid "contentnavigation_seealso"
-msgstr "vea también"
+msgstr "Vea también"
msgid "contentnavigation_seealso_description"
msgstr ""
-"sección aue muestra las entidades ligadas por la relación \"vea también\" , "
+"sección que muestra las entidades ligadas por la relación \"vea también\" , "
"si la entidad soporta esta relación."
msgid "contentnavigation_wfhistory"
-msgstr "histórico del workflow."
+msgstr "Histórico del workflow."
msgid "contentnavigation_wfhistory_description"
msgstr ""
-"sección que ofrece el reporte histórico del workflow para las entidades que "
+"Sección que ofrece el reporte histórico del workflow para las entidades que "
"posean un workflow."
msgid "context"
-msgstr "contexto"
+msgstr "Contexto"
msgid "context where this box should be displayed"
-msgstr "contexto en el cual la caja debe aparecer en el sistema"
+msgstr "Contexto en el cual la caja debe aparecer en el sistema"
msgid "context where this component should be displayed"
-msgstr "contexto en el cual el componente debe aparecer en el sistema"
+msgstr "Contexto en el cual el componente debe aparecer en el sistema"
msgid "control subject entity's relations order"
-msgstr "controla el orden de relaciones de la entidad sujeto"
+msgstr "Controla el orden de relaciones de la entidad sujeto"
msgid "copy"
-msgstr "copiar"
+msgstr "Copiar"
msgid "copy edition"
msgstr "Edición de una copia"
@@ -1268,66 +1314,66 @@
"core relation giving to a group the permission to add an entity or relation "
"type"
msgstr ""
-"relación sistema que otorga a un grupo la autorización de agregar unaentidad "
-"o una relación"
+"Relación sistema que otorga a un grupo la autorización de agregar una "
+"entidad o una relación"
msgid ""
"core relation giving to a group the permission to delete an entity or "
"relation type"
msgstr ""
-"relación sistema que otorga a un grupo la autorización de eliminar una "
+"Relación sistema que otorga a un grupo la autorización de eliminar una "
"entidad o relación"
msgid ""
"core relation giving to a group the permission to read an entity or relation "
"type"
msgstr ""
-"relación sistema que otorga a un grupo la autorización de leer una entidad o "
+"Relación sistema que otorga a un grupo la autorización de leer una entidad o "
"una relación "
msgid "core relation giving to a group the permission to update an entity type"
msgstr ""
-"relación sistema que otorga a un grupo la autorización de actualizar una "
+"Relación sistema que otorga a un grupo la autorización de actualizar una "
"entidad"
msgid "core relation indicating a user's groups"
msgstr ""
-"relación sistema que indica los grupos a los cuales pertenece un usuario"
+"Relación sistema que indica los grupos a los cuales pertenece un usuario"
msgid ""
"core relation indicating owners of an entity. This relation implicitly put "
"the owner into the owners group for the entity"
msgstr ""
-"relación sistema que indica el(los) propietario(s) de una entidad. Esta "
+"Relación sistema que indica el(los) propietario(s) de una entidad. Esta "
"relación pone de manera implícita al propietario en el grupo de propietarios "
-"por una entidad"
+"de una entidad"
msgid "core relation indicating the original creator of an entity"
-msgstr "relación sistema que indica el creador de una entidad."
+msgstr "Relación sistema que indica el creador de una entidad."
msgid "core relation indicating the type of an entity"
-msgstr "relación sistema que indica el tipo de entidad"
+msgstr "Relación sistema que indica el tipo de entidad"
msgid ""
"core relation indicating the types (including specialized types) of an entity"
msgstr ""
-"relación sistema indicando los tipos (incluídos los tipos padres) de una "
+"Relación sistema indicando los tipos (incluídos los tipos padres) de una "
"entidad"
msgid "cost"
-msgstr "costo"
+msgstr "Costo"
msgid "could not connect to the SMTP server"
-msgstr "imposible de conectarse al servidor SMTP"
+msgstr "Imposible de conectarse al servidor SMTP"
msgid "create an index for quick search on this attribute"
-msgstr "crear un índice para accelerar las búsquedas sobre este atributo"
+msgstr "Crear un índice para accelerar las búsquedas sobre este atributo"
msgid "create an index page"
-msgstr "crear una página de inicio"
+msgstr "Crear una página de inicio"
msgid "created on"
-msgstr "creado el"
+msgstr "Creado el"
msgid "created_by"
msgstr "creado por"
@@ -1336,54 +1382,49 @@
msgstr "ha creado"
msgid "creating Bookmark (Bookmark bookmarked_by CWUser %(linkto)s)"
-msgstr ""
+msgstr "Creando Favorito"
+
+msgid "creating CWConstraint (CWAttribute %(linkto)s constrained_by CWConstraint)"
+msgstr "Creación condicionada por el atributo %(linkto)s"
+
+msgid "creating CWConstraint (CWRelation %(linkto)s constrained_by CWConstraint)"
+msgstr "Creación condicionada por la relación %(linkto)s"
msgid "creating CWAttribute (CWAttribute relation_type CWRType %(linkto)s)"
-msgstr "creación atributo %(linkto)s"
-
-msgid ""
-"creating CWConstraint (CWAttribute %(linkto)s constrained_by CWConstraint)"
-msgstr "creación condicionada por el atributo %(linkto)s"
-
-msgid ""
-"creating CWConstraint (CWRelation %(linkto)s constrained_by CWConstraint)"
-msgstr "creación condicionada por la relación %(linkto)s"
+msgstr "Creación del atributo %(linkto)s"
+
+msgid "creating CWRelation (CWRelation relation_type CWRType %(linkto)s)"
+msgstr "Creación de la relación %(linkto)s"
msgid "creating CWProperty (CWProperty for_user CWUser %(linkto)s)"
-msgstr "creación de una propiedad por el usuario %(linkto)s"
-
-msgid "creating CWRelation (CWRelation relation_type CWRType %(linkto)s)"
-msgstr "creación relación %(linkto)s"
+msgstr "Creación de una propiedad por el usuario %(linkto)s"
msgid "creating CWUser (CWUser in_group CWGroup %(linkto)s)"
-msgstr "creación de un usuario para agregar al grupo %(linkto)s"
+msgstr "Creación de un usuario para agregar al grupo %(linkto)s"
msgid "creating EmailAddress (CWUser %(linkto)s use_email EmailAddress)"
-msgstr "creación de una dirección electrónica para el usuario %(linkto)s"
-
-msgid ""
-"creating RQLExpression (CWEType %(linkto)s add_permission RQLExpression)"
+msgstr "Creación de una dirección electrónica para el usuario %(linkto)s"
+
+msgid "creating RQLExpression (CWEType %(linkto)s add_permission RQLExpression)"
msgstr ""
-"creación de una expresión RQL para la autorización de agregar %(linkto)s"
+"Creación de una expresión RQL para la autorización de agregar %(linkto)s"
msgid ""
"creating RQLExpression (CWEType %(linkto)s delete_permission RQLExpression)"
msgstr ""
-"creación de una expresión RQL para la autorización de eliminar %(linkto)s"
+"Creación de una expresión RQL para la autorización de eliminar %(linkto)s"
msgid ""
"creating RQLExpression (CWEType %(linkto)s read_permission RQLExpression)"
-msgstr "creación de una expresión RQL para la autorización de leer %(linkto)s"
+msgstr "Creación de una expresión RQL para la autorización de leer %(linkto)s"
msgid ""
"creating RQLExpression (CWEType %(linkto)s update_permission RQLExpression)"
+msgstr "Creación de una expresión RQL para autorizar actualizar %(linkto)s"
+
+msgid "creating RQLExpression (CWRType %(linkto)s add_permission RQLExpression)"
msgstr ""
-"creación de una expresión RQL para la autorización de actualizar %(linkto)s"
-
-msgid ""
-"creating RQLExpression (CWRType %(linkto)s add_permission RQLExpression)"
-msgstr ""
-"creación de una expresión RQL para la autorización de agregar relaciones %"
+"Creación de una expresión RQL para la autorización de agregar relaciones %"
"(linkto)s"
msgid ""
@@ -1395,90 +1436,90 @@
msgid ""
"creating RQLExpression (CWRType %(linkto)s read_permission RQLExpression)"
msgstr ""
-"creación de una expresión RQL para autorizar la lectura de relaciones %"
+"Creación de una expresión RQL para autorizar la lectura de relaciones %"
"(linkto)s"
msgid "creating RQLExpression (Transition %(linkto)s condition RQLExpression)"
-msgstr "creación de una expresión RQL para la transición %(linkto)s"
+msgstr "Creación de una expresión RQL para la transición %(linkto)s"
msgid "creating State (State allowed_transition Transition %(linkto)s)"
-msgstr "creación de un estado que pueda ir hacia la transición %(linkto)s"
+msgstr "Creación de un estado que pueda ir hacia la transición %(linkto)s"
msgid "creating State (State state_of CWEType %(linkto)s)"
-msgstr "creación de un estado por el tipo %(linkto)s"
+msgstr "Creación de un estado por el tipo %(linkto)s"
msgid "creating State (Transition %(linkto)s destination_state State)"
-msgstr "creación de un estado destinación de la transición %(linkto)s"
+msgstr "Creación de un estado destinación de la transición %(linkto)s"
msgid "creating Transition (State %(linkto)s allowed_transition Transition)"
-msgstr "creación de una transición autorizada desde el estado %(linkto)s"
+msgstr "Creación de una transición autorizada desde el estado %(linkto)s"
msgid "creating Transition (Transition destination_state State %(linkto)s)"
-msgstr "creación de un transición hacia el estado %(linkto)s"
+msgstr "Creación de un transición hacia el estado %(linkto)s"
msgid "creating Transition (Transition transition_of CWEType %(linkto)s)"
-msgstr "creación de una transición para el tipo %(linkto)s"
+msgstr "Creación de una transición para el tipo %(linkto)s"
msgid "creation"
-msgstr "creación"
+msgstr "Creación"
msgid "creation time of an entity"
-msgstr "fecha de creación de una entidad"
+msgstr "Fecha de creación de una entidad"
msgid "creation_date"
msgstr "fecha de creación"
msgid "cstrtype"
-msgstr "tipo de condición"
+msgstr "Tipo de condición"
msgid "cstrtype_object"
msgstr "utilizado por"
msgid "csv entities export"
-msgstr "exportar entidades en csv"
+msgstr "Exportar entidades en csv"
msgid "csv export"
-msgstr "exportar CSV"
+msgstr "Exportar CSV"
#, python-format
msgid "currently attached file: %s"
msgstr ""
msgid "data directory url"
-msgstr "url del repertorio de datos"
+msgstr "Url del repertorio de datos"
msgid "date"
-msgstr "fecha"
+msgstr "Fecha"
msgid "deactivate"
-msgstr "desactivar"
+msgstr "Desactivar"
msgid "deactivated"
-msgstr "desactivado"
+msgstr "Desactivado"
msgid "december"
-msgstr "diciembre"
+msgstr "Diciembre"
msgid "default"
-msgstr "valor por default"
+msgstr "Valor por defecto"
msgid "default text format for rich text fields."
-msgstr "formato de texto como opción por defecto para los campos texto"
+msgstr "Formato de texto como opción por defecto para los campos texto"
msgid "defaultval"
-msgstr "valor por defecto"
+msgstr "Valor por defecto"
msgid "define a CubicWeb user"
-msgstr "define un usuario CubicWeb"
+msgstr "Define un usuario CubicWeb"
msgid "define a CubicWeb users group"
-msgstr "define un grupo de usuarios CubicWeb"
+msgstr "Define un grupo de usuarios CubicWeb"
msgid ""
"define a final relation: link a final relation type from a non final entity "
"to a final entity type. used to build the application schema"
msgstr ""
-"define una relación no final: liga un tipo de relación no final desde una "
+"Define una relación no final: liga un tipo de relación no final desde una "
"entidad hacia un tipo de entidad no final. Utilizada para construir el "
"esquema de la aplicación"
@@ -1486,76 +1527,76 @@
"define a non final relation: link a non final relation type from a non final "
"entity to a non final entity type. used to build the application schema"
msgstr ""
-"define una relación 'atributo', utilizada para construir el esquema dela "
+"Define una relación 'atributo', utilizada para construir el esquema dela "
"aplicación"
msgid "define a relation type, used to build the application schema"
msgstr ""
-"define un tipo de relación, utilizada para construir el esquema de la "
+"Define un tipo de relación, utilizada para construir el esquema de la "
"aplicación"
msgid "define a rql expression used to define permissions"
msgstr "Expresión RQL utilizada para definir los derechos de acceso"
msgid "define a schema constraint"
-msgstr "define una condición de esquema"
+msgstr "Define una condición de esquema"
msgid "define a schema constraint type"
-msgstr "define un tipo de condición de esquema"
+msgstr "Define un tipo de condición de esquema"
msgid "define an entity type, used to build the application schema"
msgstr ""
-"define un tipo de entidad, utilizada para construir el esquema de la "
+"Define un tipo de entidad, utilizada para construir el esquema de la "
"aplicación"
msgid ""
"defines what's the property is applied for. You must select this first to be "
"able to set value"
msgstr ""
-"define a que se aplica la propiedad . Usted debe seleccionar esto antes de "
+"Define a que se aplica la propiedad . Usted debe seleccionar esto antes de "
"poder fijar un valor"
msgid "delete"
-msgstr "eliminar"
+msgstr "Eliminar"
msgid "delete this bookmark"
-msgstr "eliminar este atajo"
+msgstr "Eliminar este favorito"
msgid "delete this permission"
-msgstr "eliminar esta autorización"
+msgstr "Eliminar esta autorización"
msgid "delete this relation"
-msgstr "eliminar estar relación"
+msgstr "Eliminar esta relación"
msgid "delete_perm"
-msgstr "eliminar"
+msgstr "Eliminar"
msgid "delete_permission"
-msgstr "autorización de eliminar"
+msgstr "Autorización de eliminar"
msgid "delete_permission_object"
msgstr "posee la autorización de eliminar"
#, python-format
msgid "deleted %(etype)s #%(eid)s (%(title)s)"
-msgstr "eliminación de la entidad %(etype)s #%(eid)s (%(title)s)"
+msgstr "Eliminación de la entidad %(etype)s #%(eid)s (%(title)s)"
#, python-format
msgid ""
"deleted relation %(rtype)s from %(frometype)s #%(fromeid)s to %(toetype)s #%"
"(toeid)s"
msgstr ""
-"eliminación de la relación %(rtype)s de %(frometype)s #%(fromeid)s hacia %"
+"Eliminación de la relación %(rtype)s de %(frometype)s #%(fromeid)s hacia %"
"(toetype)s #%(toeid)s"
msgid "depends on the constraint type"
-msgstr "depende del tipo de condición"
+msgstr "Depende del tipo de condición"
msgid "description"
-msgstr "descripción"
+msgstr "Descripción"
msgid "description_format"
-msgstr "formato"
+msgstr "Formato"
msgid "destination state for this transition"
msgstr "Estado destino para esta transición"
@@ -1567,350 +1608,334 @@
msgstr "Estado destino"
msgid "destination_state_object"
-msgstr "destino de"
-
-msgid "detach attached file"
-msgstr "soltar el archivo existente"
+msgstr "Destino de"
#, python-format
msgid "detach attached file %s"
-msgstr ""
+msgstr "Quitar archivo adjunto %s"
msgid "detailed schema view"
-msgstr "vista detallada del esquema"
+msgstr "Vista detallada del esquema"
msgid "display order of the action"
-msgstr "orden de aparición de la acción"
+msgstr "Orden de aparición de la acción"
msgid "display order of the box"
-msgstr "orden de aparición de la caja"
+msgstr "Orden de aparición de la caja"
msgid "display order of the component"
-msgstr "orden de aparición del componente"
+msgstr "Orden de aparición del componente"
msgid "display the action or not"
-msgstr "mostrar la acción o no"
+msgstr "Mostrar la acción o no"
msgid "display the box or not"
-msgstr "mostrar la caja o no"
+msgstr "Mostrar la caja o no"
msgid "display the component or not"
-msgstr "mostrar el componente o no"
+msgstr "Mostrar el componente o no"
msgid ""
"distinct label to distinguate between other permission entity of the same "
"name"
msgstr ""
-"etiqueta que permite distinguir esta autorización de otras que posean el "
+"Etiqueta que permite distinguir esta autorización de otras que posean el "
"mismo nombre"
msgid "download"
-msgstr "descargar"
+msgstr "Descargar"
msgid "download icon"
msgstr "ícono de descarga"
msgid "download schema as owl"
-msgstr ""
+msgstr "Descargar esquema en OWL"
msgid "edit bookmarks"
-msgstr "editar los atajos"
+msgstr "Editar favoritos"
msgid "edit the index page"
-msgstr "editar la página de inicio"
+msgstr "Modificar la página de inicio"
msgid "editable-table"
-msgstr "tabla modificable"
+msgstr "Tabla modificable"
msgid "edition"
-msgstr "edición"
+msgstr "Edición"
msgid "eid"
msgstr "eid"
msgid "element copied"
-msgstr "elemeto copiado"
+msgstr "Elemento copiado"
msgid "element created"
-msgstr "elemento creado"
+msgstr "Elemento creado"
msgid "element edited"
-msgstr "elemento editado"
+msgstr "Elemento editado"
msgid "email address to use for notification"
-msgstr "dirección electrónica a utilizarse para notificar"
+msgstr "Dirección electrónica a utilizarse para notificar"
msgid "emails successfully sent"
-msgstr "mensajes enviados con éxito"
+msgstr "Mensajes enviados con éxito"
msgid "embed"
-msgstr "incrustrado"
+msgstr "Incrustrado"
msgid "embedding this url is forbidden"
-msgstr "la inclusión de este url esta prohibida"
+msgstr "La inclusión de este url esta prohibida"
msgid "entities deleted"
-msgstr "entidades eliminadas"
-
-msgid "entity copied"
-msgstr ""
-
-msgid "entity created"
-msgstr ""
+msgstr "Entidades eliminadas"
msgid "entity deleted"
-msgstr "entidad eliminada"
-
-msgid "entity edited"
-msgstr ""
+msgstr "Entidad eliminada"
msgid "entity type"
-msgstr "tipo de entidad"
+msgstr "Tipo de entidad"
msgid ""
"entity type that may be used to construct some advanced security "
"configuration"
msgstr ""
-"tipo de entidqd utilizada para definir una configuración de seguridad "
+"Tipo de entidad utilizada para definir una configuración de seguridad "
"avanzada"
msgid "entity types which may use this state"
-msgstr "tipo de entidades que pueden utilizar este estado"
+msgstr "Tipo de entidades que pueden utilizar este estado"
msgid "entity types which may use this transition"
-msgstr "entidades que pueden utilizar esta transición"
+msgstr "Entidades que pueden utilizar esta transición"
msgid "error while embedding page"
-msgstr "error durante la inclusión de la página"
+msgstr "Error durante la inclusión de la página"
#, python-format
msgid "error while handling __method: %s"
-msgstr "error ocurrido durante el tratamiento del formulario (%s)"
+msgstr "Error ocurrido durante el tratamiento del formulario (%s)"
msgid "error while publishing ReST text"
msgstr ""
-"se ha producido un error durante la interpretación del texto en formatoReST"
+"Se ha producido un error durante la interpretación del texto en formatoReST"
#, python-format
msgid "error while querying source %s, some data may be missing"
msgstr ""
-"un error ha ocurrido al interrogar %s, es posible que los \n"
+"Un error ha ocurrido al interrogar %s, es posible que los \n"
"datos visibles se encuentren incompletos"
msgid "eta_date"
msgstr "fecha de fin"
msgid "expected:"
-msgstr "previsto :"
+msgstr "Previsto :"
msgid "expression"
-msgstr "expresión"
+msgstr "Expresión"
msgid "exprtype"
-msgstr "tipo de la expresión"
+msgstr "Tipo de la expresión"
msgid "external page"
-msgstr "página externa"
+msgstr "Página externa"
msgid "facetbox"
-msgstr "caja de facetas"
+msgstr "Caja de facetas"
msgid "facets_created_by-facet"
msgstr "faceta \"creada por\""
msgid "facets_created_by-facet_description"
-msgstr ""
+msgstr "faceta creado por"
msgid "facets_etype-facet"
msgstr "faceta \"es de tipo\""
msgid "facets_etype-facet_description"
-msgstr ""
+msgstr "faceta es de tipo"
msgid "facets_has_text-facet"
msgstr "faceta \"contiene el texto\""
msgid "facets_has_text-facet_description"
-msgstr ""
+msgstr "faceta contiene el texto"
msgid "facets_in_group-facet"
msgstr "faceta \"forma parte del grupo\""
msgid "facets_in_group-facet_description"
-msgstr ""
+msgstr "faceta en grupo"
msgid "facets_in_state-facet"
msgstr "faceta \"en el estado\""
msgid "facets_in_state-facet_description"
-msgstr ""
+msgstr "faceta en el estado"
msgid "february"
-msgstr "febrero"
+msgstr "Febrero"
msgid "file tree view"
-msgstr ""
+msgstr "File Vista Arborescencia"
msgid "final"
-msgstr "final"
+msgstr "Final"
msgid "firstname"
-msgstr "nombre"
+msgstr "Nombre"
msgid "foaf"
-msgstr ""
+msgstr "Amigo de un Amigo, FOAF"
msgid "follow"
-msgstr "seguir la liga"
+msgstr "Seguir la liga"
msgid "for_user"
-msgstr "para el usuario"
+msgstr "Para el usuario"
msgid "for_user_object"
-msgstr "utiliza las propiedades"
+msgstr "Utiliza las propiedades"
msgid "friday"
-msgstr "viernes"
+msgstr "Viernes"
msgid "from"
-msgstr "de"
-
-#, python-format
-msgid "from %(date)s"
-msgstr ""
+msgstr "De"
msgid "from_entity"
-msgstr "de la entidad"
+msgstr "De la entidad"
msgid "from_entity_object"
-msgstr "relación sujeto"
+msgstr "Relación sujeto"
msgid "from_state"
-msgstr "de el estado"
+msgstr "De el estado"
msgid "from_state_object"
-msgstr "transiciones desde este estado"
+msgstr "Transiciones desde este estado"
msgid "full text or RQL query"
-msgstr "texto de búsqueda o demanda RQL"
+msgstr "Texto de búsqueda o demanda RQL"
msgid "fulltext_container"
-msgstr "contenedor de texto indexado"
+msgstr "Contenedor de texto indexado"
msgid "fulltextindexed"
-msgstr "indexación de texto"
+msgstr "Indexación de texto"
msgid "generic plot"
-msgstr "trazado de curbas estándares"
+msgstr "Trazado de curbas estándares"
msgid "go back to the index page"
-msgstr "regresar a la página de inicio"
+msgstr "Regresar a la página de inicio"
msgid "granted to groups"
-msgstr "otorgado a los grupos"
+msgstr "Otorgado a los grupos"
msgid "graphical representation of the application'schema"
-msgstr "representación gráfica del esquema de la aplicación"
+msgstr "Representación gráfica del esquema de la aplicación"
#, python-format
msgid "graphical schema for %s"
-msgstr "gráfica del esquema por %s"
+msgstr "Gráfica del esquema por %s"
#, python-format
msgid "graphical workflow for %s"
-msgstr "gráfica del workflow por %s"
+msgstr "Gráfica del workflow por %s"
msgid "group in which a user should be to be allowed to pass this transition"
-msgstr "grupo en el cual el usuario debe estar para poder pasar la transición"
+msgstr "Grupo en el cual el usuario debe estar para poder pasar la transición"
msgid "groups"
-msgstr "grupos"
+msgstr "Grupos"
msgid "groups allowed to add entities/relations of this type"
-msgstr "grupos autorizados a agregar entidades/relaciones de este tipo"
+msgstr "Grupos autorizados a agregar entidades/relaciones de este tipo"
msgid "groups allowed to delete entities/relations of this type"
-msgstr "grupos autorizados a eliminar entidades/relaciones de este tipo"
+msgstr "Grupos autorizados a eliminar entidades/relaciones de este tipo"
msgid "groups allowed to read entities/relations of this type"
-msgstr "grupos autorizados a leer entidades/relaciones de este tipo"
+msgstr "Grupos autorizados a leer entidades/relaciones de este tipo"
msgid "groups allowed to update entities of this type"
-msgstr "grupos autorizados a actualizar entidades de este tipo"
+msgstr "Grupos autorizados a actualizar entidades de este tipo"
msgid "groups grant permissions to the user"
-msgstr "los grupos otorgan las autorizaciones al usuario"
+msgstr "Los grupos otorgan las autorizaciones al usuario"
msgid "groups to which the permission is granted"
-msgstr "grupos quienes tienen otorgada esta autorización"
+msgstr "Grupos quienes tienen otorgada esta autorización"
msgid "groups:"
-msgstr "grupos :"
+msgstr "Grupos :"
msgid "guests"
-msgstr "invitados"
+msgstr "Invitados"
msgid "hCalendar"
msgstr "hCalendar"
msgid "has_text"
-msgstr "contiene el texto"
+msgstr "Contiene el texto"
msgid "help"
-msgstr "ayuda"
+msgstr "Ayuda"
msgid "hide filter form"
-msgstr "esconder el filtro"
+msgstr "Esconder el filtro"
msgid "hide meta-data"
-msgstr "esconder los meta-datos"
+msgstr "Esconder los meta-datos"
msgid "home"
-msgstr "inicio"
+msgstr "Inicio"
msgid ""
"how to format date and time in the ui (\"man strftime\" for format "
"description)"
msgstr ""
-"como formatear la fecha en la interface (\"man strftime\" por la descripción "
+"Como formatear la fecha en la interface (\"man strftime\" por la descripción "
"del formato)"
msgid "how to format date in the ui (\"man strftime\" for format description)"
msgstr ""
-"como formatear la fecha en la interface (\"man strftime\" por la descripción "
+"Como formatear la fecha en la interface (\"man strftime\" por la descripción "
"del formato)"
msgid "how to format float numbers in the ui"
-msgstr "como formatear los números flotantes en la interface"
+msgstr "Como formatear los números flotantes en la interface"
msgid "how to format time in the ui (\"man strftime\" for format description)"
msgstr ""
-"como formatear la hora en la interface (\"man strftime\" por la descripción "
+"Como formatear la hora en la interface (\"man strftime\" por la descripción "
"del formato)"
msgid "html class of the component"
-msgstr "clase HTML de este componente"
+msgstr "Clase HTML de este componente"
msgid "htmlclass"
-msgstr "clase html"
+msgstr "Clase html"
msgid "i18n_login_popup"
-msgstr "identificarse"
+msgstr "Identificarse"
msgid "i18nprevnext_next"
-msgstr "siguiente"
+msgstr "Siguiente"
msgid "i18nprevnext_previous"
-msgstr "anterior"
+msgstr "Anterior"
msgid "i18nprevnext_up"
-msgstr "padre"
+msgstr "Padre"
msgid "iCalendar"
msgstr "iCalendar"
msgid "id of main template used to render pages"
-msgstr "id del template principal"
+msgstr "ID del template principal"
msgid "identical_to"
msgstr "idéntico a"
@@ -1925,23 +1950,23 @@
"if full text content of subject/object entity should be added to other side "
"entity (the container)."
msgstr ""
-"si el texto indexado de la entidad sujeto/objeto debe ser agregado a la "
+"Si el texto indexado de la entidad sujeto/objeto debe ser agregado a la "
"entidad a el otro extremo de la relación (el contenedor)."
msgid "image"
-msgstr "imagen"
+msgstr "Imagen"
msgid "in memory entity schema"
-msgstr "esquema de la entidad en memoria"
+msgstr "Esquema de la entidad en memoria"
msgid "in memory relation schema"
-msgstr "esquema de la relación en memoria"
+msgstr "Esquema de la relación en memoria"
msgid "in_group"
-msgstr "en el grupo"
+msgstr "En el grupo"
msgid "in_group_object"
-msgstr "miembros"
+msgstr "Miembros"
msgid "in_state"
msgstr "estado"
@@ -1950,64 +1975,64 @@
msgstr "estado de"
msgid "incontext"
-msgstr "en el contexto"
+msgstr "En el contexto"
#, python-format
msgid "incorrect value (%(value)s) for type \"%(type)s\""
msgstr "valor %(value)s incorrecto para el tipo \"%(type)s\""
msgid "index"
-msgstr "índice"
+msgstr "Indice"
msgid "index this attribute's value in the plain text index"
-msgstr "indexar el valor de este atributo en el índice de texto simple"
+msgstr "Indexar el valor de este atributo en el índice de texto simple"
msgid "indexed"
-msgstr "indexado"
+msgstr "Indexado"
msgid "indicate the current state of an entity"
-msgstr "indica el estado actual de una entidad"
+msgstr "Indica el estado actual de una entidad"
msgid ""
"indicate which state should be used by default when an entity using states "
"is created"
msgstr ""
-"indica cual estado deberá ser utilizado por defecto al crear una entidad"
+"Indica cual estado deberá ser utilizado por defecto al crear una entidad"
#, python-format
msgid "initial estimation %s"
-msgstr "estimación inicial %s"
+msgstr "Estimación inicial %s"
msgid "initial state for entities of this type"
-msgstr "estado inicial para las entidades de este tipo"
+msgstr "Estado inicial para las entidades de este tipo"
msgid "initial_state"
msgstr "estado inicial"
msgid "initial_state_object"
-msgstr "estado inicial de"
+msgstr "es el estado inicial de"
msgid "inlined"
-msgstr "puesto en línea"
+msgstr "Puesto en línea"
msgid "internationalizable"
-msgstr "internacionalizable"
+msgstr "Internacionalizable"
#, python-format
msgid "invalid action %r"
-msgstr "acción %r invalida"
+msgstr "Acción %r invalida"
msgid "invalid date"
-msgstr "esta fecha no es válida"
+msgstr "Esta fecha no es válida"
msgid "is"
-msgstr "de tipo"
+msgstr "es"
msgid "is it an application entity type or not ?"
-msgstr "es una entidad aplicativa o no ?"
+msgstr "Es un Tipo de entidad en la aplicación o no ?"
msgid "is it an application relation type or not ?"
-msgstr "es una relación aplicativa o no ?"
+msgstr "Es una relación aplicativa o no ?"
msgid ""
"is the subject/object entity of the relation composed of the other ? This "
@@ -2017,53 +2042,53 @@
"ser así, el destruir el composite destruirá de igual manera sus componentes "
msgid "is this attribute's value translatable"
-msgstr "es el valor de este atributo traducible ?"
+msgstr "Es el valor de este atributo traducible ?"
msgid "is this relation equivalent in both direction ?"
-msgstr "es esta relación equivalente en los ambos sentidos ?"
+msgstr "Es esta relación equivalente en los ambos sentidos ?"
msgid ""
"is this relation physically inlined? you should know what you're doing if "
"you are changing this!"
msgstr ""
-"es esta relación puesta en línea en la base de datos ? Usted debe saber lo "
+"Es esta relación puesta en línea en la base de datos ? Usted debe saber lo "
"que hace si cambia esto !"
msgid "is_instance_of"
msgstr "es una instancia de"
msgid "is_instance_of_object"
-msgstr "tipo de"
+msgstr "tiene como instancias"
msgid "is_object"
msgstr "tiene por instancia"
msgid "january"
-msgstr "enero"
+msgstr "Enero"
msgid "july"
-msgstr "julio"
+msgstr "Julio"
msgid "june"
-msgstr "junio"
+msgstr "Junio"
msgid "label"
-msgstr "etiqueta"
+msgstr "Etiqueta"
msgid "language of the user interface"
-msgstr "idioma para la interface del usuario"
+msgstr "Idioma para la interface del usuario"
msgid "last connection date"
-msgstr "última fecha de conexión"
+msgstr "Ultima fecha de conexión"
msgid "last_login_time"
-msgstr "última fecha de conexión"
+msgstr "Ultima fecha de conexión"
msgid "latest modification time of an entity"
-msgstr "fecha de la última modificación de una entidad "
+msgstr "Fecha de la última modificación de una entidad "
msgid "latest update on"
-msgstr "última actualización"
+msgstr "actualizado el"
msgid "left"
msgstr "izquierda"
@@ -2072,7 +2097,7 @@
"link a property to the user which want this property customization. Unless "
"you're a site manager, this relation will be handled automatically."
msgstr ""
-"liga una propiedad a el usuario que desea esta personalización. A menos que "
+"Liga una propiedad a el usuario que desea esta personalización. Salvo que "
"usted sea un administrador del sistema, esta relación es gestionada "
"automáticamente."
@@ -2083,212 +2108,233 @@
msgstr "liga una definición de relación a su tipo de relación"
msgid "link a relation definition to its subject entity type"
-msgstr "lie une dÈfinition de relation ‡ son type d'entitÈ sujet"
+msgstr "liga una definición de relación a su tipo de entidad"
msgid "link a state to one or more entity type"
-msgstr "lier un Ètat ‡ une ou plusieurs entitÈs"
+msgstr "liga un estado a una o mas entidades"
msgid "link a transition information to its object"
-msgstr "liÈ une enregistrement de transition vers l'objet associÈ"
+msgstr "liga una transcion de informacion a los objetos asociados"
msgid "link a transition to one or more entity type"
-msgstr "lie une transition ‡ un ou plusieurs types d'entitÈs"
+msgstr "liga una transición a una o mas tipos de entidad"
+
+msgid ""
+"link a transition to one or more rql expression allowing to go through this "
+"transition"
+msgstr ""
+"liga una transición a una o mas expresiones RQL permitiendo que funcione"
msgid "link to each item in"
-msgstr "lier vers chaque ÈlÈment dans"
+msgstr "ligar hacia cada elemento en"
msgid "list"
-msgstr "liste"
+msgstr "Lista"
msgid "loading"
-msgstr ""
+msgstr "Cargando"
msgid "log in"
-msgstr "s'identifier"
+msgstr "Identificarse"
msgid "login"
-msgstr "identifiant"
-
-msgid "login or email"
-msgstr ""
+msgstr "Clave de acesso"
msgid "login_action"
-msgstr "identifiez vous"
+msgstr "Ingresa tus datos"
msgid "logout"
-msgstr "se dÈconnecter"
+msgstr "Desconectarse"
#, python-format
msgid "loop in %(rel)s relation (%(eid)s)"
-msgstr "boucle dÈtectÈe en parcourant la relation %(rel)s de l'entitÈ #%(eid)s"
+msgstr "loop detectado en %(rel)s de la entidad #%(eid)s"
msgid "main informations"
-msgstr "Informations gÈnÈrales"
+msgstr "Informaciones Generales"
msgid "mainvars"
-msgstr "variables principales"
+msgstr "Principales variables"
msgid "manage"
-msgstr "gestion du site"
+msgstr "Administracion del Sitio"
msgid "manage bookmarks"
-msgstr "gÈrer les signets"
+msgstr "Administra tus favoritos"
msgid "manage permissions"
-msgstr ""
+msgstr "Administración de Autorizaciones"
msgid "manage security"
-msgstr "gestion de la sÈcuritÈ"
+msgstr "Administración de la Seguridad"
msgid "managers"
-msgstr "administrateurs"
+msgstr "editores"
msgid "march"
-msgstr "mars"
+msgstr "Marzo"
msgid "maximum number of characters in short description"
-msgstr "nombre maximum de caractËres dans les descriptions courtes"
+msgstr "Numero maximo de caracteres en las descripciones cortas"
msgid "maximum number of entities to display in related combo box"
-msgstr "nombre maximum d'entitÈs ‡ afficher dans les listes dÈroulantes"
+msgstr "Numero maximo de entidades a mostrar en las listas dinamicas"
msgid "maximum number of objects displayed by page of results"
-msgstr "nombre maximum d'entitÈs affichÈes par pages"
+msgstr "Numero maximo de objetos mostrados por pagina de resultados"
msgid "maximum number of related entities to display in the primary view"
-msgstr "nombre maximum d'entitÈs liÈes ‡ afficher dans la vue primaire"
+msgstr "Numero maximo de entidades ligadas a mostrar en la vista primaria"
msgid "may"
-msgstr "mai"
+msgstr "Mayo"
msgid "meta"
-msgstr "mÈta"
+msgstr "Meta"
msgid "milestone"
-msgstr "jalon"
+msgstr "Milestone"
#, python-format
msgid "missing parameters for entity %s"
-msgstr "paramËtres manquants pour l'entitÈ %s"
+msgstr "Parametros faltantes a la entidad %s"
msgid "modification_date"
-msgstr "date de modification"
+msgstr "Fecha de modificacion"
msgid "modify"
-msgstr "modifier"
+msgstr "Modificar"
msgid "monday"
-msgstr "lundi"
+msgstr "Lundi"
msgid "more actions"
-msgstr "plus d'actions"
+msgstr "mas acciones"
msgid "multiple edit"
-msgstr "Èdition multiple"
+msgstr "Edicion multiple"
msgid "my custom search"
-msgstr "ma recherche personnalisÈe"
+msgstr "Mi busqueda personalizada"
msgid "name"
-msgstr "nom"
+msgstr "Nombre"
msgid "name of the cache"
-msgstr "nom du cache applicatif"
+msgstr "Nombre del Cache"
msgid ""
"name of the main variables which should be used in the selection if "
"necessary (comma separated)"
msgstr ""
-"nom des variables principaes qui devrait Ítre utilisÈes dans la sÈlection si "
-"nÈcessaire (les sÈparer par des virgules)"
+"Nombre de las variables principales que deberian se utilizadas en la "
+"selecciónde ser necesario (separarlas con comas)"
msgid "name or identifier of the permission"
-msgstr "nom (identifiant) de la permission"
+msgstr "Nombre o indentificador de la autorización"
msgid "navbottom"
-msgstr "bas de page"
+msgstr "Pie de pagina"
msgid "navcontentbottom"
-msgstr "bas de page du contenu principal"
+msgstr "Pie de pagina del contenido principal"
msgid "navcontenttop"
-msgstr "haut de page"
+msgstr "Encabezado"
msgid "navigation"
-msgstr "navigation"
+msgstr "Navegación"
+
+msgid "navigation.combobox-limit"
+msgstr ""
+
+msgid "navigation.page-size"
+msgstr ""
+
+msgid "navigation.related-limit"
+msgstr ""
+
+msgid "navigation.short-line-size"
+msgstr ""
msgid "navtop"
-msgstr "haut de page du contenu principal"
+msgstr "Encabezado del contenido principal"
msgid "new"
-msgstr "nouveau"
+msgstr "Nuevo"
msgid "next_results"
-msgstr "rÈsultats suivants"
+msgstr "Siguientes resultados"
msgid "no"
-msgstr "non"
+msgstr "no"
msgid "no associated epermissions"
-msgstr "aucune permission spÈcifique n'est dÈfinie"
+msgstr "permisos no asociados"
msgid "no possible transition"
-msgstr "aucune transition possible"
+msgstr "transición no posible"
msgid "no related project"
-msgstr "pas de projet rattachÈ"
+msgstr "no hay proyecto relacionado"
msgid "no selected entities"
-msgstr "pas d'entitÈ sÈlectionnÈe"
+msgstr "no hay entidades seleccionadas"
#, python-format
msgid "no such entity type %s"
-msgstr "le type d'entitÈ '%s' n'existe pas"
+msgstr "el tipo de entidad '%s' no existe"
msgid "no version information"
-msgstr "pas d'information de version"
+msgstr "no información de version"
msgid "not authorized"
-msgstr "non autorisÈ"
+msgstr "no autorizado"
msgid "not selected"
-msgstr ""
+msgstr "no seleccionado"
msgid "not specified"
-msgstr "non spÈcifiÈ"
+msgstr "no especificado"
msgid "not the initial state for this entity"
-msgstr "n'est pas l'Ètat initial pour cette entitÈ"
+msgstr "no el estado inicial para esta entidad"
msgid "nothing to edit"
-msgstr "rien ‡ Èditer"
+msgstr "nada que editar"
msgid "november"
-msgstr "novembre"
+msgstr "noviembre"
msgid "object"
-msgstr "objet"
+msgstr "objeto"
+
+msgid "object_plural:"
+msgstr ""
msgid "october"
-msgstr "octobre"
+msgstr "octubre"
msgid "one month"
-msgstr "un mois"
+msgstr "un mes"
msgid "one week"
-msgstr "une semaine"
+msgstr "una semana"
msgid "oneline"
-msgstr "une ligne"
+msgstr "una linea"
msgid "only select queries are authorized"
-msgstr "seules les requÍtes de sÈlections sont autorisÈes"
+msgstr "solo estan permitidas consultas de lectura"
+
+msgid "open all"
+msgstr ""
msgid "order"
-msgstr "ordre"
+msgstr "orden"
msgid "ordernum"
-msgstr "ordre"
+msgstr "orden"
msgid "owl"
msgstr ""
@@ -2297,172 +2343,179 @@
msgstr ""
msgid "owned_by"
-msgstr "appartient ‡"
+msgstr "pertenece a"
msgid "owned_by_object"
-msgstr "possËde"
+msgstr "pertenece al objeto"
msgid "owners"
-msgstr "propriÈtaires"
+msgstr "proprietarios"
msgid "ownership"
-msgstr "propriÈtÈ"
+msgstr "pertenencia"
msgid "ownerships have been changed"
-msgstr "les droits de propriÈtÈ ont ÈtÈ modifiÈs"
+msgstr "la pertenencia ha sido modificada"
msgid "pageid-not-found"
-msgstr ""
-"des donnÈes nÈcessaires semblent expirÈes, veuillez recharger la page et "
-"recommencer."
+msgstr "pagina no encontrada."
msgid "password"
-msgstr "mot de passe"
+msgstr "Clave de acceso"
msgid "password and confirmation don't match"
-msgstr "le mot de passe et la confirmation sont diffÈrents"
+msgstr "La clave de acceso y la confirmación no concuerdan"
msgid "path"
-msgstr "chemin"
+msgstr "Ruta"
msgid "permission"
-msgstr "permission"
+msgstr "Permiso"
+
+msgid "permissions for entities"
+msgstr ""
+
+msgid "permissions for relations"
+msgstr ""
msgid "permissions for this entity"
-msgstr "permissions pour cette entitÈ"
+msgstr "Permisos para esta entidad"
msgid "personnal informations"
-msgstr "informations personnelles"
+msgstr "Información personal"
msgid "pick existing bookmarks"
-msgstr "rÈcupÈrer des signets existants"
+msgstr "Seleccione los favoritos existentes"
msgid "pkey"
-msgstr "clÈ"
+msgstr ""
msgid "please correct errors below"
-msgstr "veuillez corriger les erreurs ci-dessous"
+msgstr "Favor de corregir errores"
msgid "please correct the following errors:"
-msgstr "veuillez corriger les erreurs suivantes :"
+msgstr "Favor de corregir los siguientes errores :"
msgid "possible views"
-msgstr "vues possibles"
+msgstr "Vistas posibles"
msgid "preferences"
-msgstr "prÈfÈrences"
+msgstr "Preferencias"
msgid "previous_results"
-msgstr "rÈsultats prÈcÈdents"
+msgstr "Resultados anteriores"
msgid "primary"
-msgstr "primaire"
+msgstr "Primaria"
msgid "primary_email"
-msgstr "adresse email principale"
+msgstr "Dirección de email principal"
msgid "primary_email_object"
-msgstr "adresse email principale (object)"
+msgstr "Dirección de email principal (objeto)"
msgid "progress"
-msgstr "avancement"
+msgstr "Avance"
msgid "progress bar"
-msgstr "barre d'avancement"
+msgstr "Barra de progreso de avance"
msgid "project"
-msgstr "projet"
+msgstr "Proyecto"
msgid "read"
-msgstr "lecture"
+msgstr "Lectura"
msgid "read_perm"
-msgstr "lecture"
+msgstr "Lectura"
msgid "read_permission"
-msgstr "permission de lire"
+msgstr "Permiso de lectura"
msgid "read_permission_object"
-msgstr "a la permission de lire"
+msgstr "Objeto_permiso_lectura"
#, python-format
msgid "relation %(relname)s of %(ent)s"
-msgstr "relation %(relname)s de %(ent)s"
+msgstr "relación %(relname)s de %(ent)s"
msgid "relation_type"
-msgstr "type de relation"
+msgstr "tipo de relación"
msgid "relation_type_object"
-msgstr "dÈfinition"
+msgstr "Definición"
+
+msgid "relations"
+msgstr ""
msgid "relations deleted"
-msgstr "relations supprimÈes"
+msgstr "Relaciones eliminadas"
msgid "relative url of the bookmarked page"
-msgstr "url relative de la page"
+msgstr "Url relativa de la pagina"
msgid "remove this Bookmark"
-msgstr "supprimer ce signet"
-
-msgid "remove this CWAttribute"
-msgstr "supprimer cet attribut"
+msgstr "Eliminar este Favorito"
msgid "remove this CWCache"
-msgstr "supprimer ce cache applicatif"
+msgstr "Eliminar esta cache de aplicación"
msgid "remove this CWConstraint"
-msgstr "supprimer cette contrainte"
+msgstr "Eliminar esta restricción"
msgid "remove this CWConstraintType"
-msgstr "supprimer ce type de contrainte"
+msgstr "Eliminar este tipo de restricción"
msgid "remove this CWEType"
-msgstr "supprimer ce type d'entitÈ"
+msgstr "Eliminar este tipo de entidad"
+
+msgid "remove this CWAttribute"
+msgstr "Eliminar este atributo"
msgid "remove this CWGroup"
-msgstr "supprimer ce groupe"
+msgstr "Eliminar este grupo"
+
+msgid "remove this CWRelation"
+msgstr "Eliminar esta relación"
msgid "remove this CWPermission"
-msgstr "supprimer cette permission"
+msgstr "Eliminar este permiso"
msgid "remove this CWProperty"
-msgstr "supprimer cette propriÈtÈ"
+msgstr "Eliminar esta propiedad"
msgid "remove this CWRType"
-msgstr "supprimer cette dÈfinition de relation"
-
-msgid "remove this CWRelation"
-msgstr "supprimer cette relation"
+msgstr "Eliminar esta definición de relación"
msgid "remove this CWUser"
-msgstr "supprimer cet utilisateur"
+msgstr "Eliminar este usuario"
msgid "remove this EmailAddress"
-msgstr "supprimer cette adresse email"
+msgstr "Eliminar este correo electronico"
msgid "remove this RQLExpression"
-msgstr "supprimer cette expression rql"
+msgstr "Eliminar esta expresión RQL"
msgid "remove this State"
-msgstr "supprimer cet Ètat"
+msgstr "Eliminar este estado"
msgid "remove this TrInfo"
-msgstr "retirer cette information de transition"
+msgstr "Eliminar información de esta transición"
msgid "remove this Transition"
-msgstr "supprimer cette transition"
+msgstr "Eliminar esta transición"
msgid "require_group"
-msgstr "nÈcessite le groupe"
+msgstr "Requiere_grupo"
msgid "require_group_object"
-msgstr "‡ les droits"
+msgstr "Objeto_grupo_requerido"
msgid "required attribute"
-msgstr "attribut requis"
+msgstr "Atributo requerido"
msgid "required field"
-msgstr "champ requis"
+msgstr "Campo requerido"
msgid ""
"restriction part of a rql query. For entity rql expression, X and U are "
@@ -2470,464 +2523,487 @@
"relation rql expression, S, O and U are predefined respectivly to the "
"current relation'subject, object and to the request user. "
msgstr ""
-"partie restriction de la requÍte rql. Pour une expression s'appliquant ‡ une "
-"entitÈ, X et U sont respectivement prÈfÈfinis ‡ l'entitÈ et ‡ l'utilisateur "
-"courant. Pour une expression s'appliquant ‡ une relation, S, O et U sont "
-"respectivement prÈfÈfinis au sujet/objet de la relation et ‡ l'utilisateur "
-"courant."
+"restriction part of a rql query. For entity rql expression, X and U are "
+"predefined respectivly to the current object and to the request user. For "
+"relation rql expression, S, O and U are predefined respectivly to the "
+"current relation'subject, object and to the request user. "
msgid "revert changes"
-msgstr "annuler les changements"
+msgstr "Revertir cambios"
msgid "right"
-msgstr "droite"
+msgstr "Derecha"
msgid "rql expression allowing to add entities/relations of this type"
-msgstr ""
-"expression RQL donnant le droit d'ajouter des entitÈs/relations de ce type"
+msgstr "expresion RQL permitiendo agregar entidades/relaciones de este tipo"
msgid "rql expression allowing to delete entities/relations of this type"
-msgstr ""
-"expression RQL donnant le droit de supprimer des entitÈs/relations de ce type"
+msgstr "expresion RQL permitiendo eliminar entidades/relaciones de este tipo"
msgid "rql expression allowing to read entities/relations of this type"
-msgstr ""
-"expression RQL donnant le droit de lire des entitÈs/relations de ce type"
+msgstr "expresion RQL permitiendo leer entidades/relaciones de este tipo"
msgid "rql expression allowing to update entities of this type"
-msgstr ""
-"expression RQL donnant le droit de modifier des entitÈs/relations de ce type"
+msgstr "expresion RQL permitiendo actualizar entidades de este tipo"
msgid "rql expressions"
-msgstr "conditions rql"
+msgstr "expresiones rql"
msgid "rss"
msgstr "RSS"
msgid "sample format"
-msgstr "exemple"
+msgstr "ejemplo"
msgid "saturday"
-msgstr "samedi"
+msgstr "sabado"
msgid "schema entities"
-msgstr "entitÈs dÈfinissant le schÈma"
+msgstr "entidades del esquema"
msgid "schema's permissions definitions"
-msgstr "permissions dÈfinies dans le schÈma"
+msgstr "definiciones de permisos del esquema"
msgid "search"
-msgstr "rechercher"
+msgstr "buscar"
msgid "search for association"
-msgstr "rechercher pour associer"
+msgstr "buscar por asociación"
msgid "searching for"
-msgstr "Recherche de"
+msgstr "buscando "
msgid "secondary"
-msgstr "secondaire"
+msgstr "secundario"
msgid "security"
-msgstr "sÈcuritÈ"
+msgstr "seguridad"
msgid "see them all"
-msgstr "les voir toutes"
+msgstr "Ver todos"
msgid "select"
-msgstr "sÈlectionner"
+msgstr "Seleccionar"
msgid "select a"
-msgstr "sÈlectionner un"
-
-msgid "select a key first"
-msgstr ""
+msgstr "seleccione un"
msgid "select a relation"
-msgstr "sÈlectionner une relation"
+msgstr "seleccione una relación"
msgid "select this entity"
-msgstr "sÈlectionner cette entitÈ"
+msgstr "seleccionar esta entidad"
msgid "selected"
-msgstr ""
+msgstr "seleccionado"
msgid "semantic description of this attribute"
-msgstr "description sÈmantique de cet attribut"
+msgstr "descripción semantica de este atributo"
msgid "semantic description of this entity type"
-msgstr "description sÈmantique de ce type d'entitÈ"
+msgstr "descripción semantica de este tipo de entidad"
msgid "semantic description of this relation"
-msgstr "description sÈmantique de cette relation"
+msgstr "descripción semantica de esta relación"
msgid "semantic description of this relation type"
-msgstr "description sÈmantique de ce type de relation"
+msgstr "descripción semantica de este tipo de relación"
msgid "semantic description of this state"
-msgstr "description sÈmantique de cet Ètat"
+msgstr "descripción semantica de este estado"
msgid "semantic description of this transition"
-msgstr "description sÈmantique de cette transition"
+msgstr "descripcion semantica de esta transición"
msgid "send email"
-msgstr "envoyer un courriel"
+msgstr "enviar email"
msgid "september"
-msgstr "septembre"
+msgstr "septiembre"
msgid "server debug information"
-msgstr "informations de dÈboguage serveur"
+msgstr "server debug information"
msgid "server information"
-msgstr "informations serveur"
+msgstr "server information"
msgid ""
"should html fields being edited using fckeditor (a HTML WYSIWYG editor). "
"You should also select text/html as default text format to actually get "
"fckeditor."
msgstr ""
-"indique si les champs HTML doivent Ítre Èditer avec fckeditor (un\n"
-"Èditer HTML WYSIWYG). Il est Ègalement conseill'de choisir text/html\n"
-"comme format de texte par dÈfaut pour pouvoir utiliser fckeditor."
+"indique si los campos deberan ser editados usando fckeditor (un\n"
+"editor HTML WYSIWYG). Debera tambien elegir text/html\n"
+"como formato de texto por default para poder utilizar fckeditor."
#, python-format
msgid "show %s results"
-msgstr "montrer %s rÈsultats"
+msgstr "mostrar %s resultados"
msgid "show advanced fields"
-msgstr "montrer les champs avancÈs"
+msgstr "mostrar campos avanzados"
msgid "show filter form"
msgstr "afficher le filtre"
msgid "show meta-data"
-msgstr "afficher les mÈta-donnÈes"
+msgstr "mostrar meta-data"
msgid "site configuration"
-msgstr "configuration du site"
+msgstr "configuracion del sitio"
msgid "site documentation"
-msgstr "documentation du site"
+msgstr "documentacion del sitio"
msgid "site schema"
-msgstr "schÈma du site"
+msgstr "esquema del sitio"
msgid "site title"
-msgstr "titre du site"
+msgstr "titulo del sitio"
msgid "site-wide property can't be set for user"
-msgstr "une propriÈtÈ spÈcifique au site ne peut Ítre propre ‡ un utilisateur"
+msgstr ""
+"una propiedad especifica para el sitio no puede establecerse para el usuario"
msgid "sorry, the server is unable to handle this query"
-msgstr "dÈsolÈ, le serveur ne peut traiter cette requÍte"
+msgstr "lo sentimos, el servidor no puede manejar esta consulta"
msgid "specializes"
-msgstr "dÈrive de"
+msgstr "derivado de"
msgid "specializes_object"
-msgstr "parent de"
+msgstr "objeto_derivado"
msgid "startup views"
-msgstr "vues de dÈpart"
+msgstr "vistas de inicio"
msgid "state"
-msgstr "Ètat"
+msgstr "estado"
msgid "state_of"
-msgstr "Ètat de"
+msgstr "estado_de"
msgid "state_of_object"
-msgstr "a pour Ètat"
+msgstr "objeto_estado_de"
msgid "status change"
-msgstr "changer l'Ètat"
+msgstr "cambio de estatus"
msgid "status changed"
-msgstr "changement d'Ètat"
+msgstr "estatus cambiado"
#, python-format
msgid "status will change from %(st1)s to %(st2)s"
-msgstr "l'entitÈ passera de l'Ètat %(st1)s ‡ l'Ètat %(st2)s"
+msgstr "estatus cambiara de %(st1)s a %(st2)s"
msgid "subject"
-msgstr "sujet"
+msgstr "sujeto"
msgid "subject/object cardinality"
-msgstr "cardinalitÈ sujet/objet"
+msgstr "cardinalidad sujeto/objeto"
+
+msgid "subject_plural:"
+msgstr ""
msgid "sunday"
-msgstr "dimanche"
+msgstr "domingo"
msgid "surname"
-msgstr "nom"
+msgstr "apellido"
msgid "symetric"
-msgstr "symÈtrique"
+msgstr "simetrico"
msgid "system entities"
-msgstr "entitÈs systËmes"
+msgstr "entidades de sistema"
msgid "table"
-msgstr "table"
+msgstr "tabla"
msgid "tablefilter"
-msgstr "filtre de tableau"
+msgstr "filtro de tabla"
msgid "task progression"
-msgstr "avancement de la t‚che"
+msgstr "progreso de la tarea"
msgid "text"
msgstr "text"
msgid "text/cubicweb-page-template"
-msgstr "contenu dynamique"
+msgstr "text/cubicweb-page-template"
msgid "text/html"
msgstr "html"
msgid "text/plain"
-msgstr "texte pur"
+msgstr "text/plain"
msgid "text/rest"
-msgstr "ReST"
+msgstr "text/rest"
msgid "the prefered email"
-msgstr "l'adresse Èlectronique principale"
+msgstr "dirección principal de email"
#, python-format
msgid "the value \"%s\" is already used, use another one"
-msgstr "la valeur \"%s\" est dÈj‡ utilisÈe, veuillez utiliser une autre valeur"
+msgstr "el valor \"%s\" ya esta en uso, favor de utilizar otro"
msgid "this action is not reversible!"
-msgstr ""
-"Attention ! Cette opÈration va dÈtruire les donnÈes de faÁon irrÈversible."
+msgstr "esta acción es irreversible!."
msgid "this entity is currently owned by"
-msgstr "cette entitÈ appartient ‡"
+msgstr "esta entidad es propiedad de"
msgid "this resource does not exist"
-msgstr "cette ressource est introuvable"
+msgstr "este recurso no existe"
msgid "thursday"
-msgstr "jeudi"
+msgstr "jueves"
msgid "timestamp"
-msgstr "date"
+msgstr "fecha"
msgid "timestamp of the latest source synchronization."
-msgstr "date de la derniËre synchronisation avec la source."
+msgstr "fecha de la ultima sincronización de la fuente."
msgid "timetable"
-msgstr "emploi du temps"
+msgstr "tabla de tiempos"
msgid "title"
-msgstr "titre"
+msgstr "titulo"
msgid "to"
-msgstr "‡"
-
-#, python-format
-msgid "to %(date)s"
-msgstr ""
+msgstr "a"
msgid "to associate with"
-msgstr "pour associer ‡"
+msgstr "a asociar con"
msgid "to_entity"
-msgstr "vers l'entitÈ"
+msgstr "hacia entidad"
msgid "to_entity_object"
-msgstr "relation objet"
+msgstr "hacia entidad objeto"
msgid "to_state"
-msgstr "vers l'Ètat"
+msgstr "hacia el estado"
msgid "to_state_object"
-msgstr "transitions vers cette Ètat"
+msgstr "hacia objeto estado"
msgid "todo_by"
-msgstr "‡ faire par"
-
-msgid "toggle check boxes"
-msgstr ""
+msgstr "a hacer por"
msgid "transition is not allowed"
-msgstr "transition non permise"
+msgstr "transition no permitida"
msgid "transition_of"
-msgstr "transition de"
+msgstr "transicion de"
msgid "transition_of_object"
-msgstr "a pour transition"
+msgstr "objeto de transición"
msgid "tree view"
msgstr ""
msgid "tuesday"
-msgstr "mardi"
+msgstr "martes"
msgid "type"
msgstr "type"
msgid "ui"
-msgstr "propriÈtÈs gÈnÈriques de l'interface"
+msgstr "interfaz de usuario"
+
+msgid "ui.date-format"
+msgstr ""
+
+msgid "ui.datetime-format"
+msgstr ""
+
+msgid "ui.default-text-format"
+msgstr ""
+
+msgid "ui.encoding"
+msgstr ""
+
+msgid "ui.fckeditor"
+msgstr ""
+
+msgid "ui.float-format"
+msgstr ""
+
+msgid "ui.language"
+msgstr ""
+
+msgid "ui.main-template"
+msgstr ""
+
+msgid "ui.site-title"
+msgstr ""
+
+msgid "ui.time-format"
+msgstr ""
msgid "unaccessible"
-msgstr "inaccessible"
+msgstr "inaccesible"
msgid "unauthorized value"
-msgstr "valeur non autorisÈe"
+msgstr "valor no permitido"
msgid "unique identifier used to connect to the application"
-msgstr "identifiant unique utilisÈ pour se connecter ‡ l'application"
+msgstr "identificador unico utilizado para conectar a la aplicación"
msgid "unknown external entity"
-msgstr "entitÈ (externe) introuvable"
+msgstr "entidad externa desconocida"
msgid "unknown property key"
-msgstr "clÈ de propriÈtÈ inconnue"
+msgstr "propiedad desconocida"
+
+msgid "up"
+msgstr ""
msgid "upassword"
-msgstr "mot de passe"
+msgstr "clave de acceso"
msgid "update"
-msgstr "modification"
+msgstr "modificación"
msgid "update_perm"
-msgstr "modification"
+msgstr "modificación"
msgid "update_permission"
-msgstr "permission de modification"
+msgstr "Permiso de modificación"
msgid "update_permission_object"
-msgstr "‡ la permission de modifier"
+msgstr "objeto de autorización de modificaciones"
#, python-format
msgid "updated %(etype)s #%(eid)s (%(title)s)"
-msgstr "modification de l'entitÈ %(etype)s #%(eid)s (%(title)s)"
+msgstr "actualización de la entidad %(etype)s #%(eid)s (%(title)s)"
msgid "use template languages"
-msgstr "utiliser les langages de template"
+msgstr "utilizar plantillas de lenguaje"
msgid ""
"use to define a transition from one or multiple states to a destination "
"states in workflow's definitions."
msgstr ""
-"utiliser dans une dÈfinition de processus pour ajouter une transition depuis "
-"un ou plusieurs Ètats vers un Ètat de destination."
+"utilizado para definir una transición desde uno o multiples estados hacia "
+"uno o varios estados destino en las definiciones del workflow"
msgid "use_email"
-msgstr "adresse Èlectronique"
+msgstr "correo electrónico"
msgid "use_email_object"
-msgstr "adresse utilisÈe par"
+msgstr "objeto email utilizado"
msgid "use_template_format"
-msgstr "utilisation du format 'cubicweb template'"
+msgstr "utilización del formato 'cubicweb template'"
msgid ""
"used for cubicweb configuration. Once a property has been created you can't "
"change the key."
msgstr ""
-"utilisÈ pour la configuration de l'application. Une fois qu'une propriÈtÈ a "
-"ÈtÈ crÈÈe, vous ne pouvez plus changez la clÈ associÈe"
+"utilizado para la configuración de cubicweb. Una vez que la propiedad ha "
+"sido creada no puede cambiar la llave"
msgid ""
"used to associate simple states to an entity type and/or to define workflows"
-msgstr "associe les Ètats ‡ un type d'entitÈ pour dÈfinir un workflow"
+msgstr ""
+"utilizado para asociar estados simples a un tipo de entidad y/o para definir "
+"workflows"
msgid "used to grant a permission to a group"
-msgstr "utiliser pour donner une permission ‡ un groupe"
+msgstr "utilizado para otorgar permisos a un grupo"
#, python-format
msgid ""
"user %s has made the following change(s):\n"
"\n"
msgstr ""
-"l'utilisateur %s a effectuÈ le(s) changement(s) suivant(s):\n"
+"el usuario %s ha efectuado los siguentes cambios:\n"
"\n"
msgid ""
"user for which this property is applying. If this relation is not set, the "
"property is considered as a global property"
msgstr ""
-"utilisateur a qui s'applique cette propriÈtÈ. Si cette relation n'est pas "
-"spÈcifiÈe la propriÈtÈ est considÈrÈe comme globale."
+"usuario para el cual aplica esta propiedad. Si no se establece esta "
+"relación, la propiedad es considerada como una propiedad global."
msgid "user interface encoding"
-msgstr "encodage utilisÈ dans l'interface utilisateur"
+msgstr "codificación de la interfaz de usuario"
msgid "user preferences"
-msgstr "prÈfÈrences utilisateur"
+msgstr "preferencias del usuario"
msgid "users"
-msgstr "utilisateurs"
+msgstr "usuarios"
msgid "users using this bookmark"
-msgstr "utilisateurs utilisant ce signet"
+msgstr "usuarios en este favorito"
msgid "validate modifications on selected items"
-msgstr "valider les modifications apportÈes aux ÈlÈments sÈlectionnÈs"
+msgstr "valida modificaciones sobre elementos seleccionados"
msgid "validating..."
-msgstr "chargement en cours ..."
+msgstr "validando ..."
msgid "value"
-msgstr "valeur"
+msgstr "valor"
msgid "value associated to this key is not editable manually"
-msgstr "la valeur associÈe ‡ cette clÈ n'est pas Èditable manuellement"
+msgstr "el valor asociado a este elemento no es editable manualmente"
msgid "vcard"
msgstr "vcard"
msgid "view"
-msgstr "voir"
+msgstr "ver"
msgid "view all"
-msgstr "voir tous"
+msgstr "ver todos"
msgid "view detail for this entity"
-msgstr "voir les dÈtails de cette entitÈ"
+msgstr "ver detalle de esta entidad"
msgid "view workflow"
-msgstr "voir les Ètats possibles"
+msgstr "ver workflow"
msgid "views"
-msgstr "vues"
+msgstr "vistas"
msgid "visible"
msgstr "visible"
msgid "wednesday"
-msgstr "mercredi"
+msgstr "miercoles"
msgid "week"
msgstr "sem."
#, python-format
msgid "welcome %s !"
-msgstr "bienvenue %s !"
+msgstr "bienvenido %s !"
msgid "wf_info_for"
-msgstr "historique de"
+msgstr "historial de"
msgid "wf_info_for_object"
-msgstr "historique des transitions"
+msgstr "historial de transiciones"
msgid ""
"when multiple addresses are equivalent (such as python-projects@logilab.org "
"and python-projects@lists.logilab.org), set this to true on one of them "
"which is the preferred form."
msgstr ""
-"quand plusieurs adresses sont Èquivalentes (comme python-projects@logilab."
-"org et python-projects@lists.logilab.org), mettez cette propriÈtÈ ‡ vrai sur "
-"l'une d'entre-elle qui sera la forme canonique"
+"cuando multiples direcciones de correo son equivalentes (como python-"
+"projects@logilab.org y python-projects@lists.logilab.org), establecer esto "
+"como verdadero en una de ellas es la forma preferida "
#, python-format
msgid "workflow for %s"
-msgstr "workflow pour %s"
+msgstr "workflow para %s"
msgid "xbel"
msgstr "xbel"
@@ -2939,13 +3015,10 @@
msgstr ""
msgid "yes"
-msgstr "oui"
+msgstr "si"
msgid "you have been logged out"
-msgstr "vous avez ÈtÈ dÈconnectÈ"
-
-msgid "you should probably delete that property"
-msgstr ""
+msgstr "ha terminado la sesion"
#~ msgid "%s constraint failed"
#~ msgstr "La contrainte %s n'est pas satisfaite"
@@ -2962,30 +3035,15 @@
#~ msgid "Card_plural"
#~ msgstr "Fichas"
-#~ msgid "Email body: "
-#~ msgstr "Contenido del correo electrónico : "
-
-#~ msgid "From: "
-#~ msgstr "De : "
-
#~ msgid "Loading"
#~ msgstr "chargement"
#~ msgid "New Card"
-#~ msgstr "Nueva ficha"
-
-#~ msgid "Problem occured"
-#~ msgstr "Ha ocurrido un error"
+#~ msgstr "Agregar Ficha"
#~ msgid "Problem occured while setting new value"
#~ msgstr "Un problËme est survenu lors de la mise ‡ jour"
-#~ msgid "Recipients: "
-#~ msgstr "Destinatarios : "
-
-#~ msgid "Subject: "
-#~ msgstr "Objeto : "
-
#~ msgid "This Card"
#~ msgstr "Esta Ficha"
@@ -2994,22 +3052,10 @@
#~ "reminder"
#~ msgstr ""
#~ "una ficha es un texto utilizado como documentación, referencia, memoria "
-#~ "de procedimiento..."
+#~ "de algún procedimiento..."
#~ msgid "add a Card"
-#~ msgstr "agregar una ficha"
-
-#~ msgid "am/pm calendar (month)"
-#~ msgstr "calendario am/pm (mes)"
-
-#~ msgid "am/pm calendar (semester)"
-#~ msgstr "calendario am/pm (semestre)"
-
-#~ msgid "am/pm calendar (week)"
-#~ msgstr "calendario am/pm (semana)"
-
-#~ msgid "am/pm calendar (year)"
-#~ msgstr "calendario am/pm (año)"
+#~ msgstr "Agregar una ficha"
#~ msgid "an abstract for this card"
#~ msgstr "un resumen para esta ficha"
@@ -3020,26 +3066,14 @@
#~ msgid "at least one relation %s is required on %s(%s)"
#~ msgstr "au moins une relation %s est nÈcessaire sur %s(%s)"
-#~ msgid "calendar (month)"
-#~ msgstr "calendario (mensual)"
-
-#~ msgid "calendar (semester)"
-#~ msgstr "calendario (semestral)"
-
-#~ msgid "calendar (week)"
-#~ msgstr "calendario (semanal)"
-
-#~ msgid "calendar (year)"
-#~ msgstr "calendario (anual)"
-
#~ msgid "cancel edition"
#~ msgstr "annuler l'Èdition"
#~ msgid "content"
-#~ msgstr "contenido"
+#~ msgstr "Contenido"
#~ msgid "content_format"
-#~ msgstr "formato"
+#~ msgstr "Formato"
#~ msgid ""
#~ "default language (look at the i18n directory of the application to see "
@@ -3048,6 +3082,9 @@
#~ "langue par dÈfaut (regarder le rÈpertoire i18n de l'application pour voir "
#~ "les langues disponibles)"
+#~ msgid "detach attached file"
+#~ msgstr "soltar el archivo existente"
+
#~ msgid "filter"
#~ msgstr "filtrer"
@@ -3057,9 +3094,6 @@
#~ msgid "header"
#~ msgstr "en-tÍte de page"
-#~ msgid "i18n_register_user"
-#~ msgstr "registrarse"
-
#~ msgid "iCal"
#~ msgstr "iCal"
@@ -3067,7 +3101,7 @@
#~ msgstr "valeur incorrecte pour le type \"%s\""
#~ msgid "inlined view"
-#~ msgstr "vista incluída (en línea)"
+#~ msgstr "Vista incluída (en línea)"
#~ msgid "linked"
#~ msgstr "liÈ"
@@ -3083,8 +3117,11 @@
#~ msgid "owned by"
#~ msgstr "appartient ‡"
+#~ msgid "planned_delivery"
+#~ msgstr "entrega planeada"
+
#~ msgid "remove this Card"
-#~ msgstr "supprimer cette fiche"
+#~ msgstr "Eliminar esta Ficha"
#~ msgid "see also"
#~ msgstr "voir aussi"
@@ -3093,10 +3130,10 @@
#~ msgstr "l'Ètat va passer de %s ‡ %s"
#~ msgid "synopsis"
-#~ msgstr "synopsis"
+#~ msgstr "sinopsis"
#~ msgid "wikiid"
-#~ msgstr "identifiant wiki"
+#~ msgstr "identificador wiki"
#~ msgid "workflow history"
#~ msgstr "historique du workflow"
--- a/i18n/fr.po Tue May 05 12:07:42 2009 +0200
+++ b/i18n/fr.po Tue May 05 17:13:37 2009 +0200
@@ -123,6 +123,10 @@
msgid "%s software version of the database"
msgstr "version logicielle de la base pour %s"
+#, python-format
+msgid "%s_perm"
+msgstr ""
+
msgid "**"
msgstr "0..n 0..n"
@@ -201,11 +205,30 @@
msgid "Bytes_plural"
msgstr "Données binaires"
-msgid "CWAttribute"
-msgstr "Attribut"
-
-msgid "CWAttribute_plural"
-msgstr "Attributs"
+msgid "Date"
+msgstr "Date"
+
+msgid "Date_plural"
+msgstr "Dates"
+
+msgid "Datetime"
+msgstr "Date et heure"
+
+msgid "Datetime_plural"
+msgstr "Date et heure"
+
+#, python-format
+msgid "Debug level set to %s"
+msgstr "Niveau de debug mis à %s"
+
+msgid "Decimal"
+msgstr "Nombre décimal"
+
+msgid "Decimal_plural"
+msgstr "Nombres décimaux"
+
+msgid "Do you want to delete the following element(s) ?"
+msgstr "Voulez vous supprimer le(s) élément(s) suivant(s)"
msgid "CWCache"
msgstr "Cache applicatif"
@@ -231,12 +254,24 @@
msgid "CWEType_plural"
msgstr "Types d'entité"
+msgid "CWAttribute"
+msgstr "Attribut"
+
+msgid "CWAttribute_plural"
+msgstr "Attributs"
+
msgid "CWGroup"
msgstr "Groupe"
msgid "CWGroup_plural"
msgstr "Groupes"
+msgid "CWRelation"
+msgstr "Relation"
+
+msgid "CWRelation_plural"
+msgstr "Relations"
+
msgid "CWPermission"
msgstr "Permission"
@@ -255,42 +290,14 @@
msgid "CWRType_plural"
msgstr "Types de relation"
-msgid "CWRelation"
-msgstr "Relation"
-
-msgid "CWRelation_plural"
-msgstr "Relations"
-
msgid "CWUser"
msgstr "Utilisateur"
msgid "CWUser_plural"
msgstr "Utilisateurs"
-msgid "Date"
-msgstr "Date"
-
-msgid "Date_plural"
-msgstr "Dates"
-
-msgid "Datetime"
-msgstr "Date et heure"
-
-msgid "Datetime_plural"
-msgstr "Date et heure"
-
-#, python-format
-msgid "Debug level set to %s"
-msgstr "Niveau de debug mis à %s"
-
-msgid "Decimal"
-msgstr "Nombre décimal"
-
-msgid "Decimal_plural"
-msgstr "Nombres décimaux"
-
-msgid "Do you want to delete the following element(s) ?"
-msgstr "Voulez vous supprimer le(s) élément(s) suivant(s)"
+msgid "Email body: "
+msgstr "Contenu du courriel : "
msgid "EmailAddress"
msgstr "Adresse électronique"
@@ -310,8 +317,8 @@
msgid "Float_plural"
msgstr "Nombres flottants"
-msgid "From:"
-msgstr ""
+msgid "From: "
+msgstr "De : "
msgid "Int"
msgstr "Nombre entier"
@@ -328,9 +335,6 @@
msgid "New Bookmark"
msgstr "Nouveau signet"
-msgid "New CWAttribute"
-msgstr "Nouvelle définition de relation"
-
msgid "New CWCache"
msgstr "Nouveau cache applicatif"
@@ -343,9 +347,15 @@
msgid "New CWEType"
msgstr "Nouveau type d'entité"
+msgid "New CWAttribute"
+msgstr "Nouvelle définition de relation finale"
+
msgid "New CWGroup"
msgstr "Nouveau groupe"
+msgid "New CWRelation"
+msgstr "Nouvelle définition de relation non finale"
+
msgid "New CWPermission"
msgstr "Nouvelle permission"
@@ -355,9 +365,6 @@
msgid "New CWRType"
msgstr "Nouveau type de relation"
-msgid "New CWRelation"
-msgstr "Nouvel attribut"
-
msgid "New CWUser"
msgstr "Nouvel utilisateur"
@@ -394,14 +401,17 @@
msgid "Please note that this is only a shallow copy"
msgstr "Attention, cela n'effectue qu'une copie de surface"
+msgid "Problem occured"
+msgstr "Une erreur est survenue"
+
msgid "RQLExpression"
msgstr "Expression RQL"
msgid "RQLExpression_plural"
msgstr "Expressions RQL"
-msgid "Recipients:"
-msgstr "Destinataires :"
+msgid "Recipients: "
+msgstr "Destinataires : "
msgid "Relations"
msgstr "Relations"
@@ -434,8 +444,8 @@
msgid "String_plural"
msgstr "Chaînes de caractères"
-msgid "Subject:"
-msgstr "Sujet :"
+msgid "Subject: "
+msgstr "Sujet : "
msgid "Submit bug report"
msgstr "Soumettre un rapport de bug"
@@ -461,9 +471,6 @@
msgid "This Bookmark"
msgstr "Ce signet"
-msgid "This CWAttribute"
-msgstr "Cette définition de relation"
-
msgid "This CWCache"
msgstr "Ce cache applicatif"
@@ -476,9 +483,15 @@
msgid "This CWEType"
msgstr "Ce type d'entité"
+msgid "This CWAttribute"
+msgstr "Cette définition de relation finale"
+
msgid "This CWGroup"
msgstr "Ce groupe"
+msgid "This CWRelation"
+msgstr "Cette définition de relation non finale"
+
msgid "This CWPermission"
msgstr "Cette permission"
@@ -488,9 +501,6 @@
msgid "This CWRType"
msgstr "Ce type de relation"
-msgid "This CWRelation"
-msgstr "Cet attribut"
-
msgid "This CWUser"
msgstr "Cet utilisateur"
@@ -680,12 +690,6 @@
msgid "actions_manage_description"
msgstr ""
-msgid "actions_managepermission"
-msgstr ""
-
-msgid "actions_managepermission_description"
-msgstr ""
-
msgid "actions_muledit"
msgstr "édition multiple"
@@ -758,12 +762,6 @@
msgid "add Bookmark bookmarked_by CWUser object"
msgstr "signet"
-msgid "add CWAttribute constrained_by CWConstraint subject"
-msgstr "contrainte"
-
-msgid "add CWAttribute relation_type CWRType object"
-msgstr "définition d'attribut"
-
msgid "add CWEType add_permission RQLExpression subject"
msgstr "définir une expression RQL d'ajout"
@@ -776,6 +774,18 @@
msgid "add CWEType update_permission RQLExpression subject"
msgstr "définir une expression RQL de mise à jour"
+msgid "add CWAttribute constrained_by CWConstraint subject"
+msgstr "contrainte"
+
+msgid "add CWAttribute relation_type CWRType object"
+msgstr "définition d'attribut"
+
+msgid "add CWRelation constrained_by CWConstraint subject"
+msgstr "contrainte"
+
+msgid "add CWRelation relation_type CWRType object"
+msgstr "définition de relation"
+
msgid "add CWProperty for_user CWUser object"
msgstr "propriété"
@@ -788,12 +798,6 @@
msgid "add CWRType read_permission RQLExpression subject"
msgstr "expression RQL de lecture"
-msgid "add CWRelation constrained_by CWConstraint subject"
-msgstr "contrainte"
-
-msgid "add CWRelation relation_type CWRType object"
-msgstr "définition de relation"
-
msgid "add CWUser in_group CWGroup object"
msgstr "utilisateur"
@@ -824,9 +828,6 @@
msgid "add a Bookmark"
msgstr "ajouter un signet"
-msgid "add a CWAttribute"
-msgstr "ajouter un attribut"
-
msgid "add a CWCache"
msgstr "ajouter un cache applicatif"
@@ -839,9 +840,15 @@
msgid "add a CWEType"
msgstr "ajouter un type d'entité"
+msgid "add a CWAttribute"
+msgstr "ajouter un type de relation"
+
msgid "add a CWGroup"
msgstr "ajouter un groupe d'utilisateurs"
+msgid "add a CWRelation"
+msgstr "ajouter une relation"
+
msgid "add a CWPermission"
msgstr "ajouter une permission"
@@ -851,9 +858,6 @@
msgid "add a CWRType"
msgstr "ajouter un type de relation"
-msgid "add a CWRelation"
-msgstr "ajouter une relation"
-
msgid "add a CWUser"
msgstr "ajouter un utilisateur"
@@ -919,6 +923,18 @@
msgid "allowed_transition_object"
msgstr "états en entrée"
+msgid "am/pm calendar (month)"
+msgstr "calendrier am/pm (mois)"
+
+msgid "am/pm calendar (semester)"
+msgstr "calendrier am/pm (semestre)"
+
+msgid "am/pm calendar (week)"
+msgstr "calendrier am/pm (semaine)"
+
+msgid "am/pm calendar (year)"
+msgstr "calendrier am/pm (année)"
+
msgid "an electronic mail address associated to a short alias"
msgstr "une addresse électronique associée à un alias"
@@ -958,6 +974,9 @@
msgid "attribute"
msgstr "attribut"
+msgid "attributes with modified permissions:"
+msgstr "attributs ayant des permissions modifiées :"
+
msgid "august"
msgstr "août"
@@ -1070,6 +1089,18 @@
msgid "calendar"
msgstr "afficher un calendrier"
+msgid "calendar (month)"
+msgstr "calendrier (mensuel)"
+
+msgid "calendar (semester)"
+msgstr "calendrier (semestriel)"
+
+msgid "calendar (week)"
+msgstr "calendrier (hebdo)"
+
+msgid "calendar (year)"
+msgstr "calendrier (annuel)"
+
#, python-format
msgid "can't change the %s attribute"
msgstr "ne peut changer l'attribut %s"
@@ -1102,6 +1133,9 @@
msgid "cardinality"
msgstr "cardinalité"
+msgid "category"
+msgstr "categorie"
+
#, python-format
msgid "changed state of %(etype)s #%(eid)s (%(title)s)"
msgstr "changement de l'état de %(etype)s #%(eid)s (%(title)s)"
@@ -1112,6 +1146,9 @@
msgid "click on the box to cancel the deletion"
msgstr "cliquer dans la zone d'édition pour annuler la suppression"
+msgid "close all"
+msgstr "tout fermer"
+
msgid "comment"
msgstr "commentaire"
@@ -1184,6 +1221,12 @@
msgid "components_rqlinput_description"
msgstr "la barre de requête rql, dans l'en-tête de page"
+msgid "components_rss_feed_url"
+msgstr "syndication rss"
+
+msgid "components_rss_feed_url_description"
+msgstr ""
+
msgid "composite"
msgstr "composite"
@@ -1340,31 +1383,28 @@
msgid "creating Bookmark (Bookmark bookmarked_by CWUser %(linkto)s)"
msgstr "création d'un signet pour %(linkto)s"
+msgid "creating CWConstraint (CWAttribute %(linkto)s constrained_by CWConstraint)"
+msgstr "création d'une contrainte pour l'attribut %(linkto)s"
+
+msgid "creating CWConstraint (CWRelation %(linkto)s constrained_by CWConstraint)"
+msgstr "création d'une contrainte pour la relation %(linkto)s"
+
msgid "creating CWAttribute (CWAttribute relation_type CWRType %(linkto)s)"
msgstr "création d'un attribut %(linkto)s"
-msgid ""
-"creating CWConstraint (CWAttribute %(linkto)s constrained_by CWConstraint)"
-msgstr "création d'une contrainte pour l'attribut %(linkto)s"
-
-msgid ""
-"creating CWConstraint (CWRelation %(linkto)s constrained_by CWConstraint)"
-msgstr "création d'une contrainte pour la relation %(linkto)s"
+msgid "creating CWRelation (CWRelation relation_type CWRType %(linkto)s)"
+msgstr "création relation %(linkto)s"
msgid "creating CWProperty (CWProperty for_user CWUser %(linkto)s)"
msgstr "création d'une propriété pour l'utilisateur %(linkto)s"
-msgid "creating CWRelation (CWRelation relation_type CWRType %(linkto)s)"
-msgstr "création relation %(linkto)s"
-
msgid "creating CWUser (CWUser in_group CWGroup %(linkto)s)"
msgstr "création d'un utilisateur à rajouter au groupe %(linkto)s"
msgid "creating EmailAddress (CWUser %(linkto)s use_email EmailAddress)"
msgstr "création d'une adresse électronique pour l'utilisateur %(linkto)s"
-msgid ""
-"creating RQLExpression (CWEType %(linkto)s add_permission RQLExpression)"
+msgid "creating RQLExpression (CWEType %(linkto)s add_permission RQLExpression)"
msgstr "création d'une expression RQL pour la permission d'ajout de %(linkto)s"
msgid ""
@@ -1381,8 +1421,7 @@
msgstr ""
"création d'une expression RQL pour la permission de mise à jour de %(linkto)s"
-msgid ""
-"creating RQLExpression (CWRType %(linkto)s add_permission RQLExpression)"
+msgid "creating RQLExpression (CWRType %(linkto)s add_permission RQLExpression)"
msgstr ""
"création d'une expression RQL pour la permission d'ajout des relations %"
"(linkto)s"
@@ -1569,9 +1608,6 @@
msgid "destination_state_object"
msgstr "destination de"
-msgid "detach attached file"
-msgstr "détacher le fichier existant"
-
#, python-format
msgid "detach attached file %s"
msgstr "détacher le fichier existant %s"
@@ -1652,18 +1688,9 @@
msgid "entities deleted"
msgstr "entités supprimées"
-msgid "entity copied"
-msgstr ""
-
-msgid "entity created"
-msgstr ""
-
msgid "entity deleted"
msgstr "entité supprimée"
-msgid "entity edited"
-msgstr ""
-
msgid "entity type"
msgstr "type d'entité"
@@ -1774,10 +1801,6 @@
msgid "from"
msgstr "de"
-#, python-format
-msgid "from %(date)s"
-msgstr ""
-
msgid "from_entity"
msgstr "de l'entité"
@@ -1863,7 +1886,7 @@
msgstr "cacher le filtre"
msgid "hide meta-data"
-msgstr "cacher les méta-données"
+msgstr "cacher les entités et relations \"méta\""
msgid "home"
msgstr "maison"
@@ -2095,6 +2118,11 @@
msgid "link a transition to one or more entity type"
msgstr "lie une transition à un ou plusieurs types d'entités"
+msgid ""
+"link a transition to one or more rql expression allowing to go through this "
+"transition"
+msgstr ""
+
msgid "link to each item in"
msgstr "lier vers chaque élément dans"
@@ -2110,9 +2138,6 @@
msgid "login"
msgstr "identifiant"
-msgid "login or email"
-msgstr "identifiant ou email"
-
msgid "login_action"
msgstr "identifiez vous"
@@ -2218,6 +2243,18 @@
msgid "navigation"
msgstr "navigation"
+msgid "navigation.combobox-limit"
+msgstr "nombre d'entités dans les listes déroulantes"
+
+msgid "navigation.page-size"
+msgstr "nombre de résultats"
+
+msgid "navigation.related-limit"
+msgstr "nombre d'entités dans la vue primaire"
+
+msgid "navigation.short-line-size"
+msgstr "description courtes"
+
msgid "navtop"
msgstr "haut de page du contenu principal"
@@ -2270,6 +2307,9 @@
msgid "object"
msgstr "objet"
+msgid "object_plural:"
+msgstr "objets :"
+
msgid "october"
msgstr "octobre"
@@ -2285,6 +2325,9 @@
msgid "only select queries are authorized"
msgstr "seules les requêtes de sélections sont autorisées"
+msgid "open all"
+msgstr "tout ouvrir"
+
msgid "order"
msgstr "ordre"
@@ -2329,6 +2372,12 @@
msgid "permission"
msgstr "permission"
+msgid "permissions for entities"
+msgstr "permissions pour les entités"
+
+msgid "permissions for relations"
+msgstr "permissions pour les relations"
+
msgid "permissions for this entity"
msgstr "permissions pour cette entité"
@@ -2396,6 +2445,9 @@
msgid "relation_type_object"
msgstr "définition"
+msgid "relations"
+msgstr ""
+
msgid "relations deleted"
msgstr "relations supprimées"
@@ -2405,9 +2457,6 @@
msgid "remove this Bookmark"
msgstr "supprimer ce signet"
-msgid "remove this CWAttribute"
-msgstr "supprimer cet attribut"
-
msgid "remove this CWCache"
msgstr "supprimer ce cache applicatif"
@@ -2420,9 +2469,15 @@
msgid "remove this CWEType"
msgstr "supprimer ce type d'entité"
+msgid "remove this CWAttribute"
+msgstr "supprimer cet attribut"
+
msgid "remove this CWGroup"
msgstr "supprimer ce groupe"
+msgid "remove this CWRelation"
+msgstr "supprimer cette relation"
+
msgid "remove this CWPermission"
msgstr "supprimer cette permission"
@@ -2432,9 +2487,6 @@
msgid "remove this CWRType"
msgstr "supprimer cette définition de relation"
-msgid "remove this CWRelation"
-msgstr "supprimer cette relation"
-
msgid "remove this CWUser"
msgstr "supprimer cet utilisateur"
@@ -2541,9 +2593,6 @@
msgid "select a"
msgstr "sélectionner un"
-msgid "select a key first"
-msgstr ""
-
msgid "select a relation"
msgstr "sélectionner une relation"
@@ -2603,7 +2652,7 @@
msgstr "afficher le filtre"
msgid "show meta-data"
-msgstr "afficher les méta-données"
+msgstr "afficher le schéma complet"
msgid "site configuration"
msgstr "configuration du site"
@@ -2657,6 +2706,9 @@
msgid "subject/object cardinality"
msgstr "cardinalité sujet/objet"
+msgid "subject_plural:"
+msgstr "sujets :"
+
msgid "sunday"
msgstr "dimanche"
@@ -2728,10 +2780,6 @@
msgid "to"
msgstr "à"
-#, python-format
-msgid "to %(date)s"
-msgstr ""
-
msgid "to associate with"
msgstr "pour associer à"
@@ -2750,9 +2798,6 @@
msgid "todo_by"
msgstr "à faire par"
-msgid "toggle check boxes"
-msgstr ""
-
msgid "transition is not allowed"
msgstr "transition non permise"
@@ -2774,6 +2819,36 @@
msgid "ui"
msgstr "propriétés génériques de l'interface"
+msgid "ui.date-format"
+msgstr "format de date"
+
+msgid "ui.datetime-format"
+msgstr "format de date et de l'heure"
+
+msgid "ui.default-text-format"
+msgstr "format de texte"
+
+msgid "ui.encoding"
+msgstr "encodage"
+
+msgid "ui.fckeditor"
+msgstr "éditeur du contenu"
+
+msgid "ui.float-format"
+msgstr "format des flottants"
+
+msgid "ui.language"
+msgstr "langue"
+
+msgid "ui.main-template"
+msgstr "gabarit principal"
+
+msgid "ui.site-title"
+msgstr "titre du site"
+
+msgid "ui.time-format"
+msgstr "format de l'heure"
+
msgid "unaccessible"
msgstr "inaccessible"
@@ -2789,6 +2864,9 @@
msgid "unknown property key"
msgstr "clé de propriété inconnue"
+msgid "up"
+msgstr ""
+
msgid "upassword"
msgstr "mot de passe"
@@ -2945,9 +3023,6 @@
msgid "you have been logged out"
msgstr "vous avez été déconnecté"
-msgid "you should probably delete that property"
-msgstr ""
-
#~ msgid "%s constraint failed"
#~ msgstr "La contrainte %s n'est pas satisfaite"
@@ -2963,21 +3038,12 @@
#~ msgid "Card_plural"
#~ msgstr "Fiches"
-#~ msgid "Email body: "
-#~ msgstr "Contenu du courriel : "
-
-#~ msgid "From: "
-#~ msgstr "De : "
-
#~ msgid "Loading"
#~ msgstr "chargement"
#~ msgid "New Card"
#~ msgstr "Nouvelle fiche"
-#~ msgid "Problem occured"
-#~ msgstr "Une erreur est survenue"
-
#~ msgid "Problem occured while setting new value"
#~ msgstr "Un problème est survenu lors de la mise à jour"
@@ -2991,21 +3057,12 @@
#~ "une fiche est un texte utilisé comme documentation, référence, rappel de "
#~ "procédure..."
+#~ msgid "actions_addpermission"
+#~ msgstr "ajouter une permission"
+
#~ msgid "add a Card"
#~ msgstr "ajouter une fiche"
-#~ msgid "am/pm calendar (month)"
-#~ msgstr "calendrier am/pm (mois)"
-
-#~ msgid "am/pm calendar (semester)"
-#~ msgstr "calendrier am/pm (semestre)"
-
-#~ msgid "am/pm calendar (week)"
-#~ msgstr "calendrier am/pm (semaine)"
-
-#~ msgid "am/pm calendar (year)"
-#~ msgstr "calendrier am/pm (année)"
-
#~ msgid "an abstract for this card"
#~ msgstr "un résumé pour cette fiche"
@@ -3015,24 +3072,9 @@
#~ msgid "at least one relation %s is required on %s(%s)"
#~ msgstr "au moins une relation %s est nécessaire sur %s(%s)"
-#~ msgid "calendar (month)"
-#~ msgstr "calendrier (mensuel)"
-
-#~ msgid "calendar (semester)"
-#~ msgstr "calendrier (semestriel)"
-
-#~ msgid "calendar (week)"
-#~ msgstr "calendrier (hebdo)"
-
-#~ msgid "calendar (year)"
-#~ msgstr "calendrier (annuel)"
-
#~ msgid "cancel edition"
#~ msgstr "annuler l'édition"
-#~ msgid "components_rss_feed_url"
-#~ msgstr "syndication rss"
-
#~ msgid "content"
#~ msgstr "contenu"
@@ -3046,6 +3088,9 @@
#~ "langue par défaut (regarder le répertoire i18n de l'application pour voir "
#~ "les langues disponibles)"
+#~ msgid "detach attached file"
+#~ msgstr "détacher le fichier existant"
+
#~ msgid "filter"
#~ msgstr "filtrer"
@@ -3055,9 +3100,6 @@
#~ msgid "header"
#~ msgstr "en-tête de page"
-#~ msgid "i18n_register_user"
-#~ msgstr "s'enregister"
-
#~ msgid "iCal"
#~ msgstr "iCal"
@@ -3096,9 +3138,6 @@
#~ msgid "synopsis"
#~ msgstr "synopsis"
-#~ msgid "trcomment"
-#~ msgstr "commentaire"
-
#~ msgid "wikiid"
#~ msgstr "identifiant wiki"
--- a/server/schemaserial.py Tue May 05 12:07:42 2009 +0200
+++ b/server/schemaserial.py Tue May 05 17:13:37 2009 +0200
@@ -32,7 +32,7 @@
if missing:
print 'some native groups are missing but the following groups have been found:'
print '\n'.join('* %s (%s)' % (n, eid) for n, eid in res.items())
- print
+ print
print 'enter the eid of a to group to map to each missing native group'
print 'or just type enter to skip permissions granted to a group'
for group in missing:
@@ -56,7 +56,7 @@
print 'changed SQL_PREFIX for %s' % module
except KeyError:
pass
-
+
def _update_database(schema, sqlcu):
"""3.2.0 migration function: update database schema by adding SQL_PREFIX to
entity type tables and columns
@@ -90,7 +90,8 @@
repo = session.repo
sqlcu = session.pool['system']
_3_2_migration = False
- if 'eetype' in [t.lower() for t in repo.system_source.dbhelper.list_tables(sqlcu)]:
+ tables = set(t.lower() for t in repo.system_source.dbhelper.list_tables(sqlcu))
+ if 'eetype' in tables:
_3_2_migration = True
# 3.2 migration
_set_sql_prefix('')
@@ -99,9 +100,11 @@
for etype in ('EFRDef', 'ENFRDef', 'ERType', 'EEType',
'EConstraintType', 'EConstraint', 'EGroup', 'EUser',
'ECache', 'EPermission', 'EProperty'):
- sql = 'ALTER TABLE %s RENAME TO %s' % (etype, ETYPE_NAME_MAP[etype])
- print sql
- sqlcu.execute(sql)
+ if etype.lower() in tables:
+ sql = 'ALTER TABLE %s RENAME TO %s' % (etype,
+ ETYPE_NAME_MAP[etype])
+ print sql
+ sqlcu.execute(sql)
# other table renaming done once schema has been readen
# print 'reading schema from the database...'
index = {}
@@ -132,9 +135,9 @@
except:
pass
tocleanup = [eid]
- tocleanup += (eid for eid, (eidetype, uri, extid) in session.repo._type_source_cache.items()
+ tocleanup += (eid for eid, (eidetype, uri, extid) in repo._type_source_cache.items()
if etype == eidetype)
- session.repo.clear_caches(tocleanup)
+ repo.clear_caches(tocleanup)
session.commit(False)
etype = ETYPE_NAME_MAP[etype]
etype = ybo.EntityType(name=etype, description=desc, meta=meta, eid=eid)
@@ -167,7 +170,7 @@
fulltext_container=ft_container, eid=eid)
rschema = schema.add_relation_type(rtype)
index[eid] = rschema
- set_perms(rschema, permsdict.get(eid, {}))
+ set_perms(rschema, permsdict.get(eid, {}))
cstrsdict = deserialize_rdef_constraints(session)
for values in session.execute(
'Any X,SE,RT,OE,CARD,ORD,DESC,IDX,FTIDX,I18N,DFLT WHERE X is CWAttribute,'
@@ -181,7 +184,7 @@
rtype = index[reid].type
toetype = index[teid].type
rdef = ybo.RelationDefinition(frometype, rtype, toetype, cardinality=card,
- order=ord, description=desc,
+ order=ord, description=desc,
constraints=constraints,
indexed=idx, fulltextindexed=ftidx,
internationalizable=i18n,
@@ -197,7 +200,7 @@
toetype = index[teid].type
constraints = cstrsdict.get(rdefeid, ())
rdef = ybo.RelationDefinition(frometype, rtype, toetype, cardinality=card,
- order=ord, description=desc,
+ order=ord, description=desc,
composite=c, constraints=constraints,
eid=rdefeid)
schema.add_relation_def(rdef)
@@ -241,7 +244,7 @@
actperms.append(erschema.rql_expression(*something))
else: # group name
actperms.append(something)
- erschema.set_permissions(action, actperms)
+ erschema.set_permissions(action, actperms)
def deserialize_rdef_constraints(session):
@@ -254,8 +257,8 @@
cstr.eid = ceid
res.setdefault(rdefeid, []).append(cstr)
return res
-
-
+
+
# schema / perms serialization ################################################
def serialize_schema(cursor, schema, verbose=False):
@@ -352,12 +355,12 @@
value = unicode(value)
values[amap.get(prop, prop)] = value
return values
-
+
def nfrdef_relations_values(rschema, objtype, props):
values = _rdef_values(rschema, objtype, props)
relations = ['X %s %%(%s)s' % (attr, attr) for attr in sorted(values)]
return relations, values
-
+
def frdef_relations_values(rschema, objtype, props):
values = _rdef_values(rschema, objtype, props)
default = values['default']
@@ -371,7 +374,7 @@
relations = ['X %s %%(%s)s' % (attr, attr) for attr in sorted(values)]
return relations, values
-
+
def __rdef2rql(genmap, rschema, subjtype=None, objtype=None, props=None):
if subjtype is None:
assert objtype is None
@@ -405,7 +408,7 @@
elif allow is not None:
return chain(*[erschema2rql(schema[t]) for t in all if t in allow])
return chain(*[erschema2rql(schema[t]) for t in all])
-
+
def erschema2rql(erschema):
if isinstance(erschema, schemamod.EntitySchema):
return eschema2rql(erschema)
@@ -442,7 +445,7 @@
if addrdef:
for rql, values in rdef2rql(rschema):
yield rql, values
-
+
def rdef2rql(rschema, subjtype=None, objtype=None, props=None):
genmap = {True: frdef2rql, False: nfrdef2rql}
return __rdef2rql(genmap, rschema, subjtype, objtype, props)
@@ -458,7 +461,7 @@
yield 'INSERT CWAttribute X: %s WHERE %s' % (','.join(relations), _LOCATE_RDEF_RQL1), values
for rql, values in rdefrelations2rql(rschema, subjtype, objtype, props):
yield rql + ', EDEF is CWAttribute', values
-
+
def nfrdef2rql(rschema, subjtype, objtype, props):
relations, values = nfrdef_relations_values(rschema, objtype, props)
relations.append(_LOCATE_RDEF_RQL0)
@@ -466,7 +469,7 @@
yield 'INSERT CWRelation X: %s WHERE %s' % (','.join(relations), _LOCATE_RDEF_RQL1), values
for rql, values in rdefrelations2rql(rschema, subjtype, objtype, props):
yield rql + ', EDEF is CWRelation', values
-
+
def rdefrelations2rql(rschema, subjtype, objtype, props):
iterators = []
for constraint in props['constraints']:
@@ -525,7 +528,7 @@
relations, values = rschema_relations_values(rschema)
values['rt'] = rschema.type
yield 'SET %s WHERE X is CWRType, X name %%(rt)s' % ','.join(relations), values
-
+
def updaterdef2rql(rschema, subjtype=None, objtype=None, props=None):
genmap = {True: updatefrdef2rql, False: updatenfrdef2rql}
return __rdef2rql(genmap, rschema, subjtype, objtype, props)
@@ -536,7 +539,7 @@
yield 'SET %s WHERE %s, %s, X is CWAttribute' % (','.join(relations),
_LOCATE_RDEF_RQL0,
_LOCATE_RDEF_RQL1), values
-
+
def updatenfrdef2rql(rschema, subjtype, objtype, props):
relations, values = nfrdef_relations_values(rschema, objtype, props)
values.update({'se': subjtype, 'rt': str(rschema), 'oe': objtype})
--- a/server/serverconfig.py Tue May 05 12:07:42 2009 +0200
+++ b/server/serverconfig.py Tue May 05 17:13:37 2009 +0200
@@ -81,7 +81,7 @@
'system (using cron for instance).',
'group': 'main', 'inputlevel': 1,
}),
-
+
# email configuration
('default-recipients-mode',
{'type' : 'choice',
@@ -123,14 +123,14 @@
'group': 'pyro-server', 'inputlevel': 2,
}),
) + CubicWebConfiguration.options)
-
+
# read the schema from the database
read_application_schema = True
bootstrap_schema = True
-
+
# check user's state at login time
consider_user_state = True
-
+
# hooks registration configuration
# all hooks should be activated during normal execution
core_hooks = True
@@ -142,7 +142,7 @@
# should some hooks be deactivated during [pre|post]create script execution
free_wheel = False
-
+
# list of enables sources when sources restriction is necessary
# (eg repository initialization at least)
_enabled_sources = None
@@ -150,7 +150,7 @@
def enabled_sources(self, sourceuris=None):
self._enabled_sources = sourceuris
clear_cache(self, 'sources')
-
+
@classmethod
def schemas_lib_dir(cls):
"""application schema directory"""
@@ -172,17 +172,17 @@
else:
# no cubes
self.init_cubes(())
-
+
def write_bootstrap_cubes_file(self, cubes):
stream = file(join(self.apphome, 'bootstrap_cubes'), 'w')
stream.write('# this is a generated file only used for bootstraping\n')
stream.write('# you should not have to edit this\n')
stream.write('%s\n' % ','.join(cubes))
stream.close()
-
+
def sources_file(self):
return join(self.apphome, 'sources')
-
+
# this method has to be cached since when the server is running using a
# restricted user, this user usually don't have access to the sources
# configuration file (#16102)
@@ -196,11 +196,11 @@
return allsources
return dict((uri, config) for uri, config in allsources.items()
if uri in self._enabled_sources or uri == 'admin')
-
+
def pyro_enabled(self):
"""pyro is always enabled in standalone repository configuration"""
return True
-
+
def load_hooks(self, vreg):
hooks = {}
for path in reversed([self.apphome] + self.cubes_path()):
@@ -209,8 +209,8 @@
self.warning('application_hooks.py is deprecated, use dynamic '
'objects to register hooks (%s)', hooksfile)
context = {}
- # Use execfile rather than `load_module_from_name` because
- # the latter gets fooled by the `sys.modules` cache when
+ # Use execfile rather than `load_module_from_name` because
+ # the latter gets fooled by the `sys.modules` cache when
# loading different configurations one after the other
# (another fix would have been to do :
# sys.modules.pop('applications_hooks')
@@ -231,8 +231,8 @@
cb = hookdef.make_callback(event)
hooks.setdefault(event, {}).setdefault(ertype, []).append(cb)
return hooks
-
- def load_schema(self, expand_cubes=False, construction_mode='strict'):
+
+ def load_schema(self, expand_cubes=False, **kwargs):
from cubicweb.schema import CubicWebSchemaLoader
if expand_cubes:
# in case some new dependencies have been introduced, we have to
@@ -240,18 +240,18 @@
origcubes = self.cubes()
self._cubes = None
self.init_cubes(self.expand_cubes(origcubes))
- schema = CubicWebSchemaLoader().load(self, construction_mode=construction_mode)
+ schema = CubicWebSchemaLoader().load(self, **kwargs)
if expand_cubes:
# restaure original value
self._cubes = origcubes
return schema
-
+
def load_bootstrap_schema(self):
from cubicweb.schema import BootstrapSchemaLoader
schema = BootstrapSchemaLoader().load(self)
schema.name = 'bootstrap'
return schema
-
+
def set_sources_mode(self, sources):
if 'migration' in sources:
from cubicweb.server.sources import source_adapter
@@ -274,7 +274,7 @@
enabled_sources = sources
self._enabled_sources = enabled_sources
clear_cache(self, 'sources')
-
+
def migration_handler(self, schema=None, interactive=True,
cnx=None, repo=None, connect=True):
"""return a migration handler instance"""
--- a/server/serverctl.py Tue May 05 12:07:42 2009 +0200
+++ b/server/serverctl.py Tue May 05 17:13:37 2009 +0200
@@ -139,6 +139,8 @@
return in_memory_cnx(config, login, pwd)
except AuthenticationError:
print 'wrong user/password'
+ # reset cubes else we'll have an assertion error on next retry
+ config._cubes = None
login, pwd = manager_userpasswd()
# repository specific command handlers ########################################
--- a/server/session.py Tue May 05 12:07:42 2009 +0200
+++ b/server/session.py Tue May 05 17:13:37 2009 +0200
@@ -13,7 +13,7 @@
from rql.nodes import VariableRef, Function, ETYPE_PYOBJ_MAP, etype_from_pyobj
from yams import BASE_TYPES
-from cubicweb import RequestSessionMixIn, Binary
+from cubicweb import RequestSessionMixIn, Binary, UnknownEid
from cubicweb.dbapi import ConnectionProperties
from cubicweb.utils import make_uid
from cubicweb.server.rqlrewrite import RQLRewriter
@@ -29,7 +29,7 @@
continue
if etype in BASE_TYPES:
return True
- return False
+ return False
def _make_description(selected, args, solution):
"""return a description for a result set"""
@@ -45,7 +45,7 @@
"""tie session id, user, connections pool and other session data all
together
"""
-
+
def __init__(self, user, repo, cnxprops=None, _id=None):
super(Session, self).__init__(repo.vreg)
self.id = _id or make_uid(user.login.encode('UTF8'))
@@ -65,7 +65,7 @@
# i18n initialization
self.set_language(cnxprops.lang)
self._threaddata = threading.local()
-
+
def get_mode(self):
return getattr(self._threaddata, 'mode', 'read')
def set_mode(self, value):
@@ -78,12 +78,12 @@
def set_commit_state(self, value):
self._threaddata.commit_state = value
commit_state = property(get_commit_state, set_commit_state)
-
+
# set according to transaction mode for each query
@property
def pool(self):
return getattr(self._threaddata, 'pool', None)
-
+
# pending transaction operations
@property
def pending_operations(self):
@@ -92,7 +92,7 @@
except AttributeError:
self._threaddata.pending_operations = []
return self._threaddata.pending_operations
-
+
# rql rewriter
@property
def rql_rewriter(self):
@@ -101,7 +101,7 @@
except AttributeError:
self._threaddata._rewriter = RQLRewriter(self.repo.querier, self)
return self._threaddata._rewriter
-
+
# transaction queries data
@property
def _query_data(self):
@@ -110,7 +110,7 @@
except AttributeError:
self._threaddata._query_data = {}
return self._threaddata._query_data
-
+
def set_language(self, language):
"""i18n configuration for translation"""
vreg = self.vreg
@@ -124,42 +124,42 @@
except KeyError:
self._ = self.__ = unicode
self.lang = language
-
+
def change_property(self, prop, value):
assert prop == 'lang' # this is the only one changeable property for now
self.set_language(value)
def __str__(self):
- return '<%ssession %s (%s 0x%x)>' % (self.cnxtype, self.user.login,
+ return '<%ssession %s (%s 0x%x)>' % (self.cnxtype, self.user.login,
self.id, id(self))
def etype_class(self, etype):
"""return an entity class for the given entity type"""
return self.vreg.etype_class(etype)
-
+
def entity(self, eid):
"""return a result set for the given eid"""
return self.eid_rset(eid).get_entity(0, 0)
-
+
def _touch(self):
"""update latest session usage timestamp and reset mode to read
"""
self.timestamp = time()
self.local_perm_cache.clear()
self._threaddata.mode = 'read'
-
+
def set_pool(self):
"""the session need a pool to execute some queries"""
if self.pool is None:
self._threaddata.pool = self.repo._get_pool()
- try:
+ try:
self._threaddata.pool.pool_set(self)
except:
self.repo._free_pool(self.pool)
self._threaddata.pool = None
raise
return self._threaddata.pool
-
+
def reset_pool(self):
"""the session has no longer using its pool, at least for some time
"""
@@ -170,7 +170,7 @@
self.repo._free_pool(self.pool)
self.pool.pool_reset(self)
self._threaddata.pool = None
-
+
def system_sql(self, sql, args=None):
"""return a sql cursor on the system database"""
if not sql.split(None, 1)[0].upper() == 'SELECT':
@@ -181,26 +181,26 @@
def actual_session(self):
"""return the original parent session if any, else self"""
- return self
+ return self
# shared data handling ###################################################
-
+
def get_shared_data(self, key, default=None, pop=False):
"""return value associated to `key` in session data"""
if pop:
return self.data.pop(key, default)
else:
return self.data.get(key, default)
-
+
def set_shared_data(self, key, value, querydata=False):
"""set value associated to `key` in session data"""
if querydata:
self.set_query_data(key, value)
else:
self.data[key] = value
-
+
# request interface #######################################################
-
+
def set_entity_cache(self, entity):
# no entity cache in the server, too high risk of inconsistency
# between pre/post hooks
@@ -211,20 +211,20 @@
def base_url(self):
return self.repo.config['base-url'] or u''
-
+
def from_controller(self):
"""return the id (string) of the controller issuing the request (no
sense here, always return 'view')
"""
return 'view'
-
+
def source_defs(self):
return self.repo.source_defs()
def describe(self, eid):
"""return a tuple (type, sourceuri, extid) for the entity with id <eid>"""
return self.repo.type_and_source_from_eid(eid, self)
-
+
# db-api like interface ###################################################
def source_from_eid(self, eid):
@@ -249,7 +249,7 @@
# need shared pool set
self.set_pool()
return csession
-
+
def unsafe_execute(self, rql, kwargs=None, eid_key=None, build_descr=False,
propagate=False):
"""like .execute but with security checking disabled (this method is
@@ -266,7 +266,7 @@
def cursor(self):
"""return a rql cursor"""
return self
-
+
def execute(self, rql, kwargs=None, eid_key=None, build_descr=True,
propagate=False):
"""db-api like method directly linked to the querier execute method
@@ -276,7 +276,7 @@
"""
rset = self._execute(self, rql, kwargs, eid_key, build_descr)
return self.decorate_rset(rset, propagate)
-
+
def commit(self, reset_pool=True):
"""commit the current session's transaction"""
if self.pool is None:
@@ -317,7 +317,7 @@
self._query_data.clear()
if reset_pool:
self.reset_pool()
-
+
def rollback(self, reset_pool=True):
"""rollback the current session's transaction"""
if self.pool is None:
@@ -340,19 +340,19 @@
self._query_data.clear()
if reset_pool:
self.reset_pool()
-
+
def close(self):
"""do not close pool on session close, since they are shared now"""
self.rollback()
-
+
# transaction data/operations management ##################################
-
+
def add_query_data(self, key, value):
self._query_data.setdefault(key, []).append(value)
-
+
def set_query_data(self, key, value):
self._query_data[key] = value
-
+
def query_data(self, key, default=None, setdefault=False, pop=False):
if setdefault:
assert not pop
@@ -361,7 +361,7 @@
return self._query_data.pop(key, default)
else:
return self._query_data.get(key, default)
-
+
def add_operation(self, operation, index=None):
"""add an observer"""
assert self.commit_state != 'commit'
@@ -369,9 +369,9 @@
self.pending_operations.insert(index, operation)
else:
self.pending_operations.append(operation)
-
+
# querier helpers #########################################################
-
+
def build_description(self, rqlst, args, result):
"""build a description for a given result"""
if len(rqlst.children) == 1 and len(rqlst.children[0].solutions) == 1:
@@ -385,7 +385,7 @@
def manual_build_descr(self, rqlst, args, result):
"""build a description for a given result by analysing each row
-
+
XXX could probably be done more efficiently during execution of query
"""
# not so easy, looks for variable which changes from one solution
@@ -410,7 +410,7 @@
if not todetermine:
return [tuple(basedescription)] * len(result)
return self._build_descr(result, basedescription, todetermine)
-
+
def _build_descr(self, result, basedescription, todetermine):
description = []
etype_from_eid = self.describe
@@ -422,23 +422,23 @@
# None value inserted by an outer join, no type
row_descr[index] = None
continue
- try:
- if isfinal:
- row_descr[index] = etype_from_pyobj(value)
- else:
+ if isfinal:
+ row_descr[index] = etype_from_pyobj(value)
+ else:
+ try:
row_descr[index] = etype_from_eid(value)[0]
- except UnknownEid:
- self.critical('wrong eid in repository, should check database')
- row_descr[index] = row[index] = None
+ except UnknownEid:
+ self.critical('wrong eid %s in repository, should check database' % value)
+ row_descr[index] = row[index] = None
description.append(tuple(row_descr))
return description
-
+
class ChildSession(Session):
"""child (or internal) session are used to hijack the security system
"""
cnxtype = 'inmemory'
-
+
def __init__(self, parent_session):
self.id = None
self.is_internal_session = False
@@ -454,7 +454,7 @@
self._ = self.__ = parent_session._
# short cut to querier .execute method
self._execute = self.repo.querier.execute
-
+
@property
def super_session(self):
return self
@@ -470,7 +470,7 @@
def set_commit_state(self, value):
self.parent_session.set_commit_state(value)
commit_state = property(get_commit_state, set_commit_state)
-
+
@property
def pool(self):
return self.parent_session.pool
@@ -480,11 +480,11 @@
@property
def _query_data(self):
return self.parent_session._query_data
-
+
def set_pool(self):
"""the session need a pool to execute some queries"""
self.parent_session.set_pool()
-
+
def reset_pool(self):
"""the session has no longer using its pool, at least for some time
"""
@@ -493,19 +493,19 @@
def actual_session(self):
"""return the original parent session if any, else self"""
return self.parent_session
-
+
def commit(self, reset_pool=True):
"""commit the current session's transaction"""
self.parent_session.commit(reset_pool)
-
+
def rollback(self, reset_pool=True):
"""rollback the current session's transaction"""
self.parent_session.rollback(reset_pool)
-
+
def close(self):
"""do not close pool on session close, since they are shared now"""
self.rollback()
-
+
def user_data(self):
"""returns a dictionnary with this user's information"""
return self.parent_session.user_data()
@@ -513,14 +513,14 @@
class InternalSession(Session):
"""special session created internaly by the repository"""
-
+
def __init__(self, repo, cnxprops=None):
super(InternalSession, self).__init__(_IMANAGER, repo, cnxprops,
_id='internal')
self.cnxtype = 'inmemory'
self.is_internal_session = True
self.is_super_session = True
-
+
@property
def super_session(self):
return self
@@ -544,7 +544,7 @@
def owns(self, eid):
return True
-
+
def has_permission(self, pname, contexteid=None):
return True
--- a/skeleton/debian/rules.tmpl Tue May 05 12:07:42 2009 +0200
+++ b/skeleton/debian/rules.tmpl Tue May 05 17:13:37 2009 +0200
@@ -25,7 +25,7 @@
dh_installdirs -i
python setup.py -q install --no-compile --prefix=debian/%(distname)s/usr/
# remove generated .egg-info file
- rm -rf debian/cubicweb-comment/usr/lib/python*
+ rm -rf debian/%(distname)s/usr/lib/python*
# Build architecture-independent files here.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/data/cubes/mycube/__init__.py Tue May 05 17:13:37 2009 +0200
@@ -0,0 +1,1 @@
+"""mycube's __init__"""
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/data/cubes/mycube/__pkginfo__.py Tue May 05 17:13:37 2009 +0200
@@ -0,0 +1,1 @@
+distname = 'cubicweb-mycube'
--- a/test/unittest_cwconfig.py Tue May 05 12:07:42 2009 +0200
+++ b/test/unittest_cwconfig.py Tue May 05 17:13:37 2009 +0200
@@ -14,7 +14,7 @@
if part.startswith('cubicweb') or part == 'cubes':
return '/'.join(parts[i+1:])
raise Exception('duh? %s' % path)
-
+
class CubicWebConfigurationTC(TestCase):
def setUp(self):
self.config = ApptestConfiguration('data')
@@ -38,7 +38,7 @@
('jpl', 'email', 'file'))
self.assertEquals(self.config.reorder_cubes(('jpl', 'email', 'file')),
('jpl', 'email', 'file'))
-
+
def test_reorder_cubes_recommends(self):
from cubes.comment import __pkginfo__ as comment_pkginfo
comment_pkginfo.__recommend__ = ('file',)
@@ -55,8 +55,8 @@
('jpl', 'email', 'comment', 'file'))
finally:
comment_pkginfo.__use__ = ()
-
-
+
+
# def test_vc_config(self):
# vcconf = self.config.vc_config()
# self.assertIsInstance(vcconf['EEMAIL'], Version)
@@ -64,7 +64,7 @@
# self.assertEquals(vcconf['CW'], (2, 31, 2))
# self.assertRaises(KeyError, vcconf.__getitem__, 'CW_VERSION')
# self.assertRaises(KeyError, vcconf.__getitem__, 'CRM')
-
+
def test_expand_cubes(self):
self.assertEquals(self.config.expand_cubes(('email', 'eblog')),
['email', 'eblog', 'file'])
@@ -104,7 +104,7 @@
del cubes.file
from cubes import file
self.assertEquals(file.__path__, [abspath(join(dirname(__file__), 'data', 'cubes', 'file'))])
-
-
+
+
if __name__ == '__main__':
unittest_main()
--- a/test/unittest_entity.py Tue May 05 12:07:42 2009 +0200
+++ b/test/unittest_entity.py Tue May 05 17:13:37 2009 +0200
@@ -15,7 +15,7 @@
## self.add_entity('Tag', name=u'x')
## self.add_entity('Link', title=u'perdu', url=u'http://www.perdu.com',
## embed=False)
-
+
def test_boolean_value(self):
e = self.etype_instance('CWUser')
self.failUnless(e)
@@ -37,7 +37,7 @@
self.assertEquals(e.has_eid(), True)
e.eid = 2
self.assertEquals(e.has_eid(), True)
-
+
def test_copy(self):
self.add_entity('Tag', name=u'x')
p = self.add_entity('Personne', nom=u'toto')
@@ -50,7 +50,7 @@
self.assertEquals(len(e.ecrit_par), 1)
self.assertEquals(e.ecrit_par[0].eid, p.eid)
self.assertEquals(len(e.reverse_tags), 0)
-
+
def test_copy_with_nonmeta_composite_inlined(self):
p = self.add_entity('Personne', nom=u'toto')
oe = self.add_entity('Note', type=u'x')
@@ -61,7 +61,7 @@
e.copy_relations(oe.eid)
self.failIf(e.ecrit_par)
self.failUnless(oe.ecrit_par)
-
+
def test_copy_with_composite(self):
user = self.user()
adeleid = self.execute('INSERT EmailAddress X: X address "toto@logilab.org", U use_email X WHERE U login "admin"')[0][0]
@@ -74,7 +74,7 @@
e.copy_relations(user.eid)
self.failIf(e.use_email)
self.failIf(e.primary_email)
-
+
def test_copy_with_non_initial_state(self):
user = self.user()
eid = self.execute('INSERT CWUser X: X login "toto", X upassword %(pwd)s, X in_group G WHERE G name "users"',
@@ -110,7 +110,7 @@
self.assertEquals(len(p.related('tags', 'object', limit=2)), 2)
self.assertEquals(len(p.related('tags', 'object')), 4)
-
+
def test_fetch_rql(self):
user = self.user()
Personne = self.vreg.etype_class('Personne')
@@ -130,7 +130,7 @@
try:
# testing unknown attributes
Personne.fetch_attrs = ('bloug', 'beep')
- self.assertEquals(Personne.fetch_rql(user), 'Any X WHERE X is Personne')
+ self.assertEquals(Personne.fetch_rql(user), 'Any X WHERE X is Personne')
# testing one non final relation
Personne.fetch_attrs = ('nom', 'prenom', 'travaille')
self.assertEquals(Personne.fetch_rql(user),
@@ -179,7 +179,7 @@
# XXX
self.assertEquals(aff.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):
p = self.add_entity('Personne', nom=u'di mascio', prenom=u'adrien')
e = self.add_entity('Tag', name=u'x')
@@ -198,7 +198,7 @@
self.add_entity('Personne', nom=u'di mascio', prenom=u'gwen')
self.assertEquals(len(e.unrelated('tags', 'Personne', 'subject', limit=1)),
1)
-
+
def test_new_entity_unrelated(self):
e = self.etype_instance('CWUser')
unrelated = [r[0] for r in e.unrelated('in_group', 'CWGroup', 'subject')]
@@ -209,7 +209,7 @@
e = self.add_entity('Card', title=u'rest test', content=u'du :eid:`1:*ReST*`',
content_format=u'text/rest')
self.assertEquals(e.printable_value('content'),
- '<p>du <a class="reference" href="http://testing.fr/cubicweb/egroup/managers">*ReST*</a></p>\n')
+ '<p>du <a class="reference" href="http://testing.fr/cubicweb/cwgroup/managers">*ReST*</a></p>\n')
e['content'] = 'du <em>html</em> <ref rql="CWUser X">users</ref>'
e['content_format'] = 'text/html'
self.assertEquals(e.printable_value('content'),
@@ -237,7 +237,7 @@
e['content_format'] = 'text/cubicweb-page-template'
self.assertEquals(e.printable_value('content'),
'<h1>zou</h1>')
-
+
def test_printable_value_bytes(self):
e = self.add_entity('File', data=Binary('lambda x: 1'), data_format=u'text/x-python',
@@ -254,7 +254,7 @@
<span style="color: #C00000;">lambda</span> <span style="color: #000000;">x</span><span style="color: #0000C0;">:</span> <span style="color: #0080C0;">1</span>
</pre>
''')
-
+
e = self.add_entity('File', data=Binary('*héhéhé*'), data_format=u'text/rest',
data_encoding=u'utf-8', name=u'toto.txt')
self.assertEquals(e.printable_value('data'),
@@ -290,8 +290,8 @@
self.assertEquals(e.printable_value('content'), e['content'])
e['content'] = u'été'
self.assertEquals(e.printable_value('content'), e['content'])
-
-
+
+
def test_fulltextindex(self):
e = self.etype_instance('File')
e['name'] = 'an html file'
@@ -300,17 +300,17 @@
e['data'] = Binary('some <em>data</em>')
e['data_format'] = 'text/html'
e['data_encoding'] = 'ascii'
- self.assertEquals(set(e.get_words()),
+ self.assertEquals(set(e.get_words()),
set(['an', 'html', 'file', 'du', 'html', 'some', 'data']))
-
+
def test_nonregr_relation_cache(self):
p1 = self.add_entity('Personne', nom=u'di mascio', prenom=u'adrien')
p2 = self.add_entity('Personne', nom=u'toto')
self.execute('SET X evaluee Y WHERE X nom "di mascio", Y nom "toto"')
self.assertEquals(p1.evaluee[0].nom, "toto")
self.failUnless(not p1.reverse_evaluee)
-
+
def test_complete_relation(self):
self.execute('SET RT add_permission G WHERE RT name "wf_info_for", G name "managers"')
self.commit()
@@ -382,7 +382,7 @@
metainf['source'] = metainf['source'].copy()
metainf['source']['base-url'] = 'http://cubicweb2.com/'
self.assertEquals(note.absolute_url(), 'http://cubicweb2.com/note/%s' % note.eid)
-
+
if __name__ == '__main__':
from logilab.common.testlib import unittest_main
unittest_main()
--- a/test/unittest_rset.py Tue May 05 12:07:42 2009 +0200
+++ b/test/unittest_rset.py Tue May 05 17:13:37 2009 +0200
@@ -12,17 +12,17 @@
from cubicweb.rset import NotAnEntity, ResultSet, attr_desc_iterator
-
+
def pprelcachedict(d):
res = {}
for k, (rset, related) in d.items():
res[k] = sorted(v.eid for v in related)
return sorted(res.items())
-
+
class AttrDescIteratorTC(TestCase):
"""TestCase for cubicweb.rset.attr_desc_iterator"""
-
+
def test_relations_description(self):
"""tests relations_description() function"""
queries = {
@@ -35,7 +35,7 @@
for rql, relations in queries.items():
result = list(attr_desc_iterator(parse(rql).children[0]))
self.assertEquals((rql, result), (rql, relations))
-
+
def test_relations_description_indexed(self):
"""tests relations_description() function"""
queries = {
@@ -49,7 +49,7 @@
-class ResultSetTC(EnvBasedTC):
+class ResultSetTC(EnvBasedTC):
def setUp(self):
super(ResultSetTC, self).setUp()
@@ -67,7 +67,7 @@
params2 = dict(pair.split('=') for pair in info1[3].split('&'))
self.assertDictEquals(params1, params2)
-
+
def test_build_url(self):
req = self.request()
baseurl = req.base_url()
@@ -79,8 +79,8 @@
# '%stask/title/go' % baseurl)
# empty _restpath should not crash
self.compare_urls(req.build_url('view', _restpath=''), baseurl)
-
-
+
+
def test_resultset_build(self):
"""test basic build of a ResultSet"""
rs = ResultSet([1,2,3], 'CWGroup X', description=['CWGroup', 'CWGroup', 'CWGroup'])
@@ -102,7 +102,7 @@
self.assertEquals(rs2.get_entity(0, 0).row, 0)
self.assertEquals(rs.limit(2, offset=2).rows, [[14000, 'nico']])
self.assertEquals(rs.limit(2, offset=3).rows, [])
-
+
def test_resultset_filter(self):
rs = ResultSet([[12000, 'adim'], [13000, 'syt'], [14000, 'nico']],
@@ -112,11 +112,11 @@
rs.vreg = self.env.vreg
def test_filter(entity):
return entity.login != 'nico'
-
+
rs2 = rs.filtered_rset(test_filter)
self.assertEquals(len(rs2), 2)
self.assertEquals([login for _, login in rs2], ['adim', 'syt'])
-
+
def test_resultset_transform(self):
rs = ResultSet([[12, 'adim'], [13, 'syt'], [14, 'nico']],
'Any U,L where U is CWUser, U login L',
@@ -128,20 +128,20 @@
self.assertEquals(len(rs2), 3)
self.assertEquals(list(rs2), [['adim'],['syt'],['nico']])
-
+
def test_resultset_sort(self):
rs = ResultSet([[12000, 'adim'], [13000, 'syt'], [14000, 'nico']],
'Any U,L where U is CWUser, U login L',
description=[['CWUser', 'String']] * 3)
rs.req = self.request()
rs.vreg = self.env.vreg
-
+
rs2 = rs.sorted_rset(lambda e:e['login'])
self.assertEquals(len(rs2), 3)
self.assertEquals([login for _, login in rs2], ['adim', 'nico', 'syt'])
# make sure rs is unchanged
self.assertEquals([login for _, login in rs], ['adim', 'syt', 'nico'])
-
+
rs2 = rs.sorted_rset(lambda e:e['login'], reverse=True)
self.assertEquals(len(rs2), 3)
self.assertEquals([login for _, login in rs2], ['syt', 'nico', 'adim'])
@@ -165,7 +165,7 @@
description=[['CWUser', 'String', 'String']] * 5)
rs.req = self.request()
rs.vreg = self.env.vreg
-
+
rsets = rs.split_rset(lambda e:e['login'])
self.assertEquals(len(rsets), 3)
self.assertEquals([login for _, login,_ in rsets[0]], ['adim', 'adim'])
@@ -173,7 +173,7 @@
self.assertEquals([login for _, login,_ in rsets[2]], ['nico', 'nico'])
# make sure rs is unchanged
self.assertEquals([login for _, login,_ in rs], ['adim', 'adim', 'syt', 'nico', 'nico'])
-
+
rsets = rs.split_rset(lambda e:e['login'], return_dict=True)
self.assertEquals(len(rsets), 3)
self.assertEquals([login for _, login,_ in rsets['nico']], ['nico', 'nico'])
@@ -198,7 +198,7 @@
u'Le carrelage en 42 leçons',
u'La tarte tatin en 15 minutes',
u"L'épluchage du castor commun"])
-
+
def test_cached_syntax_tree(self):
"""make sure syntax tree is cached"""
rqlst1 = self.rset.syntax_tree()
@@ -216,21 +216,20 @@
e.complete()
self.assertEquals(e['firstname'], 'adrien')
self.assertEquals(pprelcachedict(e._related_cache), [])
-
+
def test_get_entity_advanced(self):
self.add_entity('Bookmark', title=u'zou', path=u'/view')
self.execute('SET X bookmarked_by Y WHERE X is Bookmark, Y login "anon"')
rset = self.execute('Any X,Y,XT,YN WHERE X bookmarked_by Y, X title XT, Y login YN')
-
+
e = rset.get_entity(0, 0)
self.assertEquals(e.row, 0)
self.assertEquals(e.col, 0)
self.assertEquals(e['title'], 'zou')
self.assertRaises(KeyError, e.__getitem__, 'path')
- with traced_selection():
- self.assertEquals(e.view('text'), 'zou')
+ self.assertEquals(e.view('text'), 'zou')
self.assertEquals(pprelcachedict(e._related_cache), [])
-
+
e = rset.get_entity(0, 1)
self.assertEquals(e.row, 0)
self.assertEquals(e.col, 1)
@@ -243,7 +242,7 @@
self.assertEquals(e.view('text'), 'anon')
self.assertEquals(pprelcachedict(e._related_cache),
[])
-
+
self.assertRaises(NotAnEntity, rset.get_entity, 0, 2)
self.assertRaises(NotAnEntity, rset.get_entity, 0, 3)
@@ -274,7 +273,7 @@
self.assertEquals(s['name'], 'activated')
self.assertRaises(KeyError, s.__getitem__, 'description')
-
+
def test_get_entity_cache_with_left_outer_join(self):
eid = self.execute('INSERT CWUser E: E login "joe", E upassword "joe", E in_group G '
'WHERE G name "users"')[0][0]
@@ -287,7 +286,7 @@
cached = e.related_cache('primary_email', 'subject', False)
self.assertIsInstance(cached, ResultSet)
self.assertEquals(cached.rowcount, 0)
-
+
def test_get_entity_union(self):
e = self.add_entity('Bookmark', title=u'manger', path=u'path')
@@ -303,14 +302,14 @@
self.assertEquals(entity.id, etype)
attr = etype == 'Bookmark' and 'title' or 'name'
self.assertEquals(entity[attr], n)
-
+
def test_related_entity_optional(self):
e = self.add_entity('Bookmark', title=u'aaaa', path=u'path')
rset = self.execute('Any B,U,L WHERE B bookmarked_by U?, U login L')
entity, rtype = rset.related_entity(0, 2)
self.assertEquals(entity, None)
self.assertEquals(rtype, None)
-
+
def test_related_entity_union_subquery(self):
e = self.add_entity('Bookmark', title=u'aaaa', path=u'path')
rset = self.execute('Any X,N ORDERBY N WITH X,N BEING '
@@ -330,7 +329,7 @@
entity, rtype = rset.related_entity(0, 1)
self.assertEquals(entity.eid, e.eid)
self.assertEquals(rtype, 'title')
-
+
def test_entities(self):
rset = self.execute('Any U,G WHERE U in_group G')
# make sure we have at least one element
@@ -340,7 +339,7 @@
self.assertEquals(set(e.e_schema.type for e in rset.entities(1)),
set(['CWGroup',]))
- def test_printable_rql(self):
+ def test_printable_rql(self):
rset = self.execute(u'CWEType X WHERE X final FALSE, X meta FALSE')
self.assertEquals(rset.printable_rql(),
'Any X WHERE X final FALSE, X meta FALSE, X is CWEType')
@@ -351,7 +350,7 @@
self.assertEquals(rset.searched_text(), 'foobar')
rset = self.execute(u'Any X WHERE X has_text %(text)s', {'text' : 'foo'})
self.assertEquals(rset.searched_text(), 'foo')
-
-
+
+
if __name__ == '__main__':
unittest_main()
--- a/test/unittest_selectors.py Tue May 05 12:07:42 2009 +0200
+++ b/test/unittest_selectors.py Tue May 05 17:13:37 2009 +0200
@@ -9,7 +9,7 @@
from cubicweb.devtools.testlib import EnvBasedTC
from cubicweb.vregistry import Selector, AndSelector, OrSelector
-from cubicweb.selectors import implements
+from cubicweb.selectors import implements, match_user_groups
from cubicweb.interfaces import IDownloadable
from cubicweb.web import action
@@ -109,6 +109,7 @@
id = 'yo'
category = 'foo'
__select__ = match_user_groups('owners')
+ self.vreg._loadedmods[__name__] = {}
self.vreg.register_vobject_class(SomeAction)
self.failUnless(SomeAction in self.vreg['actions']['yo'], self.vreg['actions'])
try:
@@ -117,16 +118,16 @@
self.login('john')
# it should not be possible to use SomeAction not owned objects
rset, req = self.env.get_rset_and_req('Any G WHERE G is CWGroup, G name "managers"')
- self.failIf('foo' in self.pactions(req, rset))
+ self.failIf('yo' in dict(self.pactions(req, rset)))
# insert a new card, and check that we can use SomeAction on our object
self.execute('INSERT Card C: C title "zoubidou"')
self.commit()
rset, req = self.env.get_rset_and_req('Card C WHERE C title "zoubidou"')
- self.failUnless('foo' in self.pactions(req, rset))
+ self.failUnless('yo' in dict(self.pactions(req, rset)), self.pactions(req, rset))
# make sure even managers can't use the action
self.restore_connection()
rset, req = self.env.get_rset_and_req('Card C WHERE C title "zoubidou"')
- self.failIf('foo' in self.pactions(req, rset))
+ self.failIf('yo' in dict(self.pactions(req, rset)))
finally:
del self.vreg[SomeAction.__registry__][SomeAction.id]
--- a/test/unittest_vregistry.py Tue May 05 12:07:42 2009 +0200
+++ b/test/unittest_vregistry.py Tue May 05 17:13:37 2009 +0200
@@ -6,15 +6,16 @@
from cubicweb.vregistry import VObject
from cubicweb.cwvreg import CubicWebRegistry, UnknownProperty
from cubicweb.devtools import TestServerConfiguration
-from cubicweb.entities.lib import Card
from cubicweb.interfaces import IMileStone
+from cubes.card.entities import Card
+
class YesSchema:
def __contains__(self, something):
return True
WEBVIEWSDIR = join(BASE, 'web', 'views')
-
+
class VRegistryTC(TestCase):
def setUp(self):
@@ -22,24 +23,26 @@
self.vreg = CubicWebRegistry(config)
config.bootstrap_cubes()
self.vreg.schema = config.load_schema()
-
+
def test_load(self):
self.vreg.init_registration([WEBVIEWSDIR])
- self.vreg.load_file(join(WEBVIEWSDIR, 'euser.py'), 'cubicweb.web.views.euser')
+ self.vreg.load_file(join(WEBVIEWSDIR, 'cwuser.py'), 'cubicweb.web.views.cwuser')
self.vreg.load_file(join(WEBVIEWSDIR, 'baseviews.py'), 'cubicweb.web.views.baseviews')
fpvc = [v for v in self.vreg.registry_objects('views', 'primary')
- if v.__module__ == 'cubicweb.web.views.euser'][0]
+ if v.__module__ == 'cubicweb.web.views.cwuser'][0]
fpv = fpvc(None, None)
# don't want a TypeError due to super call
self.assertRaises(AttributeError, fpv.render_entity_attributes, None, None)
def test_load_interface_based_vojects(self):
self.vreg.init_registration([WEBVIEWSDIR])
+ self.vreg.load_file(join(BASE, 'entities', '__init__.py'), 'cubicweb.entities.__init__')
self.vreg.load_file(join(WEBVIEWSDIR, 'idownloadable.py'), 'cubicweb.web.views.idownloadable')
- self.vreg.load_file(join(WEBVIEWSDIR, 'baseviews.py'), 'cubicweb.web.views.baseviews')
- # check loading baseviews after idownloadable isn't kicking interface based views
+ self.vreg.load_file(join(WEBVIEWSDIR, 'primary.py'), 'cubicweb.web.views.primary')
self.assertEquals(len(self.vreg['views']['primary']), 2)
-
+ self.vreg.initialization_completed()
+ self.assertEquals(len(self.vreg['views']['primary']), 1)
+
def test___selectors__compat(self):
myselector1 = lambda *args: 1
myselector2 = lambda *args: 1
@@ -63,10 +66,11 @@
self.vreg.reset()
self.vreg._loadedmods[__name__] = {}
self.vreg.register_vobject_class(MyCard)
- self.vreg.register_objects([join(BASE, 'web', 'views', 'iprogress.py')])
+ self.vreg.register_objects([join(BASE, 'entities', '__init__.py'),
+ join(BASE, 'web', 'views', 'iprogress.py')])
# check progressbar isn't kicked
self.assertEquals(len(self.vreg['views']['progressbar']), 1)
-
+
if __name__ == '__main__':
unittest_main()
--- a/web/__init__.py Tue May 05 12:07:42 2009 +0200
+++ b/web/__init__.py Tue May 05 17:13:37 2009 +0200
@@ -7,10 +7,15 @@
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
+_ = unicode
-from cubicweb.web._exceptions import *
+from decimal import Decimal
+from datetime import datetime, date, timedelta
+from simplejson import dumps
-_ = unicode
+from cubicweb.common.uilib import urlquote
+from cubicweb.web._exceptions import *
+
INTERNAL_FIELD_VALUE = '__cubicweb_internal_field__'
@@ -37,3 +42,44 @@
# XXX deprecated
FACETTES = set()
+
+
+
+def json_dumps(value):
+ if isinstance(value, Decimal):
+ value = float(value)
+ elif isinstance(value, (date, datetime)):
+ value = value.strftime('%Y-%m-%d %H:%M')
+ elif isinstance(value, timedelta):
+ value = (value.days * 24*60*60) + value.seconds
+ try:
+ return dumps(value)
+ except TypeError:
+ return dumps(repr(value))
+
+def jsonize(function):
+ def newfunc(*args, **kwargs):
+ return json_dumps(function(*args, **kwargs))
+ return newfunc
+
+def ajax_replace_url(nodeid, rql, vid=None, swap=False, **extraparams):
+ """builds a replacePageChunk-like url
+ >>> ajax_replace_url('foo', 'Person P')
+ "javascript: replacePageChunk('foo', 'Person%20P');"
+ >>> ajax_replace_url('foo', 'Person P', 'oneline')
+ "javascript: replacePageChunk('foo', 'Person%20P', 'oneline');"
+ >>> ajax_replace_url('foo', 'Person P', 'oneline', name='bar', age=12)
+ "javascript: replacePageChunk('foo', 'Person%20P', 'oneline', {'age':12, 'name':'bar'});"
+ >>> ajax_replace_url('foo', 'Person P', name='bar', age=12)
+ "javascript: replacePageChunk('foo', 'Person%20P', 'null', {'age':12, 'name':'bar'});"
+ """
+ params = [repr(nodeid), repr(urlquote(rql))]
+ if extraparams and not vid:
+ params.append("'null'")
+ elif vid:
+ params.append(repr(vid))
+ if extraparams:
+ params.append(json_dumps(extraparams))
+ if swap:
+ params.append('true')
+ return "javascript: replacePageChunk(%s);" % ', '.join(params)
--- a/web/component.py Tue May 05 12:07:42 2009 +0200
+++ b/web/component.py Tue May 05 17:13:37 2009 +0200
@@ -51,7 +51,7 @@
context = 'navcontentbottom' # 'footer' | 'header' | 'incontext'
def call(self, view=None):
- return self.cell_call(0, 0, view)
+ return self.cell_call(0, 0, view=view)
def cell_call(self, row, col, view=None):
raise NotImplementedError()
--- a/web/controller.py Tue May 05 12:07:42 2009 +0200
+++ b/web/controller.py Tue May 05 17:13:37 2009 +0200
@@ -10,7 +10,7 @@
import datetime
from cubicweb import typed_eid
-from cubicweb.utils import strptime
+from cubicweb.utils import strptime, todate, todatetime
from cubicweb.selectors import yes, require_group_compat
from cubicweb.appobject import AppObject
from cubicweb.web import LOGGER, Redirect, RequestError
@@ -116,7 +116,7 @@
if etype == 'Datetime':
format = self.req.property_value('ui.datetime-format')
try:
- return strptime(value, format)
+ return todatetime(strptime(value, format))
except:
pass
elif etype == 'Time':
@@ -124,13 +124,15 @@
try:
# (adim) I can't find a way to parse a Time with a custom format
date = strptime(value, format) # this returns a DateTime
- return datetime.timedelta(0, date.hour *60*60 + date.minute*60 + date.second, 0)
+ return datetime.time(date.hour, date.minute, date.second)
except:
raise ValueError('can\'t parse %r (expected %s)' % (value, format))
try:
format = self.req.property_value('ui.date-format')
dt = strptime(value, format)
- return datetime.date(dt.year, dt.month, dt.day)
+ if etype == 'Datetime':
+ return todatetime(dt)
+ return todate(dt)
except:
raise ValueError('can\'t parse %r (expected %s)' % (value, format))
--- a/web/data/cubicweb.preferences.css Tue May 05 12:07:42 2009 +0200
+++ b/web/data/cubicweb.preferences.css Tue May 05 17:13:37 2009 +0200
@@ -5,12 +5,46 @@
* :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
*/
-.componentTitle{
+
+table.preferences td{
+ padding: 0 0.5em 1em;
+ }
+
+fieldset.preferences{
+ border : 1px solid #CFCEB7;
+ margin:1em 0;
+ padding:0 1em 1em;
+}
+
+div.preffield {
+ margin-bottom: 0.8em ;
+}
+
+/*
+div.preffield label{
+ font-size:110%
+ }
+*/
+
+div.prefinput{
+ margin:.3em 0;
+}
+
+div.componentLink{
+ margin-top:0.3em;
+ }
+
+a.componentTitle{
font-weight:bold;
- color: #ff7700;
- padding:0px 4px;
+ color: #000;
+ }
+
+a.componentTitle:visited{
+ color: #000;
}
+
+
h2.propertiesform a{
display:block;
margin: 10px 0px 6px 0px;
@@ -26,3 +60,56 @@
background-color:#cfceb7;
text-decoration:none;
}
+
+div.prefinput select.changed,
+div.prefinput input.changed{
+ background:#eeedd9;
+ border: 1px solid #eeedd9;
+}
+
+div.prefinput select,
+div.prefinput input{
+ background:#fff;
+ border: 1px solid #CFCEB7;
+}
+
+.prefinput input.error {
+ background:transparent url(error.png) no-repeat scroll 100% 50% !important;
+}
+
+
+div.formsg{
+ font-weight:bold;
+ margin:0.5em 0px;
+ }
+
+
+div.formsg .critical{
+ color:red;
+ padding-left:20px;
+ background:#fff url(critical.png) no-repeat;
+ }
+
+div.formsg .message{
+ color : green;
+}
+
+.helper{
+ font-size: 96%;
+ color: #555544;
+ padding:0;
+}
+
+div.prefinput .helper:hover {
+ color: #000;
+ cursor: default;
+}
+
+.error{
+ color:red;
+ padding-right:1em;
+ }
+
+div.openlink{
+ display:inline;
+ }
\ No newline at end of file
--- a/web/data/cubicweb.preferences.js Tue May 05 12:07:42 2009 +0200
+++ b/web/data/cubicweb.preferences.js Tue May 05 17:13:37 2009 +0200
@@ -3,8 +3,176 @@
* XXX whenever used outside of preferences, don't forget to
* move me in a more appropriate place
*/
-function toggle_and_remember_visibility(elemId, cookiename) {
+
+function toggleVisibility(elemId, cookiename) {
+ _clearPreviousMessages();
jqNode(elemId).toggleClass('hidden');
asyncRemoteExec('set_cookie', cookiename,
jQuery('#' + elemId).attr('class'));
}
+
+function closeFieldset(fieldsetid){
+ var linklabel = _('open all');
+ var linkhref = 'javascript:openFieldset("' +fieldsetid + '")'
+ _toggleFieldset(fieldsetid, 1, linklabel, linkhref)
+}
+
+function openFieldset(fieldsetid){
+ var linklabel = _('close all');
+ var linkhref = 'javascript:closeFieldset("'+ fieldsetid + '")'
+ _toggleFieldset(fieldsetid, 0, linklabel, linkhref)
+}
+
+
+function _toggleFieldset(fieldsetid, closeaction, linklabel, linkhref){
+ jQuery('#'+fieldsetid).find('div.openlink').each(function(){
+ var link = A({'href' : "javascript:noop();",
+ 'onclick' : linkhref},
+ linklabel)
+ jQuery(this).empty().append(link);
+ });
+ jQuery('#'+fieldsetid).find('fieldset[id]').each(function(){
+ var fieldset = jQuery(this);
+ if(closeaction){
+ fieldset.addClass('hidden')
+ }else{
+ fieldset.removeClass('hidden');
+ linkLabel = (_('open all'));
+ }
+ });
+}
+
+function validatePrefsForm(formid){
+ var form = getNode(formid);
+ freezeFormButtons(formid);
+ try {
+ var d = _sendForm(formid, null);
+ } catch (ex) {
+ log('got exception', ex);
+ return false;
+ }
+ function _callback(result, req) {
+ _clearPreviousMessages();
+ _clearPreviousErrors(formid);
+ // success
+ if(result[0]){
+ return submitSucces(formid)
+ }
+ // Failures
+ unfreezeFormButtons(formid);
+ var descr = result[1];
+ if (!isArrayLike(descr) || descr.length != 2) {
+ log('got strange error :', descr);
+ updateMessage(descr);
+ return ;
+ }
+ _displayValidationerrors(formid, descr[0], descr[1]);
+ var dom = DIV({'class':'critical'},
+ _("please correct errors below"));
+ jQuery(form).find('div.formsg').empty().append(dom);
+ updateMessage(_(""));
+ return false;
+ }
+ d.addCallback(_callback);
+ return false;
+}
+
+function submitSucces(formid){
+ var form = jQuery('#'+formid);
+ setCurrentValues(form);
+ var dom = DIV({'class':'message'},
+ _("changes applied"));
+ jQuery(form).find('div.formsg').empty().append(dom);
+ jQuery(form).find('input').removeClass('changed');
+ checkValues(form, true);
+ return;
+}
+
+function _clearPreviousMessages() {
+ jQuery('div#appMsg').addClass('hidden');
+ jQuery('div.formsg').empty();
+}
+
+function _clearPreviousErrors(formid) {
+ jQuery('#' + formid + ' span.error').remove();
+}
+
+
+function checkValues(form, success){
+ var unfreezeButtons = false;
+ jQuery(form).find('select').each(function () {
+ unfreezeButtons = _checkValue(jQuery(this), unfreezeButtons);
+ });
+ jQuery(form).find('[type=text]').each(function () {
+ unfreezeButtons = _checkValue(jQuery(this), unfreezeButtons);
+ });
+ jQuery(form).find('input[type=radio]').each(function () {
+ if (jQuery(this).attr('checked')){
+ unfreezeButtons = _checkValue(jQuery(this), unfreezeButtons);
+ }
+ });
+
+ if (unfreezeButtons){
+ unfreezeFormButtons(form.attr('id'));
+ }else{
+ if (!success){
+ _clearPreviousMessages();
+ }
+ _clearPreviousErrors(form.attr('id'));
+ freezeFormButtons(form.attr('id'));
+ }
+}
+
+function _checkValue(input, unfreezeButtons){
+ var currentValueInput = jQuery("input[id=current-" + input.attr('name') + "]");
+ if (currentValueInput.attr('value') != input.attr('value')){
+ input.addClass('changed');
+ unfreezeButtons = true;
+ }else{
+ input.removeClass('changed');
+ jQuery("span[id=err-" + input.attr('id') + "]").remove();
+ }
+ input.removeClass('error');
+ return unfreezeButtons
+}
+
+
+function setCurrentValues(form){
+ jQuery(form).find('input[id^=current-value]').each(function () {
+ var currentValueInput = jQuery(this);
+ var name = currentValueInput.attr('id').split('-')[1];
+ jQuery(form).find("[name=" + name + "]").each(function (){
+ var input = jQuery(this);
+ if(input.attr('type')=='radio'){
+ if(input.attr('checked')){
+ log(input.attr('value'));
+ currentValueInput.attr('value', input.attr('value'));
+ }
+ }else{
+ currentValueInput.attr('value', input.attr('value'));
+ }
+ });
+ });
+}
+
+
+function initEvents(){
+ jQuery('form').each(function() {
+ var form = jQuery(this);
+ freezeFormButtons(form.attr('id'));
+ form.find('input[type=text]').keyup(function(){
+ checkValues(form);
+ });
+ form.find('input[type=radio]').change(function(){
+ checkValues(form);
+ });
+ form.find('select').change(function(){
+ checkValues(form);
+ });
+ });
+}
+
+$(document).ready(function() {
+ initEvents();
+});
+
--- a/web/form.py Tue May 05 12:07:42 2009 +0200
+++ b/web/form.py Tue May 05 17:13:37 2009 +0200
@@ -20,7 +20,7 @@
from cubicweb.web.controller import NAV_FORM_PARAMETERS
from cubicweb.web.formfields import (Field, StringField, RelationField,
HiddenInitialValueField)
-from cubicweb.web.formrenderers import FormRenderer
+from cubicweb.web import formrenderers
from cubicweb.web import formwidgets as fwdgs
class FormViewMixIn(object):
@@ -220,6 +220,7 @@
__registry__ = 'forms'
__select__ = yes()
+ renderer_cls = formrenderers.FormRenderer
is_subform = False
# attributes overrideable through __init__
@@ -319,7 +320,7 @@
"""render this form, using the renderer given in args or the default
FormRenderer()
"""
- renderer = values.pop('renderer', FormRenderer())
+ renderer = values.pop('renderer', self.renderer_cls())
return renderer.render(self, values)
def form_build_context(self, rendervalues=None):
@@ -429,7 +430,7 @@
msg = kwargs.pop('submitmsg', None)
super(EntityFieldsForm, self).__init__(*args, **kwargs)
if self.edited_entity is None:
- self.edited_entity = self.complete_entity(self.row, self.col)
+ self.edited_entity = self.complete_entity(self.row or 0, self.col or 0)
self.form_add_hidden('__type', eidparam=True)
self.form_add_hidden('eid')
if msg is not None:
--- a/web/formrenderers.py Tue May 05 12:07:42 2009 +0200
+++ b/web/formrenderers.py Tue May 05 17:13:37 2009 +0200
@@ -149,6 +149,7 @@
if isinstance(field, HiddenInitialValueField):
field = field.visible_field
return (self.display_fields is None
+ or field.name in form.internal_fields
or (field.name, field.role) in self.display_fields
or (field.name, field.role) in form.internal_fields)
@@ -327,7 +328,7 @@
super(EntityFormRenderer, self).render_buttons(w, form)
def relations_form(self, w, form):
- srels_by_cat = form.srelations_by_category(('generic', 'metadata'), 'add')
+ srels_by_cat = form.srelations_by_category('generic', 'add')
if not srels_by_cat:
return u''
req = form.req
--- a/web/formwidgets.py Tue May 05 12:07:42 2009 +0200
+++ b/web/formwidgets.py Tue May 05 17:13:37 2009 +0200
@@ -9,7 +9,7 @@
from datetime import date
from cubicweb.common import tags
-from cubicweb.web import stdmsgs
+from cubicweb.web import INTERNAL_FIELD_VALUE, stdmsgs
class FieldWidget(object):
--- a/web/test/unittest_controller.py Tue May 05 12:07:42 2009 +0200
+++ b/web/test/unittest_controller.py Tue May 05 17:13:37 2009 +0200
@@ -9,13 +9,22 @@
from cubicweb.devtools import apptest
class BaseControllerTC(apptest.ControllerTC):
- def test_parse_datetime(self):
- self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24 12:18'), datetime)
- self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24'), datetime)
- self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24 12:18', 'Datetime'), datetime)
- self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24', 'Datetime'), datetime)
- self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24', 'Date'), date)
- self.assertIsInstance(self.ctrl.parse_datetime('12:18', 'Time'), time)
+
+ def test_parse_datetime_ok(self):
+ self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24 12:18'),
+ datetime)
+ self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24'),
+ date)
+ self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24 12:18', 'Datetime'),
+ datetime)
+ self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24', 'Datetime'),
+ datetime)
+ self.assertIsInstance(self.ctrl.parse_datetime('2006/06/24', 'Date'),
+ date)
+ self.assertIsInstance(self.ctrl.parse_datetime('12:18', 'Time'),
+ time)
+
+ def test_parse_datetime_ko(self):
self.assertRaises(ValueError,
self.ctrl.parse_datetime, '2006/06/24 12:188', 'Datetime')
self.assertRaises(ValueError,
@@ -28,6 +37,6 @@
self.ctrl.parse_datetime, '2006/06/240', 'Date')
self.assertRaises(ValueError,
self.ctrl.parse_datetime, '12:188', 'Time')
-
+
if __name__ == '__main__':
unittest_main()
--- a/web/test/unittest_form.py Tue May 05 12:07:42 2009 +0200
+++ b/web/test/unittest_form.py Tue May 05 17:13:37 2009 +0200
@@ -108,35 +108,35 @@
def test_richtextfield_1(self):
self.req.use_fckeditor = lambda: False
- self._test_richtextfield('''<select name="description_format:%(eid)s" size="1" id="description_format:%(eid)s" tabindex="0">
+ self._test_richtextfield('''<select id="description_format:%(eid)s" name="description_format:%(eid)s" size="1" tabindex="0">
<option value="text/cubicweb-page-template">text/cubicweb-page-template</option>
<option value="text/html">text/html</option>
<option value="text/plain">text/plain</option>
<option selected="selected" value="text/rest">text/rest</option>
-</select><textarea rows="5" name="description:564" onkeypress="autogrow(this)" cols="60" id="description:564" tabindex="1"/>''')
+</select><textarea cols="60" id="description:%(eid)s" name="description:%(eid)s" onkeypress="autogrow(this)" rows="5" tabindex="1"/>''')
def test_richtextfield_2(self):
self.req.use_fckeditor = lambda: True
- self._test_richtextfield('<input type="hidden" name="description_format:%(eid)s" value="text/rest"/><textarea rows="20" name="description:564" onkeypress="autogrow(this)" cols="80" cubicweb:type="wysiwyg" id="description:564" tabindex="0"/>')
+ self._test_richtextfield('<input name="description_format:%(eid)s" type="hidden" value="text/rest"/><textarea cols="80" cubicweb:type="wysiwyg" id="description:%(eid)s" name="description:%(eid)s" onkeypress="autogrow(this)" rows="20" tabindex="0"/>')
def test_filefield(self):
class FFForm(EntityFieldsForm):
data = FileField(format_field=StringField(name='data_format'),
encoding_field=StringField(name='data_encoding'))
- file = self.add_entity('File', name=u"pouet.txt",
+ file = self.add_entity('File', name=u"pouet.txt", data_encoding=u'UTF-8',
data=Binary('new widgets system'))
form = FFForm(self.req, redirect_path='perdu.com', entity=file)
self.assertTextEquals(self._render_entity_field('data', form),
- '''<input id="data:%(eid)s" type="file" name="data:%(eid)s" value="" tabindex="0"/>
+ '''<input id="data:%(eid)s" name="data:%(eid)s" tabindex="0" type="file" value=""/>
<a href="javascript: toggleVisibility('data:%(eid)s-advanced')" title="show advanced fields"><img src="http://testing.fr/cubicweb/data/puce_down.png" alt="show advanced fields"/></a>
<div id="data:%(eid)s-advanced" class="hidden">
-<label for="data_format:%(eid)s">data_format</label><input id="data_format:%(eid)s" type="text" name="data_format:%(eid)s" value="text/plain" tabindex="1"/><br/><br/>
-<label for="data_encoding:%(eid)s">data_encoding</label><input id="data_encoding:%(eid)s" type="text" name="data_encoding:%(eid)s" value="UTF-8" tabindex="2"/><br/><br/>
+<label for="data_format:%(eid)s">data_format</label><input id="data_format:%(eid)s" name="data_format:%(eid)s" tabindex="1" type="text" value="text/plain"/><br/><br/>
+<label for="data_encoding:%(eid)s">data_encoding</label><input id="data_encoding:%(eid)s" name="data_encoding:%(eid)s" tabindex="2" type="text" value="UTF-8"/><br/><br/>
</div>
<br/>
-<input type="checkbox" name="data:%(eid)s__detach"/>
+<input name="data:%(eid)s__detach" type="checkbox"/>
detach attached file
''' % {'eid': file.eid})
@@ -149,21 +149,21 @@
return 'ascii'
def form_field_format(self, field):
return 'text/plain'
- file = self.add_entity('File', name=u"pouet.txt",
+ file = self.add_entity('File', name=u"pouet.txt", data_encoding=u'UTF-8',
data=Binary('new widgets system'))
form = EFFForm(self.req, redirect_path='perdu.com', entity=file)
self.assertTextEquals(self._render_entity_field('data', form),
- '''<input id="data:%(eid)s" type="file" name="data:%(eid)s" value="" tabindex="0"/>
+ '''<input id="data:%(eid)s" name="data:%(eid)s" tabindex="0" type="file" value=""/>
<a href="javascript: toggleVisibility('data:%(eid)s-advanced')" title="show advanced fields"><img src="http://testing.fr/cubicweb/data/puce_down.png" alt="show advanced fields"/></a>
<div id="data:%(eid)s-advanced" class="hidden">
-<label for="data_format:%(eid)s">data_format</label><input id="data_format:%(eid)s" type="text" name="data_format:%(eid)s" value="text/plain" tabindex="1"/><br/><br/>
-<label for="data_encoding:%(eid)s">data_encoding</label><input id="data_encoding:%(eid)s" type="text" name="data_encoding:%(eid)s" value="UTF-8" tabindex="2"/><br/><br/>
+<label for="data_format:%(eid)s">data_format</label><input id="data_format:%(eid)s" name="data_format:%(eid)s" tabindex="1" type="text" value="text/plain"/><br/><br/>
+<label for="data_encoding:%(eid)s">data_encoding</label><input id="data_encoding:%(eid)s" name="data_encoding:%(eid)s" tabindex="2" type="text" value="UTF-8"/><br/><br/>
</div>
<br/>
-<input type="checkbox" name="data:%(eid)s__detach"/>
+<input name="data:%(eid)s__detach" type="checkbox"/>
detach attached file
<p><b>You can either submit a new file using the browse button above, or choose to remove already uploaded file by checking the "detach attached file" check-box, or edit file content online with the widget below.</b></p>
-<textarea tabindex="3" rows="20" cols="80" name="data:%(eid)s" onkeypress="autogrow(this)">new widgets system</textarea>''' % {'eid': file.eid})
+<textarea cols="80" name="data:%(eid)s" onkeypress="autogrow(this)" rows="20" tabindex="3">new widgets system</textarea>''' % {'eid': file.eid})
def test_passwordfield(self):
@@ -171,9 +171,9 @@
upassword = StringField(widget=PasswordInput)
form = PFForm(self.req, redirect_path='perdu.com', entity=self.entity)
self.assertTextEquals(self._render_entity_field('upassword', form),
- '''<input id="upassword:%(eid)s" type="password" name="upassword:%(eid)s" value="__cubicweb_internal_field__" tabindex="0"/>
+ '''<input id="upassword:%(eid)s" name="upassword:%(eid)s" tabindex="0" type="password" value="__cubicweb_internal_field__"/>
<br/>
-<input type="password" name="upassword-confirm:%(eid)s" value="__cubicweb_internal_field__" tabindex="0"/>
+<input name="upassword-confirm:%(eid)s" tabindex="0" type="password" value="__cubicweb_internal_field__"/>
<span class="emphasis">confirm password</span>''' % {'eid': self.entity.eid})
--- a/web/test/unittest_formfields.py Tue May 05 12:07:42 2009 +0200
+++ b/web/test/unittest_formfields.py Tue May 05 17:13:37 2009 +0200
@@ -13,7 +13,7 @@
schema = config.load_schema()
state_schema = schema['State']
cwuser_schema = schema['CWUser']
-file_schema.schema = schema['File']
+file_schema = schema['File']
class GuessFieldTC(TestCase):
--- a/web/test/unittest_magicsearch.py Tue May 05 12:07:42 2009 +0200
+++ b/web/test/unittest_magicsearch.py Tue May 05 17:13:37 2009 +0200
@@ -33,7 +33,7 @@
class QueryTranslatorTC(EnvBasedTC):
"""test suite for QueryTranslatorTC"""
-
+
def setUp(self):
super(QueryTranslatorTC, self).setUp()
self.req = self.env.create_request()
@@ -83,7 +83,7 @@
self.assertEquals(translate(u'prénom', eschema), "firstname")
self.assertEquals(translate(u'nom', eschema), 'surname')
#self.assert_(translate(u'nom') in ('name', 'surname'))
- eschema = self.schema.eschema('EmailAddress')
+ eschema = self.schema.eschema('EmailAddress')
self.assertEquals(translate(u'adresse', eschema), "address")
self.assertEquals(translate(u'nom', eschema), 'alias')
# should fail if the name is not an attribute for the given entity schema
@@ -96,9 +96,9 @@
self.assertEquals(transform('123'),
('Any X WHERE X eid %(x)s', {'x': 123}, 'x'))
self.assertEquals(transform('CWUser'),
- ('CWUser E',))
+ ('CWUser C',))
self.assertEquals(transform('Utilisateur'),
- ('CWUser E',))
+ ('CWUser C',))
self.assertEquals(transform('Adresse'),
('EmailAddress E',))
self.assertEquals(transform('adresse'),
@@ -111,9 +111,9 @@
self.assertEquals(transform('CWUser', 'E'),
("CWUser E",))
self.assertEquals(transform('CWUser', 'Smith'),
- ('CWUser E WHERE E has_text %(text)s', {'text': 'Smith'}))
+ ('CWUser C WHERE C has_text %(text)s', {'text': 'Smith'}))
self.assertEquals(transform('utilisateur', 'Smith'),
- ('CWUser E WHERE E has_text %(text)s', {'text': 'Smith'}))
+ ('CWUser C WHERE C has_text %(text)s', {'text': 'Smith'}))
self.assertEquals(transform(u'adresse', 'Logilab'),
('EmailAddress E WHERE E has_text %(text)s', {'text': 'Logilab'}))
self.assertEquals(transform(u'adresse', 'Logi%'),
@@ -125,22 +125,22 @@
"""tests the 'three words shortcut queries'"""
transform = self.proc._three_words_query
self.assertEquals(transform('utilisateur', u'prénom', 'cubicweb'),
- ('CWUser E WHERE E firstname %(text)s', {'text': 'cubicweb'}))
+ ('CWUser C WHERE C firstname %(text)s', {'text': 'cubicweb'}))
self.assertEquals(transform('utilisateur', 'nom', 'cubicweb'),
- ('CWUser E WHERE E surname %(text)s', {'text': 'cubicweb'}))
+ ('CWUser C WHERE C surname %(text)s', {'text': 'cubicweb'}))
self.assertEquals(transform(u'adresse', 'nom', 'cubicweb'),
('EmailAddress E WHERE E alias %(text)s', {'text': 'cubicweb'}))
self.assertEquals(transform('EmailAddress', 'nom', 'cubicweb'),
- ('EmailAddress E WHERE E alias %(text)s', {'text': 'cubicweb'}))
+ ('EmailAddress E WHERE E alias %(text)s', {'text': 'cubicweb'}))
self.assertEquals(transform('utilisateur', u'prénom', 'cubicweb%'),
- ('CWUser E WHERE E firstname LIKE %(text)s', {'text': 'cubicweb%'}))
+ ('CWUser C WHERE C firstname LIKE %(text)s', {'text': 'cubicweb%'}))
# expanded shortcuts
self.assertEquals(transform('CWUser', 'use_email', 'Logilab'),
- ('CWUser E WHERE E use_email E1, E1 has_text %(text)s', {'text': 'Logilab'}))
+ ('CWUser C WHERE C use_email C1, C1 has_text %(text)s', {'text': 'Logilab'}))
self.assertEquals(transform('CWUser', 'use_email', '%Logilab'),
- ('CWUser E WHERE E use_email E1, E1 alias LIKE %(text)s', {'text': '%Logilab'}))
+ ('CWUser C WHERE C use_email C1, C1 alias LIKE %(text)s', {'text': '%Logilab'}))
self.assertRaises(BadRQLQuery, transform, 'word1', 'word2', 'word3')
-
+
def test_multiple_words_query(self):
"""tests multiple_words_query()"""
self.assertEquals(self.proc._multiple_words_query(['a', 'b', 'c', 'd', 'e']),
@@ -150,9 +150,9 @@
"""tests how quoted queries are handled"""
queries = [
(u'Adresse "My own EmailAddress"', ('EmailAddress E WHERE E has_text %(text)s', {'text': u'My own EmailAddress'})),
- (u'Utilisateur prénom "Jean Paul"', ('CWUser E WHERE E firstname %(text)s', {'text': 'Jean Paul'})),
- (u'Utilisateur firstname "Jean Paul"', ('CWUser E WHERE E firstname %(text)s', {'text': 'Jean Paul'})),
- (u'CWUser firstname "Jean Paul"', ('CWUser E WHERE E firstname %(text)s', {'text': 'Jean Paul'})),
+ (u'Utilisateur prénom "Jean Paul"', ('CWUser C WHERE C firstname %(text)s', {'text': 'Jean Paul'})),
+ (u'Utilisateur firstname "Jean Paul"', ('CWUser C WHERE C firstname %(text)s', {'text': 'Jean Paul'})),
+ (u'CWUser firstname "Jean Paul"', ('CWUser C WHERE C firstname %(text)s', {'text': 'Jean Paul'})),
]
transform = self.proc._quoted_words_query
for query, expected in queries:
@@ -160,23 +160,23 @@
self.assertRaises(BadRQLQuery, transform, "unquoted rql")
self.assertRaises(BadRQLQuery, transform, 'pers "Jean Paul"')
self.assertRaises(BadRQLQuery, transform, 'CWUser firstname other "Jean Paul"')
-
+
def test_process_query(self):
"""tests how queries are processed"""
queries = [
- (u'Utilisateur', (u"CWUser E",)),
+ (u'Utilisateur', (u"CWUser C",)),
(u'Utilisateur P', (u"CWUser P",)),
- (u'Utilisateur cubicweb', (u'CWUser E WHERE E has_text %(text)s', {'text': u'cubicweb'})),
- (u'CWUser prénom cubicweb', (u'CWUser E WHERE E firstname %(text)s', {'text': 'cubicweb'},)),
+ (u'Utilisateur cubicweb', (u'CWUser C WHERE C has_text %(text)s', {'text': u'cubicweb'})),
+ (u'CWUser prénom cubicweb', (u'CWUser C WHERE C firstname %(text)s', {'text': 'cubicweb'},)),
(u'Any X WHERE X is Something', (u"Any X WHERE X is Something",)),
]
for query, expected in queries:
self.assertEquals(self.proc.preprocess_query(query, self.req), expected)
-
+
## Processor Chains tests ############################################
-
+
class ProcessorChainTC(EnvBasedTC):
"""test suite for magic_search's processor chains"""
@@ -195,9 +195,9 @@
# XXX this sounds like a language translator test...
# and it fail
(u'Utilisateur Smith',
- ('CWUser E WHERE E has_text %(text)s', {'text': u'Smith'})),
+ ('CWUser C WHERE C has_text %(text)s', {'text': u'Smith'})),
(u'utilisateur nom Smith',
- ('CWUser E WHERE E surname %(text)s', {'text': u'Smith'})),
+ ('CWUser C WHERE C surname %(text)s', {'text': u'Smith'})),
(u'Any P WHERE P is Utilisateur, P nom "Smith"',
('Any P WHERE P is CWUser, P surname "Smith"', None)),
]
@@ -219,6 +219,6 @@
rset = self.proc.process_query(u'text: utilisateur Smith', self.req)
self.assertEquals(rset.rql, 'Any X WHERE X has_text %(text)s')
self.assertEquals(rset.args, {'text': u'utilisateur Smith'})
-
+
if __name__ == '__main__':
unittest_main()
--- a/web/test/unittest_urlpublisher.py Tue May 05 12:07:42 2009 +0200
+++ b/web/test/unittest_urlpublisher.py Tue May 05 17:13:37 2009 +0200
@@ -21,11 +21,11 @@
b = self.add_entity('BlogEntry', title=u'hell\'o', content=u'blabla')
c = self.add_entity('Tag', name=u'yo') # take care: Tag's name normalized to lower case
self.execute('SET C tags B WHERE C eid %(c)s, B eid %(b)s', {'c':c.eid, 'b':b.eid}, 'b')
-
+
def process(self, url):
req = self.req = self.request()
return self.env.app.url_resolver.process(req, url)
-
+
def test_raw_path(self):
"""tests raw path resolution'"""
self.assertEquals(self.process('view'), ('view', None))
@@ -51,12 +51,12 @@
self.assertEquals(len(rset), 1)
self.assertEquals(rset.description[0][0], 'CWUser')
self.assertEquals(rset.printable_rql(), 'Any X WHERE X is CWUser, X login "admin"')
- ctrl, rset = self.process('euser/admin')
+ ctrl, rset = self.process('cwuser/admin')
self.assertEquals(ctrl, 'view')
self.assertEquals(len(rset), 1)
self.assertEquals(rset.description[0][0], 'CWUser')
self.assertEquals(rset.printable_rql(), 'Any X WHERE X is CWUser, X login "admin"')
- ctrl, rset = self.process('euser/eid/%s'%rset[0][0])
+ ctrl, rset = self.process('cwuser/eid/%s'%rset[0][0])
self.assertEquals(ctrl, 'view')
self.assertEquals(len(rset), 1)
self.assertEquals(rset.description[0][0], 'CWUser')
@@ -77,7 +77,7 @@
self.assertRaises(NotFound, self.process, 'CWUser/eid/30000')
self.assertRaises(NotFound, self.process, 'Workcases')
self.assertRaises(NotFound, self.process, 'CWUser/inexistant_attribute/joe')
-
+
def test_action_path(self):
"""tests the action path resolution"""
self.assertRaises(Redirect, self.process, '1/edit')
@@ -92,7 +92,7 @@
"""tests the regexp path resolution"""
ctrl, rset = self.process('add/Task')
self.assertEquals(ctrl, 'view')
- self.assertEquals(rset, None)
+ self.assertEquals(rset, None)
self.assertEquals(self.req.form, {'etype' : "Task", 'vid' : "creation"})
self.assertRaises(NotFound, self.process, 'add/foo/bar')
@@ -103,11 +103,11 @@
try:
path = str(FakeRequest().url_quote(u'été'))
ctrl, rset = self.process(path)
- self.assertEquals(rset, None)
+ self.assertEquals(rset, None)
self.assertEquals(self.req.form, {'vid' : "foo"})
finally:
SimpleReqRewriter.rules = oldrules
-
+
if __name__ == '__main__':
unittest_main()
--- a/web/test/unittest_views_basecontrollers.py Tue May 05 12:07:42 2009 +0200
+++ b/web/test/unittest_views_basecontrollers.py Tue May 05 17:13:37 2009 +0200
@@ -89,7 +89,7 @@
}
path, params = self.expect_redirect_publish(req)
cnx.commit() # commit to check we don't get late validation error for instance
- self.assertEquals(path, 'euser/user')
+ self.assertEquals(path, 'cwuser/user')
self.failIf('vid' in params)
def testr_user_editing_itself_no_relation(self):
@@ -137,7 +137,7 @@
}
path, params = self.expect_redirect_publish()
# should be redirected on the created person
- self.assertEquals(path, 'euser/adim')
+ self.assertEquals(path, 'cwuser/adim')
e = self.execute('Any P WHERE P surname "Di Mascio"').get_entity(0, 0)
self.assertEquals(e.surname, 'Di Mascio')
email = e.use_email[0]
@@ -329,7 +329,7 @@
self.req.form = {'eid': str(eid), '__type:%s'%eid: 'EmailAddress',
'__action_delete': ''}
path, params = self.expect_redirect_publish()
- self.assertEquals(path, 'euser/admin')
+ self.assertEquals(path, 'cwuser/admin')
self.assertEquals(params, {u'__message': u'entity deleted'})
eid1 = self.add_entity('BlogEntry', title=u'hop', content=u'hop').eid
eid2 = self.add_entity('EmailAddress', address=u'hop@logilab.fr').eid
@@ -448,7 +448,7 @@
'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'',
}
path, params = self.expect_redirect_publish()
- self.assertEquals(path, 'euser/toto')
+ self.assertEquals(path, 'cwuser/toto')
e = self.execute('Any X WHERE X is CWUser, X login "toto"').get_entity(0, 0)
self.assertEquals(e.login, 'toto')
self.assertEquals(e.in_group[0].name, 'managers')
@@ -527,16 +527,18 @@
## tests ##################################################################
def test_simple_exec(self):
- ctrl = self.ctrl(self.request(rql='CWUser P WHERE P login "John"',
- pageid='123'))
+ req = self.request(rql='CWUser P WHERE P login "John"',
+ pageid='123', fname='view')
+ ctrl = self.ctrl(req)
+ rset = self.john.as_rset()
self.assertTextEquals(ctrl.publish(),
- xhtml_wrap(self.john.view('primary')))
+ xhtml_wrap(ctrl.view('primary', rset)))
- def test_json_exec(self):
- rql = 'Any T,N WHERE T is Tag, T name N'
- ctrl = self.ctrl(self.request(mode='json', rql=rql, pageid='123'))
- self.assertEquals(ctrl.publish(),
- simplejson.dumps(self.execute(rql).rows))
+# def test_json_exec(self):
+# rql = 'Any T,N WHERE T is Tag, T name N'
+# ctrl = self.ctrl(self.request(mode='json', rql=rql, pageid='123'))
+# self.assertEquals(ctrl.publish(),
+# simplejson.dumps(self.execute(rql).rows))
def test_remote_add_existing_tag(self):
self.remote_call('tag_entity', self.john.eid, ['python'])
@@ -562,7 +564,7 @@
eid)
self.commit()
rset = self.execute('CWUser P')
- # make sure we did not insert a new euser here
+ # make sure we did not insert a new cwuser here
self.assertEquals(len(rset), nbusers)
john = self.execute('Any X WHERE X eid %(x)s', {'x': self.john.eid}, 'x').get_entity(0, 0)
self.assertEquals(john.eid, self.john.eid)
@@ -570,12 +572,12 @@
def test_pending_insertion(self):
- res, req = self.remote_call('add_pending_insert', ['12', 'tags', '13'])
+ res, req = self.remote_call('add_pending_inserts', [['12', 'tags', '13']])
deletes = req.get_pending_deletes()
self.assertEquals(deletes, [])
inserts = req.get_pending_inserts()
self.assertEquals(inserts, ['12:tags:13'])
- res, req = self.remote_call('add_pending_insert', ['12', 'tags', '14'])
+ res, req = self.remote_call('add_pending_inserts', [['12', 'tags', '14']])
deletes = req.get_pending_deletes()
self.assertEquals(deletes, [])
inserts = req.get_pending_inserts()
@@ -609,7 +611,7 @@
def test_remove_pending_operations(self):
self.remote_call('add_pending_delete', ['12', 'tags', '13'])
- _, req = self.remote_call('add_pending_insert', ['12', 'tags', '14'])
+ _, req = self.remote_call('add_pending_inserts', [['12', 'tags', '14']])
inserts = req.get_pending_inserts()
self.assertEquals(inserts, ['12:tags:14'])
deletes = req.get_pending_deletes()
@@ -636,7 +638,7 @@
simplejson.dumps(['bimboom']))
def test_format_date(self):
- self.assertEquals(self.remote_call('format_date', '"2007-01-01 12:00:00"')[0],
+ self.assertEquals(self.remote_call('format_date', '2007-01-01 12:00:00')[0],
simplejson.dumps('2007/01/01'))
--- a/web/test/unittest_views_baseviews.py Tue May 05 12:07:42 2009 +0200
+++ b/web/test/unittest_views_baseviews.py Tue May 05 17:13:37 2009 +0200
@@ -6,17 +6,17 @@
from cubicweb.devtools.apptest import EnvBasedTC
from cubicweb.web.htmlwidgets import TableWidget
-from cubicweb.web.views.baseviews import vid_from_rset
+from cubicweb.web.views import vid_from_rset
def loadjson(value):
return loads(html_unescape(value))
class VidFromRsetTC(EnvBasedTC):
-
+
def test_no_rset(self):
req = self.request()
self.assertEquals(vid_from_rset(req, None, self.schema), 'index')
-
+
def test_no_entity(self):
req = self.request()
rset = self.execute('Any X WHERE X login "blabla"')
@@ -36,24 +36,24 @@
req = self.request()
rset = self.execute('Any X WHERE X eid 1')
self.assertEquals(vid_from_rset(req, rset, self.schema), 'primary')
-
+
def test_more_than_one_entity(self):
req = self.request()
rset = self.execute('Any X WHERE X is CWUser')
self.assertEquals(vid_from_rset(req, rset, self.schema), 'list')
rset = self.execute('Any X, L WHERE X login L')
self.assertEquals(vid_from_rset(req, rset, self.schema), 'list')
-
+
def test_more_than_one_entity_by_row(self):
req = self.request()
rset = self.execute('Any X, G WHERE X in_group G')
self.assertEquals(vid_from_rset(req, rset, self.schema), 'table')
-
+
def test_more_than_one_entity_by_row_2(self):
req = self.request()
rset = self.execute('Any X, GN WHERE X in_group G, G name GN')
self.assertEquals(vid_from_rset(req, rset, self.schema), 'table')
-
+
def test_aggregat(self):
req = self.request()
rset = self.execute('Any X, COUNT(T) GROUPBY X WHERE X is T')
@@ -81,7 +81,7 @@
req = self.request()
view = self.vreg.select_view('table', req, rset)
return e, rset, view
-
+
def test_headers(self):
self.skip('implement me')
--- a/web/test/unittest_views_editforms.py Tue May 05 12:07:42 2009 +0200
+++ b/web/test/unittest_views_editforms.py Tue May 05 17:13:37 2009 +0200
@@ -1,7 +1,7 @@
from logilab.common.testlib import unittest_main
from cubicweb.devtools.apptest import EnvBasedTC
from cubicweb.devtools.testlib import WebTest
-from cubicweb.web.views.editforms import AutomaticEntityForm as AEF
+from cubicweb.web.views.autoform import AutomaticEntityForm as AEF
from cubicweb.web.formwidgets import AutoCompletionWidget
def rbc(entity, category):
return [(rschema.type, x) for rschema, tschemas, x in AEF.erelations_by_category(entity, category)]
@@ -15,7 +15,7 @@
entity=self.user())
field = form.field_by_name('login')
self.assertIsInstance(field.widget, AutoCompletionWidget)
- AEF.rwidgets.del_rtag('login', 'subject', 'CWUser')
+ AEF.rwidgets.del_rtag(('CWUser', 'login', '*'),'subject')
def test_euser_relations_by_category(self):
@@ -44,14 +44,14 @@
('bookmarked_by', 'object'),
])
self.assertListEquals(rbc(e, 'generic'),
- [('primary_email', 'subject'),
- ('use_email', 'subject'),
- ('connait', 'subject'),
+ [('connait', 'subject'),
('checked_by', 'object'),
])
# owned_by is defined both as subject and object relations on CWUser
self.assertListEquals(rbc(e, 'generated'),
- [('has_text', 'subject'),
+ [('primary_email', 'subject'),
+ ('use_email', 'subject'),
+ ('has_text', 'subject'),
('identity', 'subject'),
('is', 'subject'),
('is_instance_of', 'subject'),
--- a/web/test/unittest_viewselector.py Tue May 05 12:07:42 2009 +0200
+++ b/web/test/unittest_viewselector.py Tue May 05 17:13:37 2009 +0200
@@ -12,17 +12,18 @@
traced_selection)
from cubicweb.web import NoSelectableObject
from cubicweb.web.action import Action
-from cubicweb.web.views import (baseviews, tableview, baseforms, calendar,
- management, embedding, actions, startup,
- euser, schemaentities, xbel, vcard, owl,
- treeview, idownloadable, wdoc, debug, eproperties)
+from cubicweb.web.views import (primary, baseviews, tableview, editforms,
+ calendar, management, embedding, actions,
+ startup, cwuser, schema, xbel, vcard, owl,
+ treeview, idownloadable, wdoc, debug,
+ cwproperties, workflow, xmlrss, csvexport)
USERACTIONS = [('myprefs', actions.UserPreferencesAction),
('myinfos', actions.UserInfoAction),
('logout', actions.LogoutAction)]
SITEACTIONS = [('siteconfig', actions.SiteConfigurationAction),
('manage', actions.ManageAction),
- ('schema', actions.ViewSchemaAction)]
+ ('schema', schema.ViewSchemaAction)]
class ViewSelectorTC(EnvBasedTC):
@@ -65,13 +66,13 @@
self.assertListEqual(self.pviews(req, None),
[('changelog', wdoc.ChangeLogView),
('debug', debug.DebugView),
- ('epropertiesform', eproperties.EPropertiesForm),
+ ('epropertiesform', cwproperties.EPropertiesForm),
('index', startup.IndexView),
('info', management.ProcessInformationView),
('manage', startup.ManageView),
('owl', owl.OWLView),
('schema', startup.SchemaView),
- ('systemepropertiesform', eproperties.SystemEPropertiesForm)])
+ ('systemepropertiesform', cwproperties.SystemEPropertiesForm)])
def test_possible_views_noresult(self):
rset, req = self.env.get_rset_and_req('Any X WHERE X eid 999999')
@@ -81,92 +82,92 @@
def test_possible_views_one_egroup(self):
rset, req = self.env.get_rset_and_req('CWGroup X WHERE X name "managers"')
self.assertListEqual(self.pviews(req, rset),
- [('csvexport', baseviews.CSVRsetView),
- ('ecsvexport', baseviews.CSVEntityView),
+ [('csvexport', csvexport.CSVRsetView),
+ ('ecsvexport', csvexport.CSVEntityView),
('editable-table', tableview.EditableTableView),
('filetree', treeview.FileTreeView),
('list', baseviews.ListView),
('oneline', baseviews.OneLineView),
('owlabox', owl.OWLABOXView),
- ('primary', baseviews.PrimaryView),
- ('rsetxml', baseviews.XMLRsetView),
- ('rss', baseviews.RssView),
+ ('primary', primary.PrimaryView),
+ ('rsetxml', xmlrss.XMLRsetView),
+ ('rss', xmlrss.RSSView),
('secondary', baseviews.SecondaryView),
('security', management.SecurityManagementView),
('table', tableview.TableView),
('text', baseviews.TextView),
('treeview', treeview.TreeView),
('xbel', xbel.XbelView),
- ('xml', baseviews.XmlView),
+ ('xml', xmlrss.XMLView),
])
def test_possible_views_multiple_egroups(self):
rset, req = self.env.get_rset_and_req('CWGroup X')
self.assertListEqual(self.pviews(req, rset),
- [('csvexport', baseviews.CSVRsetView),
- ('ecsvexport', baseviews.CSVEntityView),
+ [('csvexport', csvexport.CSVRsetView),
+ ('ecsvexport', csvexport.CSVEntityView),
('editable-table', tableview.EditableTableView),
('filetree', treeview.FileTreeView),
('list', baseviews.ListView),
('oneline', baseviews.OneLineView),
('owlabox', owl.OWLABOXView),
- ('primary', baseviews.PrimaryView),
- ('rsetxml', baseviews.XMLRsetView),
- ('rss', baseviews.RssView),
+ ('primary', primary.PrimaryView),
+ ('rsetxml', xmlrss.XMLRsetView),
+ ('rss', xmlrss.RSSView),
('secondary', baseviews.SecondaryView),
('security', management.SecurityManagementView),
('table', tableview.TableView),
('text', baseviews.TextView),
('treeview', treeview.TreeView),
('xbel', xbel.XbelView),
- ('xml', baseviews.XmlView),
+ ('xml', xmlrss.XMLView),
])
def test_possible_views_multiple_different_types(self):
rset, req = self.env.get_rset_and_req('Any X')
self.assertListEqual(self.pviews(req, rset),
- [('csvexport', baseviews.CSVRsetView),
- ('ecsvexport', baseviews.CSVEntityView),
+ [('csvexport', csvexport.CSVRsetView),
+ ('ecsvexport', csvexport.CSVEntityView),
('editable-table', tableview.EditableTableView),
('filetree', treeview.FileTreeView),
('list', baseviews.ListView),
('oneline', baseviews.OneLineView),
('owlabox', owl.OWLABOXView),
- ('primary', baseviews.PrimaryView),
- ('rsetxml', baseviews.XMLRsetView),
- ('rss', baseviews.RssView),
+ ('primary', primary.PrimaryView),
+ ('rsetxml', xmlrss.XMLRsetView),
+ ('rss', xmlrss.RSSView),
('secondary', baseviews.SecondaryView),
('security', management.SecurityManagementView),
('table', tableview.TableView),
('text', baseviews.TextView),
('treeview', treeview.TreeView),
('xbel', xbel.XbelView),
- ('xml', baseviews.XmlView),
+ ('xml', xmlrss.XMLView),
])
def test_possible_views_any_rset(self):
rset, req = self.env.get_rset_and_req('Any N, X WHERE X in_group Y, Y name N')
self.assertListEqual(self.pviews(req, rset),
- [('csvexport', baseviews.CSVRsetView),
+ [('csvexport', csvexport.CSVRsetView),
('editable-table', tableview.EditableTableView),
- ('rsetxml', baseviews.XMLRsetView),
+ ('rsetxml', xmlrss.XMLRsetView),
('table', tableview.TableView),
])
def test_possible_views_multiple_eusers(self):
rset, req = self.env.get_rset_and_req('CWUser X')
self.assertListEqual(self.pviews(req, rset),
- [('csvexport', baseviews.CSVRsetView),
- ('ecsvexport', baseviews.CSVEntityView),
+ [('csvexport', csvexport.CSVRsetView),
+ ('ecsvexport', csvexport.CSVEntityView),
('editable-table', tableview.EditableTableView),
('filetree', treeview.FileTreeView),
- ('foaf', euser.FoafView),
+ ('foaf', cwuser.FoafView),
('list', baseviews.ListView),
('oneline', baseviews.OneLineView),
('owlabox', owl.OWLABOXView),
- ('primary', euser.CWUserPrimaryView),
- ('rsetxml', baseviews.XMLRsetView),
- ('rss', baseviews.RssView),
+ ('primary', cwuser.CWUserPrimaryView),
+ ('rsetxml', xmlrss.XMLRsetView),
+ ('rss', xmlrss.RSSView),
('secondary', baseviews.SecondaryView),
('security', management.SecurityManagementView),
('table', tableview.TableView),
@@ -174,7 +175,7 @@
('treeview', treeview.TreeView),
('vcard', vcard.VCardCWUserView),
('xbel', xbel.XbelView),
- ('xml', baseviews.XmlView),
+ ('xml', xmlrss.XMLView),
])
def test_possible_actions_none_rset(self):
@@ -215,16 +216,17 @@
{'useractions': USERACTIONS,
'siteactions': SITEACTIONS})
- def test_possible_actions_eetype_euser_entity(self):
+ def test_possible_actions_eetype_cwuser_entity(self):
rset, req = self.env.get_rset_and_req('CWEType X WHERE X name "CWUser"')
self.assertDictEqual(self.pactions(req, rset),
{'useractions': USERACTIONS,
'siteactions': SITEACTIONS,
'mainactions': [('edit', actions.ModifyAction),
- ('workflow', schemaentities.ViewWorkflowAction),],
- 'moreactions': [('delete', actions.DeleteAction),
+ ('workflow', workflow.ViewWorkflowAction),],
+ 'moreactions': [('managepermission', actions.ManagePermissionsAction),
+ ('delete', actions.DeleteAction),
('copy', actions.CopyAction),
- ('managepermission', actions.ManagePermissionsAction)],
+ ],
})
@@ -234,11 +236,12 @@
# creation form
req.form['etype'] = 'CWGroup'
self.assertIsInstance(self.vreg.select_view('creation', req, rset),
- baseforms.CreationForm)
+ editforms.CreationFormView)
del req.form['etype']
# custom creation form
- class CWUserCreationForm(baseforms.CreationForm):
+ class CWUserCreationForm(editforms.CreationFormView):
__select__ = specified_etype_implements('CWUser')
+ self.vreg._loadedmods[__name__] = {}
self.vreg.register_vobject_class(CWUserCreationForm)
req.form['etype'] = 'CWUser'
self.assertIsInstance(self.vreg.select_view('creation', req, rset),
@@ -268,11 +271,11 @@
# one entity
rset, req = self.env.get_rset_and_req('CWGroup X WHERE X name "managers"')
self.assertIsInstance(self.vreg.select_view('primary', req, rset),
- baseviews.PrimaryView)
+ primary.PrimaryView)
self.assertIsInstance(self.vreg.select_view('list', req, rset),
baseviews.ListView)
self.assertIsInstance(self.vreg.select_view('edition', req, rset),
- baseforms.EditionForm)
+ editforms.EditionFormView)
self.assertIsInstance(self.vreg.select_view('table', req, rset),
tableview.TableView)
self.failUnlessRaises(NoSelectableObject,
@@ -282,7 +285,7 @@
# list of entities of the same type
rset, req = self.env.get_rset_and_req('CWGroup X')
self.assertIsInstance(self.vreg.select_view('primary', req, rset),
- baseviews.PrimaryView)
+ primary.PrimaryView)
self.assertIsInstance(self.vreg.select_view('list', req, rset),
baseviews.ListView)
self.assertIsInstance(self.vreg.select_view('table', req, rset),
@@ -292,7 +295,7 @@
# list of entities of different types
rset, req = self.env.get_rset_and_req('Any X')
self.assertIsInstance(self.vreg.select_view('primary', req, rset),
- baseviews.PrimaryView)
+ primary.PrimaryView)
self.assertIsInstance(self.vreg.select_view('list', req, rset),
baseviews.ListView)
self.assertIsInstance(self.vreg.select_view('table', req, rset),
@@ -323,10 +326,10 @@
self.vreg.select_view, 'creation', req, rset)
self.assertIsInstance(self.vreg.select_view('table', req, rset),
tableview.TableView)
- # euser primary view priority
+ # cwuser primary view priority
rset, req = self.env.get_rset_and_req('CWUser X WHERE X login "admin"')
self.assertIsInstance(self.vreg.select_view('primary', req, rset),
- euser.CWUserPrimaryView)
+ cwuser.CWUserPrimaryView)
self.assertIsInstance(self.vreg.select_view('text', req, rset),
baseviews.TextView)
@@ -401,6 +404,7 @@
def setUp(self):
super(RQLActionTC, self).setUp()
+ self.vreg._loadedmods[__name__] = {}
self.vreg.register_vobject_class(CWETypeRQLAction)
def tearDown(self):
@@ -413,19 +417,21 @@
{'useractions': USERACTIONS,
'siteactions': SITEACTIONS,
'mainactions': [('edit', actions.ModifyAction)],
- 'moreactions': [('delete', actions.DeleteAction),
+ 'moreactions': [('managepermission', actions.ManagePermissionsAction),
+ ('delete', actions.DeleteAction),
('copy', actions.CopyAction),
('testaction', CWETypeRQLAction),
- ('managepermission', actions.ManagePermissionsAction)],
+ ],
})
rset, req = self.env.get_rset_and_req('CWEType X WHERE X name "CWRType"')
self.assertDictEqual(self.pactions(req, rset),
{'useractions': USERACTIONS,
'siteactions': SITEACTIONS,
'mainactions': [('edit', actions.ModifyAction)],
- 'moreactions': [('delete', actions.DeleteAction),
+ 'moreactions': [('managepermission', actions.ManagePermissionsAction),
+ ('delete', actions.DeleteAction),
('copy', actions.CopyAction),
- ('managepermission', actions.ManagePermissionsAction)],
+ ],
})
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/web/test/unittest_web.py Tue May 05 17:13:37 2009 +0200
@@ -0,0 +1,18 @@
+from logilab.common.testlib import TestCase, unittest_main
+from cubicweb.web import ajax_replace_url as arurl
+class AjaxReplaceUrlTC(TestCase):
+
+ def test_ajax_replace_url(self):
+ # NOTE: for the simplest use cases, we could use doctest
+ self.assertEquals(arurl('foo', 'Person P'),
+ "javascript: replacePageChunk('foo', 'Person%20P');")
+ self.assertEquals(arurl('foo', 'Person P', 'oneline'),
+ "javascript: replacePageChunk('foo', 'Person%20P', 'oneline');")
+ self.assertEquals(arurl('foo', 'Person P', 'oneline', name='bar', age=12),
+ 'javascript: replacePageChunk(\'foo\', \'Person%20P\', \'oneline\', {"age": 12, "name": "bar"});')
+ self.assertEquals(arurl('foo', 'Person P', name='bar', age=12),
+ 'javascript: replacePageChunk(\'foo\', \'Person%20P\', \'null\', {"age": 12, "name": "bar"});')
+
+
+if __name__ == '__main__':
+ unittest_main()
--- a/web/uicfg.py Tue May 05 12:07:42 2009 +0200
+++ b/web/uicfg.py Tue May 05 17:13:37 2009 +0200
@@ -54,6 +54,16 @@
rdisplay.tag_relation({}, ('*', rtype, '*'), 'object')
+# index view configuration ####################################################
+# entity type category in the index/manage page. May be one of
+# * 'application'
+# * 'system'
+# * 'schema'
+# * 'subobject' (not displayed by default)
+
+etypecat = {'EmailAddress': 'subobject'}
+
+
# autoform.AutomaticEntityForm configuration ##################################
# relations'category (eg primary/secondary/generic/metadata/generated)
--- a/web/views/authentication.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/authentication.py Tue May 05 17:13:37 2009 +0200
@@ -1,7 +1,7 @@
"""user authentication component
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -12,11 +12,11 @@
from cubicweb.dbapi import repo_connect, ConnectionProperties
from cubicweb.web import ExplicitLogin, InvalidSession
from cubicweb.web.application import AbstractAuthenticationManager
-
+
class RepositoryAuthenticationManager(AbstractAuthenticationManager):
"""authenticate user associated to a request and check session validity"""
-
+
def __init__(self):
self.repo = self.config.repository(self.vreg)
self.log_queries = self.config['query-log-file']
--- a/web/views/basecontrollers.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/basecontrollers.py Tue May 05 17:13:37 2009 +0200
@@ -20,7 +20,7 @@
from cubicweb.selectors import yes, match_user_groups
from cubicweb.view import STRICT_DOCTYPE
from cubicweb.common.mail import format_mail
-from cubicweb.web import ExplicitLogin, Redirect, RemoteCallFailed
+from cubicweb.web import ExplicitLogin, Redirect, RemoteCallFailed, json_dumps
from cubicweb.web.formrenderers import FormRenderer
from cubicweb.web.controller import Controller
from cubicweb.web.views import vid_from_rset
@@ -42,8 +42,7 @@
"""
def wrapper(self, *args, **kwargs):
self.req.set_content_type('application/json')
- result = func(self, *args, **kwargs)
- return simplejson.dumps(result)
+ return json_dumps(func(self, *args, **kwargs))
wrapper.__name__ = func.__name__
return wrapper
--- a/web/views/baseviews.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/baseviews.py Tue May 05 17:13:37 2009 +0200
@@ -16,7 +16,7 @@
from rql import nodes
-from logilab.mtconverter import TransformError, html_escape
+from logilab.mtconverter import TransformError, html_escape, xml_escape
from cubicweb import NoSelectableObject
from cubicweb.selectors import yes, empty_rset
@@ -338,7 +338,7 @@
highlighted = '<b>%s</b>' % searched
for attr in entity.e_schema.indexable_attributes():
try:
- value = html_escape(entity.printable_value(attr, format='text/plain').lower())
+ value = xml_escape(entity.printable_value(attr, format='text/plain').lower())
except TransformError, ex:
continue
except:
@@ -374,9 +374,9 @@
from cubicweb.web.views import boxes, xmlrss, primary
PrimaryView = class_moved(primary.PrimaryView)
SideBoxView = class_moved(boxes.SideBoxView)
-XmlView = class_moved(xmlrss.XmlView)
-XmlItemView = class_moved(xmlrss.XmlItemView)
-XmlRsetView = class_moved(xmlrss.XmlRsetView)
-RssView = class_moved(xmlrss.RssView)
-RssItemView = class_moved(xmlrss.RssItemView)
+XmlView = class_moved(xmlrss.XMLView)
+XmlItemView = class_moved(xmlrss.XMLItemView)
+XmlRsetView = class_moved(xmlrss.XMLRsetView)
+RssView = class_moved(xmlrss.RSSView)
+RssItemView = class_moved(xmlrss.RSSItemView)
--- a/web/views/bookmark.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/bookmark.py Tue May 05 17:13:37 2009 +0200
@@ -12,7 +12,7 @@
from cubicweb.selectors import implements
from cubicweb.web.htmlwidgets import BoxWidget, BoxMenu, RawBoxItem
from cubicweb.web import uicfg, action, box, formwidgets
-from cubicweb.web.views.baseviews import PrimaryView
+from cubicweb.web.views import primary
uicfg.rcategories.tag_relation('primary', ('Bookmark', 'path', '*'), 'subject')
uicfg.rwidgets.tag_relation(formwidgets.TextInput, ('Bookmark', 'path', '*'), 'subject')
@@ -29,7 +29,7 @@
return self.rset.get_entity(self.row or 0, self.col or 0).actual_url()
-class BookmarkPrimaryView(PrimaryView):
+class BookmarkPrimaryView(primary.PrimaryView):
__select__ = implements('Bookmark')
def cell_call(self, row, col):
--- a/web/views/boxes.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/boxes.py Tue May 05 17:13:37 2009 +0200
@@ -136,10 +136,10 @@
eschema = entity.e_schema
for rschema, teschema, x in self.add_related_schemas(entity):
if x == 'subject':
- label = 'add %s %s %s %s' % (eschema, rschema, teschema, x)
+ label = '%s %s %s %s' % (eschema, rschema, teschema, x)
url = self.linkto_url(entity, rschema, teschema, 'object')
else:
- label = 'add %s %s %s %s' % (teschema, rschema, eschema, x)
+ label = '%s %s %s %s' % (teschema, rschema, eschema, x)
url = self.linkto_url(entity, rschema, teschema, 'subject')
actions.append(self.mk_action(_(label), url))
return actions
--- a/web/views/calendar.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/calendar.py Tue May 05 17:13:37 2009 +0200
@@ -7,15 +7,13 @@
from datetime import datetime, date, timedelta
-from vobject import iCalendar
-
from logilab.mtconverter import html_escape
from cubicweb.interfaces import ICalendarable
from cubicweb.selectors import implements
from cubicweb.utils import strptime, date_range, todate
from cubicweb.view import EntityView
-from cubicweb.common.uilib import ajax_replace_url
+from cubicweb.web import ajax_replace_url
_ = unicode
@@ -32,35 +30,40 @@
# Calendar views ##############################################################
+try:
+ from vobject import iCalendar
-class iCalView(EntityView):
- """A calendar view that generates a iCalendar file (RFC 2445)
+ class iCalView(EntityView):
+ """A calendar view that generates a iCalendar file (RFC 2445)
- Does apply to ICalendarable compatible entities
- """
- __select__ = implements(ICalendarable)
- need_navigation = False
- content_type = 'text/calendar'
- title = _('iCalendar')
- templatable = False
- id = 'ical'
+ Does apply to ICalendarable compatible entities
+ """
+ __select__ = implements(ICalendarable)
+ need_navigation = False
+ content_type = 'text/calendar'
+ title = _('iCalendar')
+ templatable = False
+ id = 'ical'
- def call(self):
- ical = iCalendar()
- for i in range(len(self.rset.rows)):
- task = self.complete_entity(i)
- event = ical.add('vevent')
- event.add('summary').value = task.dc_title()
- event.add('description').value = task.dc_description()
- if task.start:
- event.add('dtstart').value = task.start
- if task.stop:
- event.add('dtend').value = task.stop
+ def call(self):
+ ical = iCalendar()
+ for i in range(len(self.rset.rows)):
+ task = self.complete_entity(i)
+ event = ical.add('vevent')
+ event.add('summary').value = task.dc_title()
+ event.add('description').value = task.dc_description()
+ if task.start:
+ event.add('dtstart').value = task.start
+ if task.stop:
+ event.add('dtend').value = task.stop
- buff = ical.serialize()
- if not isinstance(buff, unicode):
- buff = unicode(buff, self.req.encoding)
- self.w(buff)
+ buff = ical.serialize()
+ if not isinstance(buff, unicode):
+ buff = unicode(buff, self.req.encoding)
+ self.w(buff)
+
+except ImportError:
+ pass
class hCalView(EntityView):
"""A calendar view that generates a hCalendar file
--- a/web/views/cwproperties.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/cwproperties.py Tue May 05 17:13:37 2009 +0200
@@ -5,6 +5,7 @@
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
+_ = unicode
from logilab.mtconverter import html_escape
@@ -14,14 +15,12 @@
from cubicweb.selectors import (one_line_rset, none_rset, implements,
match_user_groups)
from cubicweb.view import StartupView
-from cubicweb.web import uicfg
-from cubicweb.web.views import baseviews
-from cubicweb.web import stdmsgs
+from cubicweb.web import uicfg, stdmsgs
from cubicweb.web.form import CompositeForm, EntityFieldsForm, FormViewMixIn
from cubicweb.web.formfields import FIELDS, StringField
from cubicweb.web.formwidgets import Select, Button, SubmitButton
+from cubicweb.web.views import primary
-_ = unicode
# some string we want to be internationalizable for nicer display of eproperty
# groups
@@ -31,11 +30,27 @@
_('boxes')
_('components')
_('contentnavigation')
+_('navigation.combobox-limit')
+_('navigation.page-size')
+_('navigation.related-limit')
+_('navigation.short-line-size')
+_('ui.date-format')
+_('ui.datetime-format')
+_('ui.default-text-format')
+_('ui.fckeditor')
+_('ui.float-format')
+_('ui.language')
+_('ui.time-format')
+_('open all')
+_('ui.main-template')
+_('ui.site-title')
+_('ui.encoding')
+_('category')
def make_togglable_link(nodeid, label, cookiename):
"""builds a HTML link that switches the visibility & remembers it"""
- action = u"javascript: toggle_and_remember_visibility('%s', '%s')" % \
+ action = u"javascript: toggleVisibility('%s', '%s')" % \
(nodeid, cookiename)
return u'<a href="%s">%s</a>' % (action, label)
@@ -43,7 +58,7 @@
return someclass and 'class="%s"' % someclass or ''
-class CWPropertyPrimaryView(baseviews.PrimaryView):
+class CWPropertyPrimaryView(primary.PrimaryView):
__select__ = implements('CWProperty')
skip_none = False
--- a/web/views/cwuser.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/cwuser.py Tue May 05 17:13:37 2009 +0200
@@ -11,7 +11,7 @@
from cubicweb.selectors import one_line_rset, implements, match_user_groups
from cubicweb.view import EntityView
from cubicweb.web import uicfg, action
-from cubicweb.web.views.baseviews import PrimaryView
+from cubicweb.web.views import primary
uicfg.rcategories.tag_relation('secondary', ('CWUser', 'firstname', '*'), 'subject')
@@ -42,7 +42,7 @@
return self.build_url('cwuser/%s'%login, vid='epropertiesform')
-class CWUserPrimaryView(PrimaryView):
+class CWUserPrimaryView(primary.PrimaryView):
__select__ = implements('CWUser')
def content_title(self, entity):
--- a/web/views/editforms.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/editforms.py Tue May 05 17:13:37 2009 +0200
@@ -18,7 +18,7 @@
from cubicweb.utils import make_uid
from cubicweb.view import EntityView
from cubicweb.common import tags
-from cubicweb.web import stdmsgs
+from cubicweb.web import INTERNAL_FIELD_VALUE, stdmsgs, eid_param
from cubicweb.web.form import CompositeForm, EntityFieldsForm, FormViewMixIn
from cubicweb.web.formwidgets import Button, SubmitButton, ResetButton
from cubicweb.web.formrenderers import (FormRenderer, EntityFormRenderer,
@@ -228,19 +228,21 @@
"""fetch and render the form"""
# make a copy of entity to avoid altering the entity in the
# request's cache.
+ entity.complete()
self.newentity = copy(entity)
self.copying = self.newentity.eid
- self.newentity.eid = None
+ self.initialize_varmaker()
+ self.newentity.eid = self.varmaker.next()
self.w(u'<script type="text/javascript">updateMessage("%s");</script>\n'
% self.req._('Please note that this is only a shallow copy'))
- super(CopyFormView, self).render_form(entity)
+ super(CopyFormView, self).render_form(self.newentity)
del self.newentity
def init_form(self, form, entity):
"""customize your form before rendering here"""
super(CopyFormView, self).init_form(form, entity)
if entity.eid == self.newentity.eid:
- form.form_add_hidden('__cloned_eid', self.copying, eidparam=True)
+ form.form_add_hidden(eid_param('__cloned_eid', entity.eid), self.copying)
def submited_message(self):
"""return the message that will be displayed on successful edition"""
--- a/web/views/emailaddress.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/emailaddress.py Tue May 05 17:13:37 2009 +0200
@@ -10,9 +10,9 @@
from cubicweb.selectors import implements
from cubicweb.common import Unauthorized
-from cubicweb.web.views import baseviews
+from cubicweb.web.views import baseviews, primary
-class EmailAddressPrimaryView(baseviews.PrimaryView):
+class EmailAddressPrimaryView(primary.PrimaryView):
__select__ = implements('EmailAddress')
def cell_call(self, row, col, skipeids=None):
@@ -63,7 +63,7 @@
__select__ = implements('EmailAddress')
id = 'shortprimary'
title = None # hidden view
-
+
def render_entity_attributes(self, entity):
self.w(u'<h5>')
entity.view('oneline', w=self.w)
--- a/web/views/idownloadable.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/idownloadable.py Tue May 05 17:13:37 2009 +0200
@@ -5,17 +5,18 @@
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
+_ = unicode
from logilab.mtconverter import BINARY_ENCODINGS, TransformError, html_escape
+from cubicweb.view import EntityView
from cubicweb.selectors import (one_line_rset, score_entity,
implements, match_context_prop)
from cubicweb.interfaces import IDownloadable
from cubicweb.common.mttransforms import ENGINE
from cubicweb.web.box import EntityBoxTemplate
-from cubicweb.web.views import baseviews
+from cubicweb.web.views import primary, baseviews
-_ = unicode
def is_image(entity):
mt = entity.download_content_type()
@@ -52,7 +53,7 @@
download_box(self.w, entity, title, label)
-class DownloadView(baseviews.EntityView):
+class DownloadView(EntityView):
"""this view is replacing the deprecated 'download' controller and allow
downloading of entities providing the necessary interface
"""
@@ -81,7 +82,7 @@
self.w(self.complete_entity(0).download_data())
-class DownloadLinkView(baseviews.EntityView):
+class DownloadLinkView(EntityView):
"""view displaying a link to download the file"""
id = 'downloadlink'
__select__ = implements(IDownloadable)
@@ -94,7 +95,7 @@
self.w(u'<a href="%s">%s</a>' % (url, html_escape(title or entity.dc_title())))
-class IDownloadablePrimaryView(baseviews.PrimaryView):
+class IDownloadablePrimaryView(primary.PrimaryView):
__select__ = implements(IDownloadable)
def render_entity_attributes(self, entity):
@@ -129,7 +130,7 @@
(url, name, durl, self.req._('download')))
-class ImageView(baseviews.EntityView):
+class ImageView(EntityView):
id = 'image'
__select__ = implements(IDownloadable) & score_entity(is_image)
--- a/web/views/isioc.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/isioc.py Tue May 05 17:13:37 2009 +0200
@@ -44,13 +44,17 @@
def cell_call(self, row, col):
entity = self.complete_entity(row, col)
- self.w(u'<sioc:%s rdf:about="%s">\n' % (html_escape(entity.isioc_type()),
- html_escape(entity.absolute_url())))
- self.w(u'<dcterms:title>%s</dcterms:title>' % html_escape(entity.dc_title()))
- self.w(u'<dcterms:created>%s</dcterms:created>' % entity.creation_date)
- self.w(u'<dcterms:modified>%s</dcterms:modified>' % entity.modification_date)
+ sioct = html_escape(entity.isioc_type())
+ self.w(u'<sioc:%s rdf:about="%s">\n'
+ % (sioct, html_escape(entity.absolute_url())))
+ self.w(u'<dcterms:title>%s</dcterms:title>'
+ % html_escape(entity.dc_title()))
+ self.w(u'<dcterms:created>%s</dcterms:created>'
+ % entity.creation_date)
+ self.w(u'<dcterms:modified>%s</dcterms:modified>'
+ % entity.modification_date)
self.w(u'<!-- FIXME : here be items -->')#entity.isioc_items()
- self.w(u'</sioc:%s>\n' % entity.isioc_type())
+ self.w(u'</sioc:%s>\n' % sioct)
class SIOCItemView(EntityView):
@@ -61,22 +65,29 @@
def cell_call(self, row, col):
entity = self.complete_entity(row, col)
- self.w(u'<sioc:%s rdf:about="%s">\n' % (html_escape(entity.isioc_type()),
- html_escape(entity.absolute_url())))
- self.w(u'<dcterms:title>%s</dcterms:title>' % html_escape(entity.dc_title()))
- self.w(u'<dcterms:created>%s</dcterms:created>' % entity.creation_date)
- self.w(u'<dcterms:modified>%s</dcterms:modified>' % entity.modification_date)
+ sioct = html_escape(entity.isioc_type())
+ self.w(u'<sioc:%s rdf:about="%s">\n'
+ % (sioct, html_escape(entity.absolute_url())))
+ self.w(u'<dcterms:title>%s</dcterms:title>'
+ % html_escape(entity.dc_title()))
+ self.w(u'<dcterms:created>%s</dcterms:created>'
+ % entity.creation_date)
+ self.w(u'<dcterms:modified>%s</dcterms:modified>'
+ % entity.modification_date)
if entity.content:
- self.w(u'<sioc:content>%s</sioc:content>''' % html_escape(entity.isioc_content()))
+ self.w(u'<sioc:content>%s</sioc:content>'''
+ % html_escape(entity.isioc_content()))
if entity.related('entry_of'):
- self.w(u'<sioc:has_container rdf:resource="%s"/>\n' % html_escape(entity.isioc_container().absolute_url()))
+ self.w(u'<sioc:has_container rdf:resource="%s"/>\n'
+ % html_escape(entity.isioc_container().absolute_url()))
if entity.creator:
self.w(u'<sioc:has_creator>\n')
- self.w(u'<sioc:User rdf:about="%s">\n' % html_escape(entity.creator.absolute_url()))
+ self.w(u'<sioc:User rdf:about="%s">\n'
+ % html_escape(entity.creator.absolute_url()))
self.w(entity.creator.view('foaf'))
self.w(u'</sioc:User>\n')
self.w(u'</sioc:has_creator>\n')
self.w(u'<!-- FIXME : here be topics -->')#entity.isioc_topics()
self.w(u'<!-- FIXME : here be replies -->')#entity.isioc_replies()
- self.w(u' </sioc:%s>\n' % 'Post')
+ self.w(u' </sioc:%s>\n' % sioct)
--- a/web/views/management.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/management.py Tue May 05 17:13:37 2009 +0200
@@ -6,6 +6,7 @@
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
+_ = unicode
from logilab.mtconverter import html_escape
@@ -17,8 +18,6 @@
from cubicweb.web.formfields import guess_field
from cubicweb.web.formrenderers import HTableFormRenderer
-_ = unicode
-
SUBMIT_MSGID = _('Submit bug report')
MAIL_SUBMIT_MSGID = _('Submit bug report by mail')
@@ -30,7 +29,7 @@
if not access_types:
access_types = eschema.ACTIONS
w(u'<table class="schemaInfo">')
- w(u'<tr><th>%s</th><th>%s</th><th>%s</th></tr>' % (
+ w(u'<tr><th>%s</th><th>%s</th><th>%s</th></tr>' % (
_("permission"), _('granted to groups'), _('rql expressions')))
for access_type in access_types:
w(u'<tr>')
@@ -272,7 +271,6 @@
binfo += '\n'
return binfo
-
class ProcessInformationView(StartupView):
id = 'info'
__select__ = none_rset() & match_user_groups('managers')
--- a/web/views/massmailing.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/massmailing.py Tue May 05 17:13:37 2009 +0200
@@ -13,7 +13,8 @@
from cubicweb.view import EntityView
from cubicweb.web import stdmsgs
from cubicweb.web.action import Action
-from cubicweb.web.form import FieldsForm, FormRenderer, FormViewMixIn
+from cubicweb.web.form import FieldsForm, FormViewMixIn
+from cubicweb.web.formrenderers import FormRenderer
from cubicweb.web.formfields import StringField
from cubicweb.web.formwidgets import CheckBox, TextInput, AjaxWidget, ImgButton
--- a/web/views/navigation.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/navigation.py Tue May 05 17:13:37 2009 +0200
@@ -44,7 +44,7 @@
w(u'[ %s ]' % u' | '.join(blocklist))
w(u' %s' % self.next_link(params))
w(u'</div>')
-
+
def index_display(self, start, stop):
return u'%s - %s' % (start+1, stop+1)
@@ -53,10 +53,10 @@
and if the result set is sorted
"""
__select__ = paginated_rset() & sorted_rset()
-
+
# number of considered chars to build page links
nb_chars = 5
-
+
def display_func(self, rset, col, attrname):
req = self.req
if attrname is not None:
@@ -70,7 +70,7 @@
def index_display(row):
return rset.get_entity(row, col).view('text')
return index_display
-
+
def call(self):
"""displays links to navigate accross pages of a result set
@@ -167,12 +167,12 @@
# monkey patch base View class to add a .pagination(req, rset, w, forcedisplay)
# method to be called on view's result set and printing pages index in the view
from cubicweb.view import View
-# XXX deprecated, use paginate
View.pagination = obsolete('.pagination is deprecated, use paginate')(limit_rset_using_paged_nav)
-def paginate(view, show_all_option=True, w=None):
+def paginate(view, show_all_option=True, w=None, page_size=None):
limit_rset_using_paged_nav(view, view.req, view.rset, w or view.w,
- not view.need_navigation, show_all_option)
+ not view.need_navigation, show_all_option,
+ page_size=page_size)
View.paginate = paginate
class NextPrevNavigationComponent(EntityVComponent):
@@ -212,7 +212,7 @@
html_escape(previous.absolute_url()),
self.req._('i18nprevnext_previous'),
html_escape(cut(previous.dc_title(), textsize)))
-
+
def next_link(self, next, textsize):
return u'<a href="%s" title="%s">%s >></a>' % (
html_escape(next.absolute_url()),
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/web/views/old_calendar.py Tue May 05 17:13:37 2009 +0200
@@ -0,0 +1,543 @@
+"""html calendar views
+
+:organization: Logilab
+:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+
+from datetime import datetime, date, time, timedelta
+#from datetime import datetime, RelativeDateTime, date, time, Sunday
+
+from logilab.mtconverter import html_escape
+
+from cubicweb.interfaces import ICalendarViews
+from cubicweb.utils import date_range
+from cubicweb.selectors import implements
+from cubicweb.view import EntityView
+
+# Define some useful constants
+#ONE_MONTH = RelativeDateTime(months=1)
+ONE_MONTH = timedelta(days=31)
+TODAY = date.today()
+THIS_MONTH = TODAY.month
+THIS_YEAR = TODAY.year
+# mx.DateTime and ustrftime could be used to build WEEKDAYS
+WEEKDAYS = [_("monday"), _("tuesday"), _("wednesday"), _("thursday"),
+ _("friday"), _("saturday"), _("sunday")]
+
+# used by i18n tools
+MONTHNAMES = [ _('january'), _('february'), _('march'), _('april'), _('may'),
+ _('june'), _('july'), _('august'), _('september'), _('october'),
+ _('november'), _('december')
+ ]
+
+class _CalendarView(EntityView):
+ """base calendar view containing helpful methods to build calendar views"""
+ __select__ = implements(ICalendarViews,)
+ need_navigation = False
+
+ # Navigation building methods / views ####################################
+
+ PREV = u'<a href="%s"><<</a> <a href="%s"><</a>'
+ NEXT = u'<a href="%s">></a> <a href="%s">>></a>'
+ NAV_HEADER = u"""<table class="calendarPageHeader">
+<tr><td class="prev">%s</td><td class="next">%s</td></tr>
+</table>
+""" % (PREV, NEXT)
+
+ def nav_header(self, date, smallshift=3, bigshift=9):
+ """prints shortcut links to go to previous/next steps (month|week)"""
+ prev1 = date - RelativeDateTime(months=smallshift)
+ prev2 = date - RelativeDateTime(months=bigshift)
+ next1 = date + RelativeDateTime(months=smallshift)
+ next2 = date + RelativeDateTime(months=bigshift)
+ rql, vid = self.rset.printable_rql(), self.id
+ return self.NAV_HEADER % (
+ html_escape(self.build_url(rql=rql, vid=vid, year=prev2.year, month=prev2.month)),
+ html_escape(self.build_url(rql=rql, vid=vid, year=prev1.year, month=prev1.month)),
+ html_escape(self.build_url(rql=rql, vid=vid, year=next1.year, month=next1.month)),
+ html_escape(self.build_url(rql=rql, vid=vid, year=next2.year, month=next2.month)))
+
+
+ # Calendar building methods ##############################################
+
+ def build_calendars(self, schedule, begin, end):
+ """build several HTML calendars at once, one for each month
+ between begin and end
+ """
+ return [self.build_calendar(schedule, date)
+ for date in date_range(begin, end, incr=ONE_MONTH)]
+
+ def build_calendar(self, schedule, first_day):
+ """method responsible for building *one* HTML calendar"""
+ # FIXME iterates between [first_day-first_day.day_of_week ;
+ # last_day+6-last_day.day_of_week]
+ umonth = self.format_date(first_day, '%B %Y') # localized month name
+ rows = []
+ current_row = [NO_CELL] * first_day.day_of_week
+ for daynum in xrange(0, first_day.days_in_month):
+ # build cell day
+ day = first_day + daynum
+ events = schedule.get(day)
+ if events:
+ events = [u'\n'.join(event) for event in events.values()]
+ current_row.append(CELL % (daynum+1, '\n'.join(events)))
+ else:
+ current_row.append(EMPTY_CELL % (daynum+1))
+ # store & reset current row on Sundays
+ if day.day_of_week == Sunday:
+ rows.append(u'<tr>%s%s</tr>' % (WEEKNUM_CELL % day.isocalendar()[1], ''.join(current_row)))
+ current_row = []
+ current_row.extend([NO_CELL] * (Sunday-day.day_of_week))
+ rql = self.rset.printable_rql()
+ if day.day_of_week != Sunday:
+ rows.append(u'<tr>%s%s</tr>' % (WEEKNUM_CELL % day.isocalendar()[1], ''.join(current_row)))
+ url = self.build_url(rql=rql, vid='calendarmonth',
+ year=first_day.year, month=first_day.month)
+ monthlink = u'<a href="%s">%s</a>' % (html_escape(url), umonth)
+ return CALENDAR(self.req) % (monthlink, '\n'.join(rows))
+
+ def _mk_schedule(self, begin, end, itemvid='calendaritem'):
+ """private method that gathers information from resultset
+ and builds calendars according to it
+
+ :param begin: begin of date range
+ :param end: end of date rangs
+ :param itemvid: which view to call to render elements in cells
+
+ returns { day1 : { hour : [views] },
+ day2 : { hour : [views] } ... }
+ """
+ # put this here since all sub views are calling this method
+ self.req.add_css('cubicweb.calendar.css')
+ schedule = {}
+ for row in xrange(len(self.rset.rows)):
+ entity = self.entity(row)
+ infos = u'<div class="event">'
+ infos += self.view(itemvid, self.rset, row=row)
+ infos += u'</div>'
+ for date in entity.matching_dates(begin, end):
+ day = Date(date.year, date.month, date.day)
+ time = Time(date.hour, date.minute, date.second)
+ schedule.setdefault(day, {})
+ schedule[day].setdefault(time, []).append(infos)
+ return schedule
+
+
+ @staticmethod
+ def get_date_range(day=TODAY, shift=4):
+ """returns a couple (begin, end)
+
+ <begin> is the first day of current_month - shift
+ <end> is the last day of current_month + (shift+1)
+ """
+ first_day_in_month = DateTime(day.year, day.month, 1)
+ begin = first_day_in_month - RelativeDateTime(months=shift)
+ end = (first_day_in_month + RelativeDateTime(months=shift+1)) - 1
+ return begin, end
+
+
+ def _build_ampm_cells(self, daynum, events):
+ """create a view without any hourly details.
+
+ :param daynum: day of the built cell
+ :param events: dictionnary with all events classified by hours"""
+ # split events according am/pm
+ am_events = [event for e_time, e_list in events.iteritems()
+ if 0 <= e_time.hour < 12
+ for event in e_list]
+ pm_events = [event for e_time, e_list in events.iteritems()
+ if 12 <= e_time.hour < 24
+ for event in e_list]
+ # format each am/pm cell
+ if am_events:
+ am_content = AMPM_CONTENT % ("amCell", "am", '\n'.join(am_events))
+ else:
+ am_content = AMPM_EMPTY % ("amCell", "am")
+ if pm_events:
+ pm_content = AMPM_CONTENT % ("pmCell", "pm", '\n'.join(pm_events))
+ else:
+ pm_content = AMPM_EMPTY % ("pmCell", "pm")
+ return am_content, pm_content
+
+
+
+class YearCalendarView(_CalendarView):
+ id = 'calendaryear'
+ title = _('calendar (year)')
+
+ def call(self, year=THIS_YEAR, month=THIS_MONTH):
+ """this view renders a 3x3 calendars' table"""
+ year = int(self.req.form.get('year', year))
+ month = int(self.req.form.get('month', month))
+ center_date = DateTime(year, month)
+ begin, end = self.get_date_range(day=center_date)
+ schedule = self._mk_schedule(begin, end)
+ self.w(self.nav_header(center_date))
+ calendars = tuple(self.build_calendars(schedule, begin, end))
+ self.w(SMALL_CALENDARS_PAGE % calendars)
+
+
+class SemesterCalendarView(_CalendarView):
+ """this view renders three semesters as three rows of six columns,
+ one column per month
+ """
+ id = 'calendarsemester'
+ title = _('calendar (semester)')
+
+ def call(self, year=THIS_YEAR, month=THIS_MONTH):
+ year = int(self.req.form.get('year', year))
+ month = int(self.req.form.get('month', month))
+ begin = DateTime(year, month) - RelativeDateTime(months=2)
+ end = DateTime(year, month) + RelativeDateTime(months=3)
+ schedule = self._mk_schedule(begin, end)
+ self.w(self.nav_header(DateTime(year, month), 1, 6))
+ self.w(u'<table class="semesterCalendar">')
+ self.build_calendars(schedule, begin, end)
+ self.w(u'</table>')
+ self.w(self.nav_header(DateTime(year, month), 1, 6))
+
+ def build_calendars(self, schedule, begin, end):
+ self.w(u'<tr>')
+ rql = self.rset.printable_rql()
+ for cur_month in date_range(begin, end, incr=ONE_MONTH):
+ umonth = u'%s %s' % (self.format_date(cur_month, '%B'), cur_month.year)
+ url = self.build_url(rql=rql, vid=self.id,
+ year=cur_month.year, month=cur_month.month)
+ self.w(u'<th colspan="2"><a href="%s">%s</a></th>' % (html_escape(url),
+ umonth))
+ self.w(u'</tr>')
+ _ = self.req._
+ for day_num in xrange(31):
+ self.w(u'<tr>')
+ for cur_month in date_range(begin, end, incr=ONE_MONTH):
+ if day_num >= cur_month.days_in_month:
+ self.w(u'%s%s' % (NO_CELL, NO_CELL))
+ else:
+ day = DateTime(cur_month.year, cur_month.month, day_num+1)
+ events = schedule.get(day)
+ self.w(u'<td>%s %s</td>\n' % (_(WEEKDAYS[day.day_of_week])[0].upper(), day_num+1))
+ self.format_day_events(day, events)
+ self.w(u'</tr>')
+
+ def format_day_events(self, day, events):
+ if events:
+ events = ['\n'.join(event) for event in events.values()]
+ self.w(WEEK_CELL % '\n'.join(events))
+ else:
+ self.w(WEEK_EMPTY_CELL)
+
+
+class MonthCalendarView(_CalendarView):
+ """this view renders a 3x1 calendars' table"""
+ id = 'calendarmonth'
+ title = _('calendar (month)')
+
+ def call(self, year=THIS_YEAR, month=THIS_MONTH):
+ year = int(self.req.form.get('year', year))
+ month = int(self.req.form.get('month', month))
+ center_date = DateTime(year, month)
+ begin, end = self.get_date_range(day=center_date, shift=1)
+ schedule = self._mk_schedule(begin, end)
+ calendars = self.build_calendars(schedule, begin, end)
+ self.w(self.nav_header(center_date, 1, 3))
+ self.w(BIG_CALENDARS_PAGE % tuple(calendars))
+ self.w(self.nav_header(center_date, 1, 3))
+
+
+class WeekCalendarView(_CalendarView):
+ """this view renders a calendar for week events"""
+ id = 'calendarweek'
+ title = _('calendar (week)')
+
+ def call(self, year=THIS_YEAR, week=TODAY.isocalendar()[1]):
+ year = int(self.req.form.get('year', year))
+ week = int(self.req.form.get('week', week))
+ day0 = DateTime(year)
+ first_day_of_week = (day0-day0.day_of_week) + 7*week
+ begin, end = first_day_of_week-7, first_day_of_week+14
+ schedule = self._mk_schedule(begin, end, itemvid='calendarlargeitem')
+ self.w(self.nav_header(first_day_of_week))
+ self.w(u'<table class="weekCalendar">')
+ _weeks = [(first_day_of_week-7, first_day_of_week-1),
+ (first_day_of_week, first_day_of_week+6),
+ (first_day_of_week+7, first_day_of_week+13)]
+ self.build_calendar(schedule, _weeks)
+ self.w(u'</table>')
+ self.w(self.nav_header(first_day_of_week))
+
+ def build_calendar(self, schedule, weeks):
+ rql = self.rset.printable_rql()
+ _ = self.req._
+ for monday, sunday in weeks:
+ umonth = self.format_date(monday, '%B %Y')
+ url = self.build_url(rql=rql, vid='calendarmonth',
+ year=monday.year, month=monday.month)
+ monthlink = '<a href="%s">%s</a>' % (html_escape(url), umonth)
+ self.w(u'<tr><th colspan="3">%s %s (%s)</th></tr>' \
+ % (_('week'), monday.isocalendar()[1], monthlink))
+ for day in date_range(monday, sunday):
+ self.w(u'<tr>')
+ self.w(u'<td>%s</td>' % _(WEEKDAYS[day.day_of_week]))
+ self.w(u'<td>%s</td>' % (day.strftime('%Y-%m-%d')))
+ events = schedule.get(day)
+ if events:
+ events = ['\n'.join(event) for event in events.values()]
+ self.w(WEEK_CELL % '\n'.join(events))
+ else:
+ self.w(WEEK_EMPTY_CELL)
+ self.w(u'</tr>')
+
+ def nav_header(self, date, smallshift=1, bigshift=3):
+ """prints shortcut links to go to previous/next steps (month|week)"""
+ prev1 = date - RelativeDateTime(weeks=smallshift)
+ prev2 = date - RelativeDateTime(weeks=bigshift)
+ next1 = date + RelativeDateTime(weeks=smallshift)
+ next2 = date + RelativeDateTime(weeks=bigshift)
+ rql, vid = self.rset.printable_rql(), self.id
+ return self.NAV_HEADER % (
+ html_escape(self.build_url(rql=rql, vid=vid, year=prev2.year, week=prev2.isocalendar()[1])),
+ html_escape(self.build_url(rql=rql, vid=vid, year=prev1.year, week=prev1.isocalendar()[1])),
+ html_escape(self.build_url(rql=rql, vid=vid, year=next1.year, week=next1.isocalendar()[1])),
+ html_escape(self.build_url(rql=rql, vid=vid, year=next2.year, week=next2.isocalendar()[1])))
+
+
+
+class AMPMYearCalendarView(YearCalendarView):
+ id = 'ampmcalendaryear'
+ title = _('am/pm calendar (year)')
+
+ def build_calendar(self, schedule, first_day):
+ """method responsible for building *one* HTML calendar"""
+ umonth = self.format_date(first_day, '%B %Y') # localized month name
+ rows = [] # each row is: (am,pm), (am,pm) ... week_title
+ current_row = [(NO_CELL, NO_CELL, NO_CELL)] * first_day.day_of_week
+ rql = self.rset.printable_rql()
+ for daynum in xrange(0, first_day.days_in_month):
+ # build cells day
+ day = first_day + daynum
+ events = schedule.get(day)
+ if events:
+ current_row.append((AMPM_DAY % (daynum+1),) + self._build_ampm_cells(daynum, events))
+ else:
+ current_row.append((AMPM_DAY % (daynum+1),
+ AMPM_EMPTY % ("amCell", "am"),
+ AMPM_EMPTY % ("pmCell", "pm")))
+ # store & reset current row on Sundays
+ if day.day_of_week == Sunday:
+ url = self.build_url(rql=rql, vid='ampmcalendarweek',
+ year=day.year, week=day.isocalendar()[1])
+ weeklink = '<a href="%s">%s</a>' % (html_escape(url),
+ day.isocalendar()[1])
+ current_row.append(WEEKNUM_CELL % weeklink)
+ rows.append(current_row)
+ current_row = []
+ current_row.extend([(NO_CELL, NO_CELL, NO_CELL)] * (Sunday-day.day_of_week))
+ url = self.build_url(rql=rql, vid='ampmcalendarweek',
+ year=day.year, week=day.isocalendar()[1])
+ weeklink = '<a href="%s">%s</a>' % (html_escape(url), day.isocalendar()[1])
+ current_row.append(WEEKNUM_CELL % weeklink)
+ rows.append(current_row)
+ # build two rows for each week: am & pm
+ formatted_rows = []
+ for row in rows:
+ week_title = row.pop()
+ day_row = [day for day, am, pm in row]
+ am_row = [am for day, am, pm in row]
+ pm_row = [pm for day, am, pm in row]
+ formatted_rows.append('<tr>%s%s</tr>'% (week_title, '\n'.join(day_row)))
+ formatted_rows.append('<tr class="amRow"><td> </td>%s</tr>'% '\n'.join(am_row))
+ formatted_rows.append('<tr class="pmRow"><td> </td>%s</tr>'% '\n'.join(pm_row))
+ # tigh everything together
+ url = self.build_url(rql=rql, vid='ampmcalendarmonth',
+ year=first_day.year, month=first_day.month)
+ monthlink = '<a href="%s">%s</a>' % (html_escape(url), umonth)
+ return CALENDAR(self.req) % (monthlink, '\n'.join(formatted_rows))
+
+
+
+class AMPMSemesterCalendarView(SemesterCalendarView):
+ """this view renders a 3x1 calendars' table"""
+ id = 'ampmcalendarsemester'
+ title = _('am/pm calendar (semester)')
+
+ def build_calendars(self, schedule, begin, end):
+ self.w(u'<tr>')
+ rql = self.rset.printable_rql()
+ for cur_month in date_range(begin, end, incr=ONE_MONTH):
+ umonth = u'%s %s' % (self.format_date(cur_month, '%B'), cur_month.year)
+ url = self.build_url(rql=rql, vid=self.id,
+ year=cur_month.year, month=cur_month.month)
+ self.w(u'<th colspan="3"><a href="%s">%s</a></th>' % (html_escape(url),
+ umonth))
+ self.w(u'</tr>')
+ _ = self.req._
+ for day_num in xrange(31):
+ self.w(u'<tr>')
+ for cur_month in date_range(begin, end, incr=ONE_MONTH):
+ if day_num >= cur_month.days_in_month:
+ self.w(u'%s%s%s' % (NO_CELL, NO_CELL, NO_CELL))
+ else:
+ day = DateTime(cur_month.year, cur_month.month, day_num+1)
+ events = schedule.get(day)
+ self.w(u'<td>%s %s</td>\n' % (_(WEEKDAYS[day.day_of_week])[0].upper(),
+ day_num+1))
+ self.format_day_events(day, events)
+ self.w(u'</tr>')
+
+ def format_day_events(self, day, events):
+ if events:
+ self.w(u'\n'.join(self._build_ampm_cells(day, events)))
+ else:
+ self.w(u'%s %s'% (AMPM_EMPTY % ("amCell", "am"),
+ AMPM_EMPTY % ("pmCell", "pm")))
+
+
+class AMPMMonthCalendarView(MonthCalendarView):
+ """this view renders a 3x1 calendars' table"""
+ id = 'ampmcalendarmonth'
+ title = _('am/pm calendar (month)')
+
+ def build_calendar(self, schedule, first_day):
+ """method responsible for building *one* HTML calendar"""
+ umonth = self.format_date(first_day, '%B %Y') # localized month name
+ rows = [] # each row is: (am,pm), (am,pm) ... week_title
+ current_row = [(NO_CELL, NO_CELL, NO_CELL)] * first_day.day_of_week
+ rql = self.rset.printable_rql()
+ for daynum in xrange(0, first_day.days_in_month):
+ # build cells day
+ day = first_day + daynum
+ events = schedule.get(day)
+ if events:
+ current_row.append((AMPM_DAY % (daynum+1),) + self._build_ampm_cells(daynum, events))
+ else:
+ current_row.append((AMPM_DAY % (daynum+1),
+ AMPM_EMPTY % ("amCell", "am"),
+ AMPM_EMPTY % ("pmCell", "pm")))
+ # store & reset current row on Sundays
+ if day.day_of_week == Sunday:
+ url = self.build_url(rql=rql, vid='ampmcalendarweek',
+ year=day.year, week=day.isocalendar()[1])
+ weeklink = '<a href="%s">%s</a>' % (html_escape(url),
+ day.isocalendar()[1])
+ current_row.append(WEEKNUM_CELL % weeklink)
+ rows.append(current_row)
+ current_row = []
+ current_row.extend([(NO_CELL, NO_CELL, NO_CELL)] * (Sunday-day.day_of_week))
+ url = self.build_url(rql=rql, vid='ampmcalendarweek',
+ year=day.year, week=day.isocalendar()[1])
+ weeklink = '<a href="%s">%s</a>' % (html_escape(url),
+ day.isocalendar()[1])
+ current_row.append(WEEKNUM_CELL % weeklink)
+ rows.append(current_row)
+ # build two rows for each week: am & pm
+ formatted_rows = []
+ for row in rows:
+ week_title = row.pop()
+ day_row = [day for day, am, pm in row]
+ am_row = [am for day, am, pm in row]
+ pm_row = [pm for day, am, pm in row]
+ formatted_rows.append('<tr>%s%s</tr>'% (week_title, '\n'.join(day_row)))
+ formatted_rows.append('<tr class="amRow"><td> </td>%s</tr>'% '\n'.join(am_row))
+ formatted_rows.append('<tr class="pmRow"><td> </td>%s</tr>'% '\n'.join(pm_row))
+ # tigh everything together
+ url = self.build_url(rql=rql, vid='ampmcalendarmonth',
+ year=first_day.year, month=first_day.month)
+ monthlink = '<a href="%s">%s</a>' % (html_escape(url),
+ umonth)
+ return CALENDAR(self.req) % (monthlink, '\n'.join(formatted_rows))
+
+
+
+class AMPMWeekCalendarView(WeekCalendarView):
+ """this view renders a 3x1 calendars' table"""
+ id = 'ampmcalendarweek'
+ title = _('am/pm calendar (week)')
+
+ def build_calendar(self, schedule, weeks):
+ rql = self.rset.printable_rql()
+ w = self.w
+ _ = self.req._
+ for monday, sunday in weeks:
+ umonth = self.format_date(monday, '%B %Y')
+ url = self.build_url(rql=rql, vid='ampmcalendarmonth',
+ year=monday.year, month=monday.month)
+ monthlink = '<a href="%s">%s</a>' % (html_escape(url), umonth)
+ w(u'<tr>%s</tr>' % (
+ WEEK_TITLE % (_('week'), monday.isocalendar()[1], monthlink)))
+ w(u'<tr><th>%s</th><th> </th></tr>'% _(u'Date'))
+ for day in date_range(monday, sunday):
+ events = schedule.get(day)
+ style = day.day_of_week % 2 and "even" or "odd"
+ w(u'<tr class="%s">' % style)
+ if events:
+ hours = events.keys()
+ hours.sort()
+ w(AMPM_DAYWEEK % (
+ len(hours), _(WEEKDAYS[day.day_of_week]),
+ self.format_date(day)))
+ w(AMPM_WEEK_CELL % (
+ hours[0].hour, hours[0].minute,
+ '\n'.join(events[hours[0]])))
+ w(u'</tr>')
+ for hour in hours[1:]:
+ w(u'<tr class="%s">%s</tr>'% (
+ style, AMPM_WEEK_CELL % (hour.hour, hour.minute,
+ '\n'.join(events[hour]))))
+ else:
+ w(AMPM_DAYWEEK_EMPTY % (
+ _(WEEKDAYS[day.day_of_week]),
+ self.format_date(day)))
+ w(WEEK_EMPTY_CELL)
+ w(u'</tr>')
+
+
+SMALL_CALENDARS_PAGE = u"""<table class="smallCalendars">
+<tr><td class="calendar">%s</td><td class="calendar">%s</td><td class="calendar">%s</td></tr>
+<tr><td class="calendar">%s</td><td class="calendar">%s</td><td class="calendar">%s</td></tr>
+<tr><td class="calendar">%s</td><td class="calendar">%s</td><td class="calendar">%s</td></tr>
+</table>
+"""
+
+BIG_CALENDARS_PAGE = u"""<table class="bigCalendars">
+<tr><td class="calendar">%s</td></tr>
+<tr><td class="calendar">%s</td></tr>
+<tr><td class="calendar">%s</td></tr>
+</table>
+"""
+
+WEEKNUM_CELL = u'<td class="weeknum">%s</td>'
+
+def CALENDAR(req):
+ _ = req._
+ WEEKNUM_HEADER = u'<th class="weeknum">%s</th>' % _('week')
+ CAL_HEADER = WEEKNUM_HEADER + u' \n'.join([u'<th class="weekday">%s</th>' % _(day)[0].upper()
+ for day in WEEKDAYS])
+ return u"""<table>
+<tr><th class="month" colspan="8">%%s</th></tr>
+<tr>
+ %s
+</tr>
+%%s
+</table>
+""" % (CAL_HEADER,)
+
+
+DAY_TEMPLATE = """<tr><td class="weekday">%(daylabel)s</td><td>%(dmydate)s</td><td>%(dayschedule)s</td>
+"""
+
+NO_CELL = u'<td class="noday"></td>'
+EMPTY_CELL = u'<td class="cellEmpty"><span class="cellTitle">%s</span></td>'
+CELL = u'<td class="cell"><span class="cellTitle">%s</span><div class="cellContent">%s</div></td>'
+
+AMPM_DAY = u'<td class="cellDay">%d</td>'
+AMPM_EMPTY = u'<td class="%sEmpty"><span class="cellTitle">%s</span></td>'
+AMPM_CONTENT = u'<td class="%s"><span class="cellTitle">%s</span><div class="cellContent">%s</div></td>'
+
+WEEK_TITLE = u'<th class="weekTitle" colspan="2">%s %s (%s)</th>'
+WEEK_EMPTY_CELL = u'<td class="weekEmptyCell"> </td>'
+WEEK_CELL = u'<td class="weekCell"><div class="cellContent">%s</div></td>'
+
+AMPM_DAYWEEK_EMPTY = u'<td>%s %s</td>'
+AMPM_DAYWEEK = u'<td rowspan="%d">%s %s</td>'
+AMPM_WEEK_CELL = u'<td class="ampmWeekCell"><div class="cellContent">%02d:%02d - %s</div></td>'
--- a/web/views/primary.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/primary.py Tue May 05 17:13:37 2009 +0200
@@ -60,7 +60,10 @@
'order': cls.rdisplay.get_timestamp()}
cls.rdisplay.tag_relation(displayinfo, (X, rschema, Y),
role)
- displayinfo.setdefault('label', '%s_%s' % (rschema, role))
+ if role == 'subject':
+ displayinfo.setdefault('label', rschema.type)
+ else:
+ displayinfo.setdefault('label', '%s_%s' % (rschema, role))
def html_headers(self):
"""return a list of html headers (eg something to be inserted between
--- a/web/views/startup.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/startup.py Tue May 05 17:13:37 2009 +0200
@@ -6,23 +6,34 @@
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
+_ = unicode
from logilab.common.textutils import unormalize
from logilab.mtconverter import html_escape
-from cubicweb.common.uilib import ureport_as_html, ajax_replace_url
from cubicweb.view import StartupView
from cubicweb.selectors import match_user_groups
-from cubicweb.web.httpcache import EtagHTTPCacheManager
+from cubicweb.common.uilib import ureport_as_html
+from cubicweb.web import ajax_replace_url, uicfg, httpcache
from cubicweb.web.views.management import SecurityViewMixIn
-from copy import deepcopy
-_ = unicode
class ManageView(StartupView):
id = 'manage'
title = _('manage')
- http_cache_manager = EtagHTTPCacheManager
+ http_cache_manager = httpcache.EtagHTTPCacheManager
+
+ @classmethod
+ def vreg_initialization_completed(cls):
+ for eschema in cls.schema.entities():
+ if eschema.schema_entity():
+ uicfg.etypecat.setdefault(eschema, 'schema')
+ elif eschema.is_subobject(strict=True):
+ uicfg.etypecat.setdefault(eschema, 'subobject')
+ elif eschema.meta:
+ uicfg.etypecat.setdefault(eschema, 'system')
+ else:
+ uicfg.etypecat.setdefault(eschema, 'application')
def display_folders(self):
return False
@@ -89,15 +100,15 @@
if manager:
self.w(u'<tr><th colspan="4">%s</th></tr>\n' % self.req._('application entities'))
self.entity_types_table(eschema for eschema in schema.entities()
- if not eschema.meta and not eschema.is_subobject(strict=True))
+ if uicfg.etypecat.get(eschema) == 'application')
if manager:
self.w(u'<tr><th colspan="4">%s</th></tr>\n' % self.req._('system entities'))
self.entity_types_table(eschema for eschema in schema.entities()
- if eschema.meta and not eschema.schema_entity())
+ if uicfg.etypecat.get(eschema) == 'system')
if 'CWAttribute' in schema: # check schema support
self.w(u'<tr><th colspan="4">%s</th></tr>\n' % self.req._('schema entities'))
- self.entity_types_table(schema.eschema(etype)
- for etype in schema.schema_entity_types())
+ self.entity_types_table(eschema for eschema in schema.entities()
+ if uicfg.etypecat.get(eschema) == 'schema')
self.w(u'</table>')
def entity_types_table(self, eschemas):
--- a/web/views/tableview.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/tableview.py Tue May 05 17:13:37 2009 +0200
@@ -14,7 +14,8 @@
from cubicweb.selectors import nonempty_rset, match_form_params
from cubicweb.utils import make_uid
from cubicweb.view import EntityView, AnyRsetView
-from cubicweb.common.uilib import toggle_action, limitsize, jsonize, htmlescape
+from cubicweb.common.uilib import toggle_action, limitsize, htmlescape
+from cubicweb.web import jsonize
from cubicweb.web.htmlwidgets import (TableWidget, TableColumn, MenuWidget,
PopupBoxMenu, BoxLink)
from cubicweb.web.facet import prepare_facets_rqlst, filter_hiddens
@@ -44,7 +45,7 @@
'displayfilter': displayfilter})
return self.show_hide_actions(divid, not hidden)
return ()
-
+
def _generate_form(self, divid, baserql, fwidgets, hidden=True, vidargs={}):
"""display a form to filter table's content. This should only
occurs when a context eid is given
@@ -88,7 +89,7 @@
else:
displaycols = range(len(self.rset.syntax_tree().children[0].selection))
return displaycols
-
+
def call(self, title=None, subvid=None, displayfilter=None, headers=None,
displaycols=None, displayactions=None, actions=(), divid=None,
cellvids=None, cellattrs=None):
@@ -169,7 +170,7 @@
if currentlydisplayed:
return [(showhide, showlabel, 'hidden', '%sShow' % divid),
(showhide, hidelabel, None, '%sHide' % divid)]
- return [(showhide, showlabel, None, '%sShow' % divid),
+ return [(showhide, showlabel, None, '%sShow' % divid),
(showhide, hidelabel, 'hidden', '%sHide' % divid)]
def render_actions(self, divid, actions):
@@ -184,7 +185,7 @@
menu.append(BoxLink(url, label, klass, ident=ident, escape=True))
box.render(w=self.w)
self.w(u'<div class="clear"/>')
-
+
def get_columns(self, rqlstdescr, displaycols, headers, subvid, cellvids,
cellattrs, mainindex):
columns = []
@@ -218,11 +219,11 @@
# add column
columns.append(column)
return columns
-
+
def render(self, cellvid, row, col, w):
self.view('cell', self.rset, row=row, col=col, cellvid=cellvid, w=w)
-
+
def get_rows(self):
return self.rset
@@ -251,12 +252,12 @@
finalview = 'editable-final'
title = _('editable-table')
-
+
class CellView(EntityView):
__select__ = nonempty_rset()
-
+
id = 'cell'
-
+
def cell_call(self, row, col, cellvid=None):
"""
:param row, col: indexes locating the cell value in view's result set
@@ -277,13 +278,13 @@
class InitialTableView(TableView):
"""same display as table view but consider two rql queries :
-
+
* the default query (ie `rql` form parameter), which is only used to select
this view and to build the filter form. This query should have the same
structure as the actual without actual restriction (but link to
restriction variables) and usually with a limit for efficiency (limit set
to 2 is advised)
-
+
* the actual query (`actualrql` form parameter) whose results will be
displayed with default restrictions set
"""
@@ -292,7 +293,7 @@
# should not be displayed in possible view since it expects some specific
# parameters
title = None
-
+
def call(self, title=None, subvid=None, headers=None, divid=None,
displaycols=None, displayactions=None):
"""Dumps a table displaying a composite query"""
--- a/web/views/xbel.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/xbel.py Tue May 05 17:13:37 2009 +0200
@@ -11,18 +11,18 @@
from cubicweb.selectors import implements
from cubicweb.view import EntityView
-from cubicweb.web.views.xmlrss import XmlView
+from cubicweb.web.views.xmlrss import XMLView
-class XbelView(XmlView):
+class XbelView(XMLView):
id = 'xbel'
title = _('xbel')
templatable = False
- content_type = 'text/xml' #application/xbel+xml
-
+ content_type = 'text/xml' #application/xbel+xml
+
def cell_call(self, row, col):
self.wview('xbelitem', self.rset, row=row, col=col)
-
+
def call(self):
"""display a list of entities by calling their <item_vid> view"""
title = self.page_title()
@@ -34,7 +34,7 @@
for i in xrange(self.rset.rowcount):
self.cell_call(i, 0)
self.w(u"</xbel>")
-
+
class XbelItemView(EntityView):
id = 'xbelitem'
@@ -48,10 +48,10 @@
def url(self, entity):
return entity.absolute_url()
-
+
class XbelItemBookmarkView(XbelItemView):
__select__ = implements('Bookmark')
def url(self, entity):
return entity.actual_url()
-
+
--- a/web/views/xmlrss.py Tue May 05 12:07:42 2009 +0200
+++ b/web/views/xmlrss.py Tue May 05 17:13:37 2009 +0200
@@ -22,7 +22,7 @@
# base xml views ##############################################################
-class XmlView(EntityView):
+class XMLView(EntityView):
"""xml view for entities"""
id = 'xml'
title = _('xml')
@@ -43,7 +43,7 @@
self.w(u'</%s>\n' % self.xml_root)
-class XmlItemView(EntityView):
+class XMLItemView(EntityView):
id = 'xmlitem'
def cell_call(self, row, col):
@@ -67,7 +67,7 @@
self.w(u'</%s>\n' % (entity.e_schema))
-class XmlRsetView(AnyRsetView):
+class XMLRsetView(AnyRsetView):
"""dumps raw rset as xml"""
id = 'rsetxml'
title = _('xml export')
@@ -142,7 +142,7 @@
self.w(u'<a href="%s"><img src="%s" alt="rss"/></a>\n' % (xml_escape(url), rss))
-class RssView(XmlView):
+class RSSView(XMLView):
id = 'rss'
title = _('rss')
templatable = False
@@ -176,7 +176,7 @@
self.wview('rssitem', self.rset, row=row, col=col)
-class RssItemView(EntityView):
+class RSSItemView(EntityView):
id = 'rssitem'
date_format = '%%Y-%%m-%%dT%%H:%%M%+03i:00' % (timezone / 3600)
add_div_section = False
--- a/web/wdoc/custom_view_rss_fr.rst Tue May 05 12:07:42 2009 +0200
+++ b/web/wdoc/custom_view_rss_fr.rst Tue May 05 17:13:37 2009 +0200
@@ -14,5 +14,5 @@
:raw-html:`<p><a class="reference"
href="view?vid=rss&rql=Any+X%2CM+WHERE+X+modification_date+M+ORDERBY+M+DESC+LIMIT+30"><img
-alt="rss" src="data/rss.png"> latest changes</a></p>`
+alt="rss" src="data/rss.png"> latest changes</img></a></p>`
--- a/web/widgets.py Tue May 05 12:07:42 2009 +0200
+++ b/web/widgets.py Tue May 05 17:13:37 2009 +0200
@@ -144,14 +144,15 @@
def render_help(self, entity):
"""render a help message about the (edited) field"""
req = entity.req
- help = [u'<br/>']
+ help = [u'<div class="helper">']
descr = self.description or self.rschema.rproperty(self.subjtype, self.objtype, 'description')
if descr:
- help.append(u'<span class="helper">%s</span>' % req._(descr))
+ help.append(u'<span>%s</span>' % req._(descr))
example = self.render_example(req)
if example:
- help.append(u'<span class="helper">(%s: %s)</span>'
+ help.append(u'<span>(%s: %s)</span>'
% (req._('sample format'), example))
+ help.append(u'</div>')
return u' '.join(help)
def render_example(self, req):
@@ -750,14 +751,15 @@
def render_help(self, entity):
"""calendar popup widget"""
req = entity.req
- help = [ u'<br/>' ]
+ help = [ u'<div class="helper">' ]
descr = self.rschema.rproperty(self.subjtype, self.objtype, 'description')
if descr:
- help.append('<span class="helper">%s</span>' % req._(descr))
+ help.append('<span>%s</span>' % req._(descr))
example = self.render_example(req)
if example:
- help.append('<span class="helper">(%s: %s)</span>'
+ help.append('<span>(%s: %s)</span>'
% (req._('sample format'), example))
+ help.append(u'</div>')
return u' '.join(help)
def render_calendar_popup(self, entity):