--- a/.hgtags Thu May 14 18:12:45 2009 +0200
+++ b/.hgtags Mon May 18 10:09:06 2009 +0200
@@ -26,3 +26,5 @@
9e98dec0768b87363a7826a04636dc161ed0ec7d cubicweb-debian-version-3_1_3-1
e0e0a1c3d80f4fbf4bbd55066278e467b75df8a4 cubicweb-version-3_1_4
0e132fbae9cc5e004f4b79a8b842addad43519a7 cubicweb-debian-version-3_1_4-1
+c14231e3a4f9120e2bb6a1d8690252fff5e48131 cubicweb-version-3_2_0
+c9c492787a8aa1b7916e22eb6498cba1c8fa316c cubicweb-debian-version-3_2_0-1
--- a/_exceptions.py Thu May 14 18:12:45 2009 +0200
+++ b/_exceptions.py Mon May 18 10:09:06 2009 +0200
@@ -26,9 +26,9 @@
"""a misconfiguration error"""
class InternalError(CubicWebException):
- """base class for exceptions which should not occurs"""
+ """base class for exceptions which should not occurs"""
-class SecurityError(CubicWebException):
+class SecurityError(CubicWebException):
"""base class for cubicweb server security exception"""
class RepositoryError(CubicWebException):
@@ -39,7 +39,7 @@
class CubicWebRuntimeError(CubicWebException):
"""base class for runtime exceptions"""
-
+
# repository exceptions #######################################################
class ConnectionError(RepositoryError):
@@ -53,7 +53,7 @@
class BadConnectionId(ConnectionError):
"""raised when a bad connection id is given or when an attempt to establish
a connection failed"""
-
+
BadSessionId = BadConnectionId # XXX bw compat for pyro connections
class UnknownEid(RepositoryError):
@@ -68,7 +68,7 @@
"""no source support a relation type"""
msg = 'No source supports %r relation\'s type'
-
+
# security exceptions #########################################################
class Unauthorized(SecurityError):
@@ -80,7 +80,7 @@
var = None
#def __init__(self, *args):
# self.args = args
-
+
def __str__(self):
try:
if self.args and len(self.args) == 2:
@@ -90,7 +90,7 @@
return self.msg
except Exception, ex:
return str(ex)
-
+
# source exceptions ###########################################################
class EidNotInSource(SourceException):
@@ -98,8 +98,8 @@
source has failed
"""
msg = 'No entity with eid %s in %s'
-
-
+
+
# registry exceptions #########################################################
class RegistryException(CubicWebException):
@@ -110,16 +110,16 @@
this is usually a programming/typo error...
"""
-
+
class ObjectNotFound(RegistryException):
"""raised when an unregistered object is requested
this may be a programming/typo or a misconfiguration error
"""
-
+
# class ViewNotFound(ObjectNotFound):
# """raised when an unregistered view is called"""
-
+
class NoSelectableObject(RegistryException):
"""some views with the given vid have been found but no
one is applyable to the result set
@@ -144,5 +144,5 @@
"""server execution control error (already started, not running...)"""
# pylint: disable-msg=W0611
-from logilab.common.clcommands import BadCommandUsage
+from logilab.common.clcommands import BadCommandUsage
--- a/common/__init__.py Thu May 14 18:12:45 2009 +0200
+++ b/common/__init__.py Mon May 18 10:09:06 2009 +0200
@@ -15,38 +15,38 @@
class COMMA_JOIN(FunctionDescr):
supported_backends = ('postgres', 'sqlite',)
rtype = 'String'
-
+
@classmethod
def st_description(cls, funcnode):
return ', '.join(term.get_description()
for term in iter_funcnode_variables(funcnode))
-
+
register_function(COMMA_JOIN) # XXX do not expose?
class CONCAT_STRINGS(COMMA_JOIN):
aggregat = True
-
+
register_function(CONCAT_STRINGS) # XXX bw compat
class GROUP_CONCAT(CONCAT_STRINGS):
supported_backends = ('mysql', 'postgres', 'sqlite',)
-
+
register_function(GROUP_CONCAT)
class LIMIT_SIZE(FunctionDescr):
supported_backends = ('postgres', 'sqlite',)
rtype = 'String'
-
+
@classmethod
def st_description(cls, funcnode):
return funcnode.children[0].get_description()
-
+
register_function(LIMIT_SIZE)
class TEXT_LIMIT_SIZE(LIMIT_SIZE):
supported_backends = ('mysql', 'postgres', 'sqlite',)
-
+
register_function(TEXT_LIMIT_SIZE)
--- a/common/i18n.py Thu May 14 18:12:45 2009 +0200
+++ b/common/i18n.py Mon May 18 10:09:06 2009 +0200
@@ -90,4 +90,3 @@
except Exception:
continue
return errors
-
--- a/common/mail.py Thu May 14 18:12:45 2009 +0200
+++ b/common/mail.py Mon May 18 10:09:06 2009 +0200
@@ -1,7 +1,7 @@
"""Common utilies to format / semd emails.
: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"
--- a/common/migration.py Thu May 14 18:12:45 2009 +0200
+++ b/common/migration.py Mon May 18 10:09:06 2009 +0200
@@ -2,7 +2,7 @@
version
: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"
@@ -125,10 +125,10 @@
def repo_connect(self):
return self.config.repository()
-
+
def migrate(self, vcconf, toupgrade, options):
"""upgrade the given set of cubes
-
+
`cubes` is an ordered list of 3-uple:
(cube, fromversion, toversion)
"""
@@ -149,23 +149,23 @@
'versions_map': vmap})
self.scripts_session(scripts)
else:
- print 'no migration script to execute'
+ print 'no migration script to execute'
def shutdown(self):
pass
-
+
def __getattribute__(self, name):
try:
return object.__getattribute__(self, name)
except AttributeError:
cmd = 'cmd_%s' % name
if hasattr(self, cmd):
- meth = getattr(self, cmd)
+ meth = getattr(self, cmd)
return lambda *args, **kwargs: self.interact(args, kwargs,
meth=meth)
raise
raise AttributeError(name)
-
+
def interact(self, args, kwargs, meth):
"""execute the given method according to user's confirmation"""
msg = 'execute command: %s(%s) ?' % (
@@ -224,7 +224,7 @@
except ImportError:
# readline not available
pass
- else:
+ else:
readline.set_completer(Completer(local_ctx).complete)
readline.parse_and_bind('tab: complete')
histfile = os.path.join(os.environ["HOME"], ".eshellhist")
@@ -256,7 +256,7 @@
else:
context[attr[4:]] = getattr(self, attr)
return context
-
+
def process_script(self, migrscript, funcname=None, *args, **kwargs):
"""execute a migration script
in interactive mode, display the migration script path, ask for
@@ -280,7 +280,7 @@
self.critical('no %s in script %s', funcname, migrscript)
return None
return func(*args, **kwargs)
-
+
def scripts_session(self, migrscripts):
"""execute some scripts in a transaction"""
try:
@@ -311,7 +311,7 @@
def cmd_option_type_changed(self, optname, oldtype, newvalue):
"""a configuration option's type has changed"""
self._option_changes.append(('typechanged', optname, oldtype, newvalue))
-
+
def cmd_add_cubes(self, cubes):
"""modify the list of used cubes in the in-memory config
returns newly inserted cubes, including dependencies
@@ -319,7 +319,7 @@
if isinstance(cubes, basestring):
cubes = (cubes,)
origcubes = self.config.cubes()
- newcubes = [p for p in self.config.expand_cubes(cubes)
+ newcubes = [p for p in self.config.expand_cubes(cubes)
if not p in origcubes]
if newcubes:
for cube in cubes:
@@ -340,7 +340,7 @@
assert cube in removed, \
"can't remove cube %s, used as a dependancy" % cube
return removed
-
+
def rewrite_configuration(self):
# import locally, show_diffs unavailable in gae environment
from cubicweb.toolsutils import show_diffs
--- a/common/test/unittest_mail.py Thu May 14 18:12:45 2009 +0200
+++ b/common/test/unittest_mail.py Mon May 18 10:09:06 2009 +0200
@@ -17,14 +17,14 @@
Another solution would be to use $LOGNAME, $USER or $USERNAME
"""
return pwd.getpwuid(os.getuid())[0]
-
+
class EmailTC(EnvBasedTC):
def test_format_mail(self):
self.set_option('sender-addr', 'bim@boum.fr')
self.set_option('sender-name', 'BimBam')
-
+
mail = format_mail({'name': 'oim', 'email': 'oim@logilab.fr'},
['test@logilab.fr'], u'un petit cöucou', u'bïjour',
config=self.config)
@@ -47,7 +47,7 @@
self.assertEquals(msg.get('reply-to'), u'oim <oim@logilab.fr>, BimBam <bim@boum.fr>')
self.assertEquals(msg.get_payload(decode=True), u'un petit cöucou')
-
+
def test_format_mail_euro(self):
mail = format_mail({'name': u'oîm', 'email': u'oim@logilab.fr'},
['test@logilab.fr'], u'un petit cöucou €', u'bïjour €')
@@ -92,7 +92,7 @@
self.assertEquals(msg.get('reply-to'), u'tutu <tutu@logilab.fr>')
# set sender name and address as expected
self.set_option('sender-name', 'cubicweb-test')
- self.set_option('sender-addr', 'cubicweb-test@logilab.fr')
+ self.set_option('sender-addr', 'cubicweb-test@logilab.fr')
# anonymous notification: no name and no email specified
msg = format_mail({'name': u'', 'email': u''},
['test@logilab.fr'], u'un petit cöucou €', u'bïjour €',
@@ -119,4 +119,4 @@
if __name__ == '__main__':
unittest_main()
-
+
--- a/common/test/unittest_migration.py Thu May 14 18:12:45 2009 +0200
+++ b/common/test/unittest_migration.py Mon May 18 10:09:06 2009 +0200
@@ -24,7 +24,7 @@
def cube_migration_scripts_dir(cls, cube):
return TMIGRDIR
-
+
class MigrationToolsTC(TestCase):
def setUp(self):
self.config = MigrTestConfig('data')
@@ -32,7 +32,7 @@
self.config.load_schema = lambda expand_cubes=False: Schema('test')
self.config.__class__.cubicweb_vobject_path = frozenset()
self.config.__class__.cube_vobject_path = frozenset()
-
+
def test_migration_files_base(self):
self.assertListEquals(migration_files(self.config, [('cubicweb', (2,3,0), (2,4,0)),
('TEMPLATE', (0,0,2), (0,0,3))]),
@@ -48,7 +48,7 @@
[SMIGRDIR+'bootstrapmigration_repository.py',
SMIGRDIR+'2.6.0_Any.sql',
TMIGRDIR+'0.0.4_Any.py'])
-
+
## def test_migration_files_overlap(self):
## self.assertListEquals(migration_files(self.config, (2,4,0), (2,10,2),
## (0,0,2), (0,1,2)),
@@ -62,7 +62,7 @@
## TMIGRDIR+'0.1.0_repository.py',
## TMIGRDIR+'0.1.2_Any.py',
## SMIGRDIR+'2.10.1_2.10.2_Any.sql'])
-
+
def test_migration_files_for_mode(self):
from cubicweb.server.migractions import ServerMigrationHelper
self.assertIsInstance(self.config.migration_handler(), ServerMigrationHelper)
--- a/common/test/unittest_mixins.py Thu May 14 18:12:45 2009 +0200
+++ b/common/test/unittest_mixins.py Mon May 18 10:09:06 2009 +0200
@@ -8,7 +8,7 @@
{'x': s.eid})
es = self.user().wf_state('activated')
self.assertEquals(es.state_of[0].name, 'CWUser')
-
+
def test_wf_transition(self):
t = self.add_entity('Transition', name=u'deactivate')
self.execute('SET X transition_of ET WHERE ET name "Bookmark", X eid %(x)s',
@@ -20,6 +20,6 @@
user = self.user()
user.change_state(user.wf_state('deactivated').eid)
self.assertEquals(user.state, 'deactivated')
-
+
if __name__ == '__main__':
unittest_main()
--- a/cwconfig.py Thu May 14 18:12:45 2009 +0200
+++ b/cwconfig.py Mon May 18 10:09:06 2009 +0200
@@ -8,7 +8,7 @@
.. envvar:: CW_CUBES_PATH
Augments the default search path for cubes
-
+
"""
__docformat__ = "restructuredtext en"
--- a/debian/changelog Thu May 14 18:12:45 2009 +0200
+++ b/debian/changelog Mon May 18 10:09:06 2009 +0200
@@ -1,3 +1,9 @@
+cubicweb (3.2.0-1) unstable; urgency=low
+
+ * new upstream release
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr> Thu, 14 May 2009 12:31:06 +0200
+
cubicweb (3.1.4-1) unstable; urgency=low
* new upstream release
--- a/debian/control Thu May 14 18:12:45 2009 +0200
+++ b/debian/control Mon May 18 10:09:06 2009 +0200
@@ -75,7 +75,7 @@
Package: cubicweb-common
Architecture: all
XB-Python-Version: ${python:Versions}
-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)
+Depends: ${python:Depends}, graphviz, gettext, python-logilab-mtconverter (>= 0.6.0), python-logilab-common (>= 0.40.0), python-yams (>= 0.22.0), python-rql (>= 0.22.0)
Recommends: python-simpletal (>= 4.0), python-lxml
Conflicts: cubicweb-core
Replaces: cubicweb-core
--- a/debian/cubicweb-common.install.in Thu May 14 18:12:45 2009 +0200
+++ b/debian/cubicweb-common.install.in Mon May 18 10:09:06 2009 +0200
@@ -1,17 +1,4 @@
debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/common/ usr/lib/PY_VERSION/site-packages/cubicweb
debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/entities/ usr/lib/PY_VERSION/site-packages/cubicweb
debian/tmp/usr/share/cubicweb/cubes/shared/i18n usr/share/cubicweb/cubes/shared/
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/rset.py usr/share/pyshared/cubicweb
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/gettext.py usr/share/pyshared/cubicweb
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/toolsutils.py usr/share/pyshared/cubicweb
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/cwvreg.py usr/share/pyshared/cubicweb
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/_exceptions.py usr/share/pyshared/cubicweb
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/schemaviewer.py usr/share/pyshared/cubicweb
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/dbapi.py usr/share/pyshared/cubicweb
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/cwconfig.py usr/share/pyshared/cubicweb
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/__init__.py usr/share/pyshared/cubicweb
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/md5crypt.py usr/share/pyshared/cubicweb
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/schema.py usr/share/pyshared/cubicweb
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/interfaces.py usr/share/pyshared/cubicweb
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/vregistry.py usr/share/pyshared/cubicweb
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/__pkginfo__.py usr/share/pyshared/cubicweb
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/*.py usr/share/pyshared/cubicweb
--- a/debian/cubicweb-dev.install.in Thu May 14 18:12:45 2009 +0200
+++ b/debian/cubicweb-dev.install.in Mon May 18 10:09:06 2009 +0200
@@ -1,7 +1,2 @@
debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/devtools/ usr/lib/PY_VERSION/site-packages/cubicweb/
debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/skeleton/ usr/lib/PY_VERSION/site-packages/cubicweb/
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/test usr/lib/PY_VERSION/site-packages/cubicweb/
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/common/test usr/lib/PY_VERSION/site-packages/cubicweb/common/
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/server/test usr/lib/PY_VERSION/site-packages/cubicweb/server/
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/sobjects/test usr/lib/PY_VERSION/site-packages/cubicweb/sobjects/
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/web/test usr/lib/PY_VERSION/site-packages/cubicweb/web/
--- a/debian/rules Thu May 14 18:12:45 2009 +0200
+++ b/debian/rules Mon May 18 10:09:06 2009 +0200
@@ -39,13 +39,19 @@
# Put all the python library and data in cubicweb-common
# and scripts in cubicweb-server
dh_install -vi
+ # cwctl in the cubicweb-ctl package
+ rm -f debian/cubicweb-common/usr/share/pyshared/cubicweb/cwctl.py
+ rm -f debian/cubicweb-common/usr/share/pyshared/cubicweb/hercule.py
+
dh_lintian
# Remove unittests directory (should be available in cubicweb-dev only)
- rm -rf debian/cubicweb-server/usr/lib/${PY_VERSION}/site-packages/cubicweb/server/test
- rm -rf debian/cubicweb-server/usr/lib/${PY_VERSION}/site-packages/cubicweb/sobjects/test
- rm -rf debian/cubicweb-web/usr/lib/${PY_VERSION}/site-packages/cubicweb/web/test
- rm -rf debian/cubicweb-common/usr/lib/${PY_VERSION}/site-packages/cubicweb/common/test
+ rm -rf debian/cubicweb-server/usr/share/pyshared/cubicweb/server/test
+ rm -rf debian/cubicweb-server/usr/share/pyshared/cubicweb/sobjects/test
+ rm -rf debian/cubicweb-dev/usr/share/pyshared/cubicweb/devtools/test
+ rm -rf debian/cubicweb-web/usr/share/pyshared/cubicweb/web/test
+ rm -rf debian/cubicweb-common/usr/share/pyshared/cubicweb/common/test
+ rm -rf debian/cubicweb-common/usr/share/pyshared/cubicweb/entities/test
# cubes directory must be managed as a valid python module
touch debian/cubicweb-common/usr/share/cubicweb/cubes/__init__.py
--- a/devtools/__init__.py Thu May 14 18:12:45 2009 +0200
+++ b/devtools/__init__.py Mon May 18 10:09:06 2009 +0200
@@ -59,10 +59,10 @@
'group': 'main', 'inputlevel': 1,
}),
))
-
+
if not os.environ.get('APYCOT_ROOT'):
REGISTRY_DIR = normpath(join(CW_SOFTWARE_ROOT, '../cubes'))
-
+
def __init__(self, appid, log_threshold=logging.CRITICAL+10):
ServerConfiguration.__init__(self, appid)
self.global_set_option('log-file', None)
@@ -71,7 +71,7 @@
self.load_cwctl_plugins()
anonymous_user = TwistedConfiguration.anonymous_user.im_func
-
+
@property
def apphome(self):
if exists(self.appid):
@@ -79,7 +79,7 @@
# application cube test
return abspath('..')
appdatahome = apphome
-
+
def main_config_file(self):
"""return application's control configuration file"""
return join(self.apphome, '%s.conf' % self.name)
@@ -116,7 +116,7 @@
if not sources:
sources = DEFAULT_SOURCES
return sources
-
+
def load_defaults(self):
super(TestServerConfiguration, self).load_defaults()
# note: don't call global set option here, OptionManager may not yet be initialized
@@ -146,25 +146,25 @@
def available_languages(self, *args):
return ('en', 'fr', 'de')
-
+
def ext_resources_file(self):
"""return application's external resources file"""
return join(self.apphome, 'data', 'external_resources')
-
+
def pyro_enabled(self):
# but export PYRO_MULTITHREAD=0 or you get problems with sqlite and threads
return True
class ApptestConfiguration(BaseApptestConfiguration):
-
+
def __init__(self, appid, log_threshold=logging.CRITICAL, sourcefile=None):
BaseApptestConfiguration.__init__(self, appid, log_threshold=log_threshold)
self.init_repository = sourcefile is None
self.sourcefile = sourcefile
import re
self.global_set_option('embed-allowed', re.compile('.*'))
-
+
class RealDatabaseConfiguration(ApptestConfiguration):
init_repository = False
@@ -180,7 +180,7 @@
'password': u'gingkow',
},
}
-
+
def __init__(self, appid, log_threshold=logging.CRITICAL, sourcefile=None):
ApptestConfiguration.__init__(self, appid)
self.init_repository = False
@@ -191,7 +191,7 @@
By default, we run tests with the sqlite DB backend.
One may use its own configuration by just creating a
'sources' file in the test directory from wich tests are
- launched.
+ launched.
"""
self._sources = self.sourcesdef
return self._sources
@@ -220,11 +220,11 @@
"""
return type('MyRealDBConfig', (RealDatabaseConfiguration,),
{'sourcesdef': read_config(filename)})
-
+
class LivetestConfiguration(BaseApptestConfiguration):
init_repository = False
-
+
def __init__(self, cube=None, sourcefile=None, pyro_name=None,
log_threshold=logging.CRITICAL):
TestServerConfiguration.__init__(self, cube, log_threshold=log_threshold)
@@ -254,7 +254,7 @@
return False
CubicWebConfiguration.cls_adjust_sys_path()
-
+
def install_sqlite_path(querier):
"""This patch hotfixes the following sqlite bug :
- http://www.sqlite.org/cvstrac/tktview?tn=1327,33
@@ -331,7 +331,7 @@
os.remove('%s-cube' % dbfile)
except OSError:
pass
-
+
def init_test_database_sqlite(config, source, vreg=None):
"""initialize a fresh sqlite databse used for testing purpose"""
import shutil
--- a/devtools/_apptest.py Thu May 14 18:12:45 2009 +0200
+++ b/devtools/_apptest.py Mon May 18 10:09:06 2009 +0200
@@ -1,7 +1,7 @@
"""Hidden internals for the devtools.apptest module
: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"
@@ -20,7 +20,7 @@
from cubicweb.devtools import ApptestConfiguration, init_test_database
from cubicweb.devtools.fake import FakeRequest
-
+
SYSTEM_ENTITIES = ('CWGroup', 'CWUser',
'CWAttribute', 'CWRelation',
'CWConstraint', 'CWConstraintType', 'CWProperty',
@@ -35,7 +35,7 @@
'is', 'is_instance_of', 'owned_by', 'created_by', 'specializes',
# workflow related
'state_of', 'transition_of', 'initial_state', 'allowed_transition',
- 'destination_state', 'in_state', 'wf_info_for', 'from_state', 'to_state',
+ 'destination_state', 'in_state', 'wf_info_for', 'from_state', 'to_state',
'condition',
# permission
'in_group', 'require_group', 'require_permission',
@@ -46,7 +46,7 @@
'relation_type', 'from_entity', 'to_entity',
'constrained_by', 'cstrtype', 'widget',
# deducted from other relations
- 'primary_email',
+ 'primary_email',
)
def unprotected_entities(app_schema, strict=False):
@@ -58,7 +58,7 @@
protected_entities = yams.schema.BASE_TYPES.union(set(SYSTEM_ENTITIES))
entities = set(app_schema.entities())
return entities - protected_entities
-
+
def ignore_relations(*relations):
global SYSTEM_RELATIONS
@@ -68,7 +68,7 @@
"""TestEnvironment defines a context (e.g. a config + a given connection) in
which the tests are executed
"""
-
+
def __init__(self, appid, reporter=None, verbose=False,
configcls=ApptestConfiguration, requestcls=FakeRequest):
config = configcls(appid)
@@ -114,7 +114,7 @@
self.cnx.vreg = self.vreg
self.cnx.login = source['db-user']
self.cnx.password = source['db-password']
-
+
def create_user(self, login, groups=('users',), req=None):
req = req or self.create_request()
@@ -140,7 +140,7 @@
if login == self.vreg.config.anonymous_user()[0]:
self.cnx.anonymous_connection = True
return self.cnx
-
+
def restore_connection(self):
if not self.cnx is self._orig_cnx:
try:
@@ -157,7 +157,7 @@
"""
req = req or self.create_request(rql=rql)
return self.cnx.cursor(req).execute(unicode(rql), args, eidkey)
-
+
def create_request(self, rql=None, **kwargs):
"""executes <rql>, builds a resultset, and returns a
couple (rset, req) where req is a FakeRequest
@@ -167,14 +167,14 @@
req = self.requestcls(self.vreg, form=kwargs)
req.set_connection(self.cnx)
return req
-
+
def get_rset_and_req(self, rql, optional_args=None, args=None, eidkey=None):
"""executes <rql>, builds a resultset, and returns a
couple (rset, req) where req is a FakeRequest
"""
return (self.execute(rql, args, eidkey),
self.create_request(rql=rql, **optional_args or {}))
-
+
def check_view(self, rql, vid, optional_args, template='main'):
"""checks if vreg.view() raises an exception in this environment
@@ -183,7 +183,7 @@
"""
return self.call_view(vid, rql,
template=template, optional_args=optional_args)
-
+
def call_view(self, vid, rql, template='main', optional_args=None):
"""shortcut for self.vreg.view()"""
assert template
@@ -227,7 +227,7 @@
yield action
class ExistingTestEnvironment(TestEnvironment):
-
+
def __init__(self, appid, sourcefile, verbose=False):
config = ApptestConfiguration(appid, sourcefile=sourcefile)
if verbose:
@@ -237,12 +237,12 @@
self.cnx = init_test_database(driver=source['db-driver'],
vreg=self.vreg)[1]
if verbose:
- print "init done"
+ print "init done"
self.app = CubicWebPublisher(config, vreg=self.vreg)
self.verbose = verbose
# this is done when the publisher is opening a connection
self.cnx.vreg = self.vreg
-
+
def setup(self, config=None):
"""config is passed by TestSuite but is ignored in this environment"""
cursor = self.cnx.cursor()
@@ -254,4 +254,3 @@
cursor.execute('DELETE Any X WHERE X eid > %(x)s', {'x' : self.last_eid}, eid_key='x')
print "cleaning done"
self.cnx.commit()
-
--- a/devtools/cwtwill.py Thu May 14 18:12:45 2009 +0200
+++ b/devtools/cwtwill.py Mon May 18 10:09:06 2009 +0200
@@ -1,4 +1,9 @@
-"""cubicweb extensions for twill"""
+"""cubicweb extensions for twill
+
+:organization: Logilab
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
import re
from urllib import quote
@@ -24,9 +29,9 @@
# if url is specified linkurl must match
if url and linkurl != url:
continue
- return
+ return
raise AssertionError('link %s (%s) not found' % (text, url))
-
+
def view(rql, vid=''):
"""
@@ -56,7 +61,7 @@
twc.go('view?rql=%s&vid=edition' % quote(rql))
-
+
def setvalue(formname, fieldname, value):
"""
@@ -104,5 +109,5 @@
browser._browser.form = form
browser.submit(submit_button)
-
+
# missing actions: delete, copy, changeview
--- a/devtools/fake.py Thu May 14 18:12:45 2009 +0200
+++ b/devtools/fake.py Mon May 18 10:09:06 2009 +0200
@@ -1,7 +1,7 @@
"""Fake objects to ease testing of cubicweb without a fully working environment
: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"
--- a/devtools/fill.py Thu May 14 18:12:45 2009 +0200
+++ b/devtools/fill.py Mon May 18 10:09:06 2009 +0200
@@ -33,7 +33,7 @@
if isinstance(cst, StaticVocabularyConstraint):
return cst.vocabulary()
return None
-
+
def get_max_length(eschema, attrname):
"""returns the maximum length allowed for 'attrname'"""
@@ -75,7 +75,7 @@
value = self.__generate_value(attrname, index, **kwargs)
_GENERATED_VALUES.setdefault((self.e_schema.type, attrname), set()).add(value)
return value
-
+
def __generate_value(self, attrname, index, **kwargs):
"""generates a consistent value for 'attrname'"""
attrtype = str(self.e_schema.destination(attrname)).lower()
@@ -100,7 +100,7 @@
if choices is None:
return None
return unicode(choice(choices)) # FIXME
-
+
def generate_string(self, attrname, index, format=None):
"""generates a consistent value for 'attrname' if it's a string"""
# First try to get choices
@@ -133,7 +133,7 @@
def generate_password(self, attrname, index):
"""generates a consistent value for 'attrname' if it's a password"""
return u'toto'
-
+
def generate_integer(self, attrname, index):
"""generates a consistent value for 'attrname' if it's an integer"""
choosed = self.generate_choice(attrname, index)
@@ -145,17 +145,17 @@
else:
maxvalue = maxvalue or index
return randint(minvalue or 0, maxvalue)
-
+
generate_int = generate_integer
-
+
def generate_float(self, attrname, index):
"""generates a consistent value for 'attrname' if it's a float"""
return float(randint(-index, index))
-
+
def generate_decimal(self, attrname, index):
"""generates a consistent value for 'attrname' if it's a float"""
return Decimal(str(self.generate_float(attrname, index)))
-
+
def generate_date(self, attrname, index):
"""generates a random date (format is 'yyyy-mm-dd')"""
return date(randint(2000, 2004), randint(1, 12), randint(1, 28))
@@ -163,11 +163,11 @@
def generate_time(self, attrname, index):
"""generates a random time (format is ' HH:MM')"""
return timedelta(0, 11, index%60) #'11:%02d' % (index % 60)
-
+
def generate_datetime(self, attrname, index):
"""generates a random date (format is 'yyyy-mm-dd HH:MM')"""
return datetime(randint(2000, 2004), randint(1, 12), randint(1, 28), 11, index%60)
-
+
def generate_bytes(self, attrname, index, format=None):
# modpython way
@@ -175,7 +175,7 @@
fakefile.filename = "file_%s" % attrname
fakefile.value = fakefile.getvalue()
return fakefile
-
+
def generate_boolean(self, attrname, index):
"""generates a consistent value for 'attrname' if it's a boolean"""
return index % 2 == 0
@@ -185,7 +185,7 @@
# need this method else stupid values will be set which make mtconverter
# raise exception
return u'application/octet-stream'
-
+
def generate_Any_content_format(self, index, **kwargs):
# content_format attribute of EmailPart has no vocabulary constraint, we
# need this method else stupid values will be set which make mtconverter
@@ -250,7 +250,7 @@
args))
assert not 'eid' in args, args
else:
- queries.append(('INSERT %s X' % etype, {}))
+ queries.append(('INSERT %s X' % etype, {}))
return queries
@@ -365,7 +365,7 @@
continue
subjcard, objcard = rschema.rproperty(subj, obj, 'cardinality')
# process mandatory relations first
- if subjcard in '1+' or objcard in '1+':
+ if subjcard in '1+' or objcard in '1+':
queries += self.make_relation_queries(sedict, oedict,
rschema, subj, obj)
else:
@@ -374,7 +374,7 @@
queries += self.make_relation_queries(sedict, oedict, rschema,
subj, obj)
return queries
-
+
def qargs(self, subjeids, objeids, subjcard, objcard, subjeid, objeid):
if subjcard in '?1':
subjeids.remove(subjeid)
@@ -411,7 +411,7 @@
subjeids.remove(subjeid)
if not subjeids:
check_card_satisfied(objcard, objeids, subj, rschema, obj)
- return
+ return
if not objeids:
check_card_satisfied(subjcard, subjeids, subj, rschema, obj)
return
@@ -452,7 +452,7 @@
used.add( (subjeid, objeid) )
yield q, self.qargs(subjeids, objeids, subjcard, objcard,
subjeid, objeid)
-
+
def check_card_satisfied(card, remaining, subj, rschema, obj):
if card in '1+' and remaining:
raise Exception("can't satisfy cardinality %s for relation %s %s %s"
@@ -466,8 +466,8 @@
while objeid == avoid: # avoid infinite recursion like in X comment X
objeid = choice(values)
return objeid
-
-
+
+
# UTILITIES FUNCS ##############################################################
def make_tel(num_tel):
--- a/devtools/livetest.py Thu May 14 18:12:45 2009 +0200
+++ b/devtools/livetest.py Mon May 18 10:09:06 2009 +0200
@@ -1,4 +1,9 @@
-"""provide utilies for web (live) unit testing"""
+"""provide utilies for web (live) unit testing
+
+:organization: Logilab
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
import socket
import logging
@@ -41,9 +46,9 @@
return static.File(str(datadir), segments[1:])
# Otherwise we use this single resource
return self, ()
-
-
-
+
+
+
def make_site(cube, options=None):
from cubicweb.etwist import twconfig # trigger configuration registration
sourcefile = options.sourcefile
@@ -75,7 +80,7 @@
def saveconf(templhome, port, user, passwd):
import pickle
conffile = file(join(templhome, 'test', 'livetest.conf'), 'w')
-
+
pickle.dump((port, user, passwd, get_starturl(port, user, passwd)),
conffile)
conffile.close()
@@ -99,8 +104,8 @@
from twill import browser as twb
twc.OUT = new_output
twb.OUT = new_output
-
-
+
+
class LiveTestCase(TestCase):
sourcefile = None
@@ -118,7 +123,7 @@
def tearDown(self):
self.teardown_db(self.cnx)
-
+
def setup_db(self, cnx):
"""override setup_db() to setup your environment"""
@@ -141,5 +146,3 @@
if __name__ == '__main__':
runserver()
-
-
--- a/devtools/repotest.py Thu May 14 18:12:45 2009 +0200
+++ b/devtools/repotest.py Mon May 18 10:09:06 2009 +0200
@@ -103,7 +103,7 @@
class RQLGeneratorTC(TestCase):
schema = None # set this in concret test
-
+
def setUp(self):
self.rqlhelper = RQLHelper(self.schema, special_relations={'eid': 'uid',
'has_text': 'fti'})
@@ -114,7 +114,7 @@
def tearDown(self):
ExecutionPlan._check_permissions = _orig_check_permissions
rqlannotation._select_principal = _orig_select_principal
-
+
def _prepare(self, rql):
#print '******************** prepare', rql
union = self.rqlhelper.parse(rql)
@@ -133,7 +133,7 @@
class BaseQuerierTC(TestCase):
repo = None # set this in concret test
-
+
def setUp(self):
self.o = self.repo.querier
self.session = self.repo._sessions.values()[0]
@@ -148,7 +148,7 @@
return self.session.unsafe_execute('Any MAX(X)')[0][0]
def cleanup(self):
self.session.unsafe_execute('DELETE Any X WHERE X eid > %s' % self.maxeid)
-
+
def tearDown(self):
undo_monkey_patch()
self.session.rollback()
@@ -159,7 +159,7 @@
def set_debug(self, debug):
set_debug(debug)
-
+
def _rqlhelper(self):
rqlhelper = self.o._rqlhelper
# reset uid_func so it don't try to get type from eids
@@ -175,8 +175,8 @@
for select in rqlst.children:
select.solutions.sort()
return self.o.plan_factory(rqlst, kwargs, self.session)
-
- def _prepare(self, rql, kwargs=None):
+
+ def _prepare(self, rql, kwargs=None):
plan = self._prepare_plan(rql, kwargs)
plan.preprocess(plan.rqlst)
rqlst = plan.rqlst.children[0]
@@ -195,10 +195,10 @@
def execute(self, rql, args=None, eid_key=None, build_descr=True):
return self.o.execute(self.session, rql, args, eid_key, build_descr)
-
+
def commit(self):
self.session.commit()
- self.session.set_pool()
+ self.session.set_pool()
class BasePlannerTC(BaseQuerierTC):
@@ -270,7 +270,7 @@
def merge_input_maps(self, *args):
pass
def _choose_term(self, sourceterms):
- pass
+ pass
_orig_merge_input_maps = PartPlanInformation.merge_input_maps
_orig_choose_term = PartPlanInformation._choose_term
@@ -309,4 +309,3 @@
ExecutionPlan.init_temp_table = _orig_init_temp_table
PartPlanInformation.merge_input_maps = _orig_merge_input_maps
PartPlanInformation._choose_term = _orig_choose_term
-
--- a/devtools/stresstester.py Thu May 14 18:12:45 2009 +0200
+++ b/devtools/stresstester.py Mon May 18 10:09:06 2009 +0200
@@ -5,13 +5,13 @@
OPTIONS:
-h / --help
Display this help message and exit.
-
+
-u / --user <user>
Connect as <user> instead of being prompted to give it.
-p / --password <password>
Automatically give <password> for authentication instead of being prompted
to give it.
-
+
-n / --nb-times <num>
Repeat queries <num> times.
-t / --nb-threads <num>
@@ -21,7 +21,7 @@
-o / --report-output <filename>
Write profiler report into <filename> rather than on stdout
-Copyright (c) 2003-2006 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+Copyright (c) 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
@@ -49,7 +49,7 @@
self._times = times
self._queries = queries
self._reporter = reporter
-
+
def run(self):
cursor = self._cursor
times = self._times
@@ -80,7 +80,7 @@
threads and can write a report that summarizes all profile informations
"""
profiler_lock = threading.Lock()
-
+
def __init__(self, queries):
self._queries = tuple(queries)
self._profile_results = [(0., 0)] * len(self._queries)
@@ -111,8 +111,8 @@
table_layout = Table(3, rheaders = True, children = table_elems)
TextWriter().format(table_layout, output)
# output.write('\n'.join(tmp_output))
-
-
+
+
def run(args):
"""run the command line tool"""
try:
@@ -150,7 +150,7 @@
user = raw_input('login: ')
if password is None:
password = getpass('password: ')
- from cubicweb.cwconfig import application_configuration
+ from cubicweb.cwconfig import application_configuration
config = application_configuration(args[0])
# get local access to the repository
print "Creating repo", prof_file
@@ -176,7 +176,7 @@
else:
QueryExecutor(repo_cursor, repeat, queries, reporter = reporter).run()
reporter.dump_report(report_output)
-
-
+
+
if __name__ == '__main__':
run(sys.argv[1:])
--- a/devtools/test/unittest_dbfill.py Thu May 14 18:12:45 2009 +0200
+++ b/devtools/test/unittest_dbfill.py Mon May 18 10:09:06 2009 +0200
@@ -31,7 +31,7 @@
return getattr(self, '_available_%s_%s' % (etype, attrname))(etype, attrname)
except AttributeError:
return None
-
+
def _available_Person_firstname(self, etype, attrname):
return [f.strip() for f in file(osp.join(DATADIR, 'firstnames.txt'))]
@@ -51,11 +51,11 @@
year = date.year
month = date.month
day = date.day
- self.failUnless(day in range(1, 29), '%s not in [0;28]' % day)
+ self.failUnless(day in range(1, 29), '%s not in [0;28]' % day)
self.failUnless(month in range(1, 13), '%s not in [1;12]' % month)
self.failUnless(year in range(2000, 2005),
'%s not in [2000;2004]' % year)
-
+
def test_string(self):
"""test string generation"""
@@ -89,7 +89,7 @@
for index in range(5):
date_value = self.person_valgen._generate_value('birthday', index)
self._check_date(date_value)
-
+
def test_phone(self):
"""tests make_tel utility"""
self.assertEquals(make_tel(22030405), '22 03 04 05')
@@ -102,14 +102,14 @@
u'yo')
self.assertEquals(self.person_valgen._generate_value('description', 12),
u'yo')
-
-
+
+
class ConstraintInsertionTC(TestCase):
def test_writeme(self):
self.skip('Test automatic insertion / Schema Constraints')
-
+
if __name__ == '__main__':
unittest_main()
--- a/devtools/test/unittest_fill.py Thu May 14 18:12:45 2009 +0200
+++ b/devtools/test/unittest_fill.py Mon May 18 10:09:06 2009 +0200
@@ -20,7 +20,7 @@
for attrname in attrvalues - set(self.attrvalues):
delattr(_ValueGenerator, attrname)
-
+
def test_autoextend(self):
self.failIf('generate_server' in dir(ValueGenerator))
class MyValueGenerator(ValueGenerator):
--- a/devtools/test/unittest_testlib.py Thu May 14 18:12:45 2009 +0200
+++ b/devtools/test/unittest_testlib.py Mon May 18 10:09:06 2009 +0200
@@ -22,14 +22,14 @@
def test_error_view(self):
self.add_entity('Bug', title=u"bt")
self.view('raising', self.execute('Bug B'), template=None)
-
+
def test_correct_view(self):
self.view('primary', self.execute('CWUser U'), template=None)
-
+
tests = [MyWebTest('test_error_view'), MyWebTest('test_correct_view')]
result = self.runner.run(TestSuite(tests))
self.assertEquals(result.testsRun, 2)
- self.assertEquals(len(result.errors), 0)
+ self.assertEquals(len(result.errors), 0)
self.assertEquals(len(result.failures), 1)
@@ -97,13 +97,13 @@
def test_source1(self):
"""make sure source is stored correctly"""
self.assertEquals(self.page_info.source, HTML_PAGE2)
-
+
def test_source2(self):
"""make sure source is stored correctly - raise exception"""
parser = htmlparser.DTDValidator()
self.assertRaises(AssertionError, parser.parse_string, HTML_PAGE_ERROR)
-
+
def test_has_title_no_level(self):
"""tests h? tags information"""
self.assertEquals(self.page_info.has_title('Test'), True)
@@ -128,7 +128,7 @@
self.assertEquals(self.page_info.has_title_regexp('h[23] title', 2), True)
self.assertEquals(self.page_info.has_title_regexp('h[23] title', 3), True)
self.assertEquals(self.page_info.has_title_regexp('h[23] title', 4), False)
-
+
def test_appears(self):
"""tests PageInfo.appears()"""
self.assertEquals(self.page_info.appears('CW'), True)
@@ -151,4 +151,3 @@
if __name__ == '__main__':
unittest_main()
-
--- a/doc/book/en/annexes/cookbook.rst Thu May 14 18:12:45 2009 +0200
+++ b/doc/book/en/annexes/cookbook.rst Mon May 18 10:09:06 2009 +0200
@@ -62,3 +62,19 @@
cnx.commit()
cnx.close()
+
+* How to load data from a script?
+
+ The following script aims at loading data within a script assuming pyro-nsd is
+ running and your application is configured with ``pyro-server=yes``, otherwise
+ you would not be able to use dbapi. ::
+
+ from cubicweb import dbapi
+
+ cnx = dbapi.connection(database='instance-id', user='admin', password='admin')
+ cur = cnx.cursor()
+ for name in ('Personal', 'Professional', 'Computers'):
+ cur.execute('INSERT Blog B: B name %s', name)
+ cnx.commit()
+
+
--- a/doc/book/en/annexes/faq.rst Thu May 14 18:12:45 2009 +0200
+++ b/doc/book/en/annexes/faq.rst Mon May 18 10:09:06 2009 +0200
@@ -69,8 +69,13 @@
one schema to the other ever since. There is a well-defined way to
handle data and schema migration.
+<<<<<<< /home/syt/src/fcubicweb/cubicweb_3.2/doc/book/en/annexes/faq.rst
+Why is the RQL query language looking similar to X ?
+----------------------------------------------------
+=======
Why is the RQL query language looking similar to X ?
-----------------------------------------------------
+>>>>>>> /tmp/faq.rst~other.MxOUAP
It may remind you of SQL but it is higher level than SQL, more like
SPARQL. Except that SPARQL did not exist when we started the project.
@@ -96,7 +101,46 @@
which ajax library
------------------
- [we use jquery and things on top of that]
+[we use jquery and things on top of that]
+
+
+How to implement security?
+--------------------------
+
+ This is an example of how it works in our framework::
+
+ class Version(EntityType):
+ """a version is defining the content of a particular project's
+ release"""
+ # definition of attributes is voluntarily missing
+ 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'),)}
+
+ The above means that permission to read a Version is granted to any
+ user that is part of one of the groups 'managers', 'users', 'guests'.
+ The 'add' permission is granted to users in group 'managers' or
+ 'logilab' and to users in group G, if G is linked by a permission
+ entity named "add_version" to the version's project.
+ ::
+
+ class version_of(RelationType):
+ """link a version to its project. A version is necessarily linked
+ to one and only one project. """
+ # some lines voluntarily missing
+ 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'),) }
+
+ You can find additional information in the section :ref:`security`.
+
+ [XXX what does the second example means in addition to the first one?]
+
`Error while publishing rest text ...`
--------------------------------------
@@ -204,6 +248,7 @@
where DATADIR is ``mycubes/data``.
+
How to configure LDAP source?
-------------------------------
@@ -297,41 +342,3 @@
[XXX check that cw handle users better by
mapping Google Accounts to local Euser entities automatically]
-
-How to implement security?
---------------------------
-
- This is an example of how it works in our framework::
-
- class Version(EntityType):
- """a version is defining the content of a particular project's
- release"""
- # definition of attributes is voluntarily missing
- 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'),)}
-
- The above means that permission to read a Version is granted to any
- user that is part of one of the groups 'managers', 'users', 'guests'.
- The 'add' permission is granted to users in group 'managers' or
- 'logilab' and to users in group G, if G is linked by a permission
- entity named "add_version" to the version's project.
- ::
-
- class version_of(RelationType):
- """link a version to its project. A version is necessarily linked
- to one and only one project. """
- # some lines voluntarily missing
- 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'),) }
-
- You can find additional information in the section :ref:`security`.
-
- [XXX what does the second example means in addition to the first one?]
-
--- a/doc/book/en/conf.py Thu May 14 18:12:45 2009 +0200
+++ b/doc/book/en/conf.py Mon May 18 10:09:06 2009 +0200
@@ -53,7 +53,7 @@
today_fmt = '%B %d, %Y'
# List of documents that shouldn't be included in the build.
-#unused_docs = []
+unused_docs = ['D070-modules-cbw-api.en',]
# List of directories, relative to source directories, that shouldn't be searched
# for source files.
--- a/doc/book/en/index.rst Thu May 14 18:12:45 2009 +0200
+++ b/doc/book/en/index.rst Mon May 18 10:09:06 2009 +0200
@@ -29,8 +29,6 @@
The hacker will join development at the forge_.
-The impatient will go strait away to :ref:`QuickInstall`.
-
The impatient developper will move right away to :ref:`SetUpEnv`.
.. _Logilab: http://www.logilab.fr/
--- a/doc/book/en/intro/tutorial/components.rst Thu May 14 18:12:45 2009 +0200
+++ b/doc/book/en/intro/tutorial/components.rst Mon May 18 10:09:06 2009 +0200
@@ -70,7 +70,7 @@
database with your model. For this purpose, `CubicWeb` provides
a very useful command ``cubicweb-ctl shell blogdemo`` which
launches an interactive migration Python shell. (see
-:ref:`cubicweb-ctl-shell` for more details))
+:ref:`cubicweb-ctl` for more details))
As you modified a relation from the `BlogEntry` schema,
run the following command:
::
--- a/doc/book/en/intro/tutorial/create-cube.rst Thu May 14 18:12:45 2009 +0200
+++ b/doc/book/en/intro/tutorial/create-cube.rst Mon May 18 10:09:06 2009 +0200
@@ -3,6 +3,10 @@
Create your cube
----------------
+The packages ``cubicweb`` and ``cubicweb-dev`` installs a command line tool
+for `CubicWeb` called ``cubicweb-ctl``. This tool provides a wide range of
+commands described in details in :ref:`cubicweb-ctl`.
+
Once your `CubicWeb` development environment is set up, you can create a new
cube::
--- a/doc/book/fr/conf.py Thu May 14 18:12:45 2009 +0200
+++ b/doc/book/fr/conf.py Mon May 18 10:09:06 2009 +0200
@@ -36,7 +36,7 @@
# General substitutions.
project = 'Cubicweb'
-copyright = '2008, Logilab'
+copyright = '2008-2009, Logilab'
# The default replacements for |version| and |release|, also used in various
# other places throughout the built documents.
--- a/doc/tools/generate_modules.py Thu May 14 18:12:45 2009 +0200
+++ b/doc/tools/generate_modules.py Mon May 18 10:09:06 2009 +0200
@@ -1,99 +1,12 @@
+"""generate list of modules for sphinx doc"""
+
import sys
-"""
-Generates the chapter that list all the modules in CubicWeb
-in order to pull all the docstring.
-"""
-
-class ModuleGenerator:
- HEADER = """.. -*- coding: utf-8 -*-
-
-============
-CubicWeb API
-============
-"""
- EXCLUDE_DIRS = ('test', 'tests', 'examples', 'data', 'doc', '.hg', 'migration')
-
- def __init__(self, output_fn, mod_names):
- self.mod_names = mod_names
- self.fn = open(output_fn, 'w')
- self.fn.write(self.HEADER)
-
- def done(self):
- self.fn.close()
-
- def gen_module(self, mod_name):
- mod_entry = """
-:mod:`%s`
-%s
-
-.. automodule:: %s
- :members:
-""" % (mod_name, '='*(len(':mod:``'+mod_name)), mod_name)
- self.fn.write(mod_entry)
-
- def find_modules(self):
- import os
- modules = []
- for mod_name in self.mod_names:
- for root, dirs, files in os.walk(mod_name):
- if self.keep_module(root):
- for name in files:
- if name == "__init__.py":
- if self.format_mod_name(root, mod_name) not in modules:
- modules.append(self.format_mod_name(root, mod_name))
- else:
- if name.endswith(".py") and name != "__pkginfo__.py" and "__init__.py" in files:
- filename = root + '/' + name.split('.py')[0]
- if self.format_mod_name(filename, mod_name) not in modules:
- modules.append(self.format_mod_name(filename, mod_name))
- return modules
+EXCLUDE_DIRS = ('test', 'tests', 'examples', 'data', 'doc', '.hg', 'migration')
+if __name__ == '__main__':
- def gen_modules(self):
- for module in self.find_modules():
- self.gen_module(module)
-
- def format_mod_name(self, path, mod_name):
- mod_root = mod_name.split('/')[-1]
- mod_end = path.split(mod_root)[-1]
- return mod_root + mod_end.replace('/', '.')
-
- def keep_module(self, mod_end):
- """
- Filter modules in order to exclude specific package directories.
- """
- for dir in self.EXCLUDE_DIRS:
- if mod_end.find(dir) != -1:
- return False
- return True
-
-USAGE = """
-Two arguments required:
- generate_modules [cubicweb-root] [file-out]
+ from logilab.common.sphinxutils import generate_modules_file
-[cubicweb-root] : full path to cubicweb forest
-[file-out] : rest file containing the list of modules for Sphinx
-"""
-def generate_modules_file(args):
- if len(args) != 2:
- print USAGE
- sys.exit()
- CW_ROOT = args[0]
- OUTPUT = args[1]
- modules = (CW_ROOT + '/cubicweb', \
- CW_ROOT + '/indexer', \
- CW_ROOT + '/logilab', \
- CW_ROOT + '/rql', \
- CW_ROOT + '/yams')
-
- mg = ModuleGenerator(CW_ROOT + '/cubicweb/doc/book/en/' + OUTPUT, modules)
- mg.find_modules()
- mg.gen_modules()
- mg.done()
- print args
-
-
-
-if __name__ == '__main__':
- generate_modules_file(sys.argv[1:])
-
+ gen = generate_modules_file(sys.argv[1:])
+ gen.set_docdir("cubicweb/doc/book/en")
+ gen.make(['cubicweb', '/indexer', '/logilab', '/rql', '/yams'], EXCLUDE_DIRS)
--- a/entities/schemaobjs.py Thu May 14 18:12:45 2009 +0200
+++ b/entities/schemaobjs.py Mon May 18 10:09:06 2009 +0200
@@ -20,7 +20,7 @@
def dc_title(self):
return self.req._(self.name)
-
+
def dc_long_title(self):
stereotypes = []
_ = self.req._
@@ -40,10 +40,10 @@
class CWRType(AnyEntity):
id = 'CWRType'
fetch_attrs, fetch_order = fetch_config(['name'])
-
+
def dc_title(self):
return self.req._(self.name)
-
+
def dc_long_title(self):
stereotypes = []
_ = self.req._
@@ -61,7 +61,7 @@
def inlined_changed(self, inlined):
"""check inlining is necessary and possible:
-
+
* return False if nothing has changed
* raise ValidationError if inlining is'nt possible
* eventually return True
@@ -88,13 +88,13 @@
class CWRelation(AnyEntity):
id = 'CWRelation'
fetch_attrs = fetch_config(['cardinality'])[0]
-
+
def dc_title(self):
return u'%s %s %s' % (
self.from_entity[0].name,
- self.relation_type[0].name,
+ self.relation_type[0].name,
self.to_entity[0].name)
-
+
def dc_long_title(self):
card = self.cardinality
scard, ocard = u'', u''
@@ -118,7 +118,7 @@
class CWAttribute(CWRelation):
id = 'CWAttribute'
-
+
def dc_long_title(self):
card = self.cardinality
scard = u''
@@ -126,7 +126,7 @@
scard = '+'
return u'%s %s%s %s' % (
self.from_entity[0].name,
- scard, self.relation_type[0].name,
+ scard, self.relation_type[0].name,
self.to_entity[0].name)
@@ -136,7 +136,7 @@
def dc_title(self):
return '%s(%s)' % (self.cstrtype[0].name, self.value or u'')
-
+
def after_deletion_path(self):
"""return (path, parameters) which should be used as redirect
information when this entity is being deleted
@@ -149,7 +149,7 @@
def type(self):
return self.cstrtype[0].name
-
+
class RQLExpression(AnyEntity):
id = 'RQLExpression'
fetch_attrs, fetch_order = fetch_config(['exprtype', 'mainvars', 'expression'])
@@ -164,17 +164,17 @@
values = getattr(self, 'reverse_%s' % rel)
if values:
return values[0]
-
+
@cached
def _rqlexpr(self):
if self.exprtype == 'ERQLExpression':
return ERQLExpression(self.expression, self.mainvars, self.eid)
#if self.exprtype == 'RRQLExpression':
return RRQLExpression(self.expression, self.mainvars, self.eid)
-
+
def check_expression(self, *args, **kwargs):
return self._rqlexpr().check(*args, **kwargs)
-
+
def after_deletion_path(self):
"""return (path, parameters) which should be used as redirect
information when this entity is being deleted
@@ -192,7 +192,7 @@
if self.label:
return '%s (%s)' % (self.req._(self.name), self.label)
return self.req._(self.name)
-
+
def after_deletion_path(self):
"""return (path, parameters) which should be used as redirect
information when this entity is being deleted
--- a/entity.py Thu May 14 18:12:45 2009 +0200
+++ b/entity.py Mon May 18 10:09:06 2009 +0200
@@ -123,7 +123,7 @@
for name, widgets in _get_defs('widgets', name, bases, classdict):
warn('%s: widgets is deprecated' % name, DeprecationWarning)
for rtype, wdgname in widgets.iteritems():
- if wdgname in ('URLWidget', 'EmbededURLWidget'):
+ if wdgname in ('URLWidget', 'EmbededURLWidget', 'RawDynamicComboBoxWidget'):
warn('%s widget is deprecated' % wdgname, DeprecationWarning)
continue
if wdgname == 'StringWidget':
--- a/etwist/request.py Thu May 14 18:12:45 2009 +0200
+++ b/etwist/request.py Mon May 18 10:09:06 2009 +0200
@@ -39,11 +39,11 @@
def base_url(self):
"""return the root url of the application"""
return self._base_url
-
+
def http_method(self):
"""returns 'POST', 'GET', 'HEAD', etc."""
return self._twreq.method
-
+
def relative_path(self, includeparams=True):
"""return the normalized path of the request (ie at least relative
to the application's root, but some other normalization may be needed
--- a/etwist/twconfig.py Thu May 14 18:12:45 2009 +0200
+++ b/etwist/twconfig.py Mon May 18 10:09:06 2009 +0200
@@ -2,13 +2,13 @@
* the "twisted" configuration to get a web application running in a standalone
twisted web server which talk to a repository server using Pyro
-
+
* the "all-in-one" configuration to get a web application running in a twisted
web server integrating a repository server in the same process (only available
if the repository part of the software is installed
: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"
@@ -63,12 +63,12 @@
('pyro-server',
{'type' : 'yn',
# pyro is only a recommends by default, so don't activate it here
- 'default': False,
+ 'default': False,
'help': 'run a pyro server',
'group': 'main', 'inputlevel': 1,
}),
) + WebConfiguration.options)
-
+
def server_file(self):
return join(self.apphome, '%s-%s.py' % (self.appid, self.name))
@@ -91,6 +91,6 @@
def pyro_enabled(self):
"""tell if pyro is activated for the in memory repository"""
return self['pyro-server']
-
+
except ImportError:
pass
--- a/etwist/twctl.py Thu May 14 18:12:45 2009 +0200
+++ b/etwist/twctl.py Mon May 18 10:09:06 2009 +0200
@@ -1,4 +1,8 @@
"""cubicweb-clt handlers for twisted
+
+:organization: Logilab
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
import sys
@@ -52,8 +56,8 @@
class TWStopHandler(CommandHandler):
cmdname = 'stop'
cfgname = 'twisted'
-
-
+
+
try:
from cubicweb.server import serverctl
@@ -67,7 +71,7 @@
"""bootstrap this configuration"""
serverctl.RepositoryCreateHandler.bootstrap(self, cubes, inputlevel)
TWCreateHandler.bootstrap(self, cubes, inputlevel)
-
+
class AllInOneStartHandler(TWStartHandler):
cmdname = 'start'
cfgname = 'all-in-one'
@@ -80,4 +84,3 @@
except ImportError:
pass
-
--- a/ext/html4zope.py Thu May 14 18:12:45 2009 +0200
+++ b/ext/html4zope.py Mon May 18 10:09:06 2009 +0200
@@ -40,19 +40,19 @@
def __init__(self, url, klass):
self.base_url = url
self.translator_class = HTMLTranslator
-
+
def __call__(self, document):
translator = self.translator_class(document)
translator.base_url = self.base_url
return translator
-
+
class HTMLTranslator(CSS1HTMLTranslator):
"""ReST tree to html translator"""
def astext(self):
"""return the extracted html"""
return ''.join(self.body)
-
+
def visit_title(self, node):
"""Only 6 section levels are supported by HTML."""
if isinstance(node.parent, nodes.topic):
@@ -124,7 +124,7 @@
def depart_problematic(self, node):
pass
-
+
def visit_system_message(self, node):
backref_text = ''
if len(node['backrefs']):
--- a/ext/tal.py Thu May 14 18:12:45 2009 +0200
+++ b/ext/tal.py Mon May 18 10:09:06 2009 +0200
@@ -1,7 +1,7 @@
"""provides simpleTAL extensions for CubicWeb
: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
"""
@@ -12,7 +12,7 @@
from os.path import exists, isdir, join
from logging import getLogger
from StringIO import StringIO
-
+
from simpletal import simpleTAL, simpleTALES
from logilab.common.decorators import cached
@@ -23,7 +23,7 @@
class LoggerAdapter(object):
def __init__(self, tal_logger):
self.tal_logger = tal_logger
-
+
def debug(self, msg):
LOGGER.debug(msg)
@@ -49,7 +49,7 @@
simpleTALES.Context.addRepeat(self, name, var, initialValue)
# XXX FIXME need to find a clean to define OPCODE values for extensions
-I18N_CONTENT = 18
+I18N_CONTENT = 18
I18N_REPLACE = 19
RQL_EXECUTE = 20
# simpleTAL uses the OPCODE values to define priority over commands.
@@ -113,7 +113,7 @@
"""
# Compile tal:attributes into attribute command
# Argument: [(attributeName, expression)]
-
+
# Break up the list of attribute settings first
commandArgs = []
# We only want to match semi-colons that are not escaped
@@ -187,7 +187,7 @@
def compile_template_file(filepath):
"""compiles a TAL template file
:type filepath: str
- :param template: path of the file to compile
+ :param template: path of the file to compile
"""
fp = file(filepath)
file_content = unicode(fp.read()) # template file should be pure ASCII
@@ -253,4 +253,3 @@
return compile_template_file(filepath)
raise Exception('no such template %s' % self.filename)
_compiled_template = cached(_compiled_template, 0)
-
--- a/goa/__init__.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/__init__.py Mon May 18 10:09:06 2009 +0200
@@ -17,7 +17,7 @@
pass
else:
- import os
+ import os
_SS = os.environ.get('SERVER_SOFTWARE')
if _SS is None:
MODE = 'test'
@@ -30,7 +30,7 @@
from cubicweb.goa.gaesource import GAESource
SOURCE_TYPES['gae'] = GAESource
-
+
def do_monkey_patch():
# monkey patch yams Bytes validator since it should take a bytes string with gae
@@ -56,16 +56,16 @@
# XXX monkey patch cubicweb.schema.CubicWebSchema to have string eid with
# optional cardinality (since eid is set after the validation)
-
+
import re
from yams import buildobjs as ybo
-
+
def add_entity_type(self, edef):
edef.name = edef.name.encode()
assert re.match(r'[A-Z][A-Za-z0-9]*[a-z]+[0-9]*$', edef.name), repr(edef.name)
eschema = super(CubicWebSchema, self).add_entity_type(edef)
if not eschema.is_final():
- # automatically add the eid relation to non final entity types
+ # automatically add the eid relation to non final entity types
rdef = ybo.RelationDefinition(eschema.type, 'eid', 'Bytes',
cardinality='?1', uid=True)
self.add_relation_def(rdef)
@@ -73,7 +73,7 @@
self.add_relation_def(rdef)
self._eid_index[eschema.eid] = eschema
return eschema
-
+
from cubicweb.schema import CubicWebSchema
CubicWebSchema.add_entity_type = add_entity_type
@@ -93,7 +93,7 @@
cubes = config['included-cubes'] + config['included-yams-cubes']
return config.expand_cubes(cubes)
repository.Repository.get_cubes = get_cubes
-
+
from rql import RQLHelper
RQLHelper.simplify = lambda x, r: None
--- a/goa/appobjects/components.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/appobjects/components.py Mon May 18 10:09:06 2009 +0200
@@ -23,7 +23,7 @@
to search for something to link to the edited eid
"""
id = 'search-associate'
-
+
__select__ = one_line_rset() & match_search_state('linksearch') & accept
def cell_call(self, row, col):
@@ -43,7 +43,7 @@
binary = True
content_type = 'image/png'
def call(self):
- """display global schema information"""
+ """display global schema information"""
skipmeta = not int(self.req.form.get('withmeta', 0))
if skipmeta:
url = self.build_url('data/schema.png')
--- a/goa/appobjects/dbmgmt.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/appobjects/dbmgmt.py Mon May 18 10:09:06 2009 +0200
@@ -54,8 +54,8 @@
values.append('__session=%s' % cookie['__session'].value)
self.w(u"<p>pass this flag to the client: --cookie='%s'</p>"
% html_escape('; '.join(values)))
-
-
+
+
class ContentInit(StartupView):
"""special management view to initialize content of a repository,
@@ -74,7 +74,7 @@
status['stepid'] = stepid
Put(status)
self.msg(msg)
-
+
def call(self):
status = _get_status('creation')
if status.get('finished'):
@@ -149,7 +149,7 @@
'<b>delete all datastore content</b> so process can be '
'reinitialized</div>' % html_escape(self.req.base_url()))
Put(status)
-
+
@property
@cached
def _migrhandler(self):
@@ -164,12 +164,12 @@
def continue_link(self):
self.w(u'<a href="%s">continue</a><br/>' % html_escape(self.req.url()))
-
+
class ContentClear(StartupView):
id = 'contentclear'
__select__ = none_rset() & match_user_groups('managers')
skip_etypes = ('CWGroup', 'CWUser')
-
+
def call(self):
# XXX should use unsafe_execute with all hooks deactivated
# XXX step by catching datastore errors?
--- a/goa/appobjects/gauthservice.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/appobjects/gauthservice.py Mon May 18 10:09:06 2009 +0200
@@ -23,7 +23,7 @@
def url(self):
return users.create_logout_url(self.req.build_url('logout') )
-
+
def registration_callback(vreg):
if hasattr(vreg.config, 'has_resource'):
vreg.register(GACWUserLink, clear=True)
--- a/goa/appobjects/sessions.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/appobjects/sessions.py Mon May 18 10:09:06 2009 +0200
@@ -41,10 +41,10 @@
def __init__(self, *args, **kwargs):
super(GAEAuthenticationManager, self).__init__(*args, **kwargs)
self._repo = self.config.repository(vreg=self.vreg)
-
+
def authenticate(self, req, _login=None, _password=None):
"""authenticate user and return an established connection for this user
-
+
:raise ExplicitLogin: if authentication is required (no authentication
info found or wrong user/password)
"""
@@ -75,7 +75,7 @@
def __init__(self, *args, **kwargs):
super(GAEPersistentSessionManager, self).__init__(*args, **kwargs)
self._repo = self.config.repository(vreg=self.vreg)
-
+
def get_session(self, req, sessionid):
"""return existing session for the given session identifier"""
# search a record for the given session
@@ -126,7 +126,7 @@
record['anonymous_connection'] = cnx.anonymous_connection
Put(record)
return self._get_proxy(req, record, cnx, user)
-
+
def close_session(self, proxy):
"""close session on logout or on invalid session detected (expired out,
corrupted...)
@@ -136,7 +136,7 @@
def current_sessions(self):
for record in Query('CubicWebSession').Run():
yield ConnectionProxy(record)
-
+
def _get_proxy(self, req, record, cnx, user):
proxy = ConnectionProxy(record, cnx, user)
user.req = req
@@ -145,7 +145,7 @@
class ConnectionProxy(object):
-
+
def __init__(self, record, cnx=None, user=None):
self.__record = record
self.__cnx = cnx
@@ -153,7 +153,7 @@
self.__data = None
self.__is_dirty = False
self.sessionid = record.key().name()[4:] # remove 'key_' prefix
-
+
def __repr__(self):
sstr = '<ConnectionProxy %s' % self.sessionid
if self.anonymous_connection:
@@ -162,7 +162,7 @@
sstr += ' for %s' % self.__user.login
sstr += ', last used %s>' % strftime('%T', localtime(self.last_usage_time))
return sstr
-
+
def __getattribute__(self, name):
try:
return super(ConnectionProxy, self).__getattribute__(name)
@@ -174,7 +174,7 @@
self.__record['last_usage_time'] = value
def _get_last_usage_time(self):
return self.__record['last_usage_time']
-
+
last_usage_time = property(_get_last_usage_time, _set_last_usage_time)
@property
@@ -182,7 +182,7 @@
# use get() for bw compat if sessions without anonymous information are
# found. Set default to True to limit lifetime of those sessions.
return self.__record.get('anonymous_connection', True)
-
+
@property
@cached
def data(self):
@@ -194,7 +194,7 @@
self.exception('corrupted session data for session %s',
self.__cnx)
return {}
-
+
def get_session_data(self, key, default=None, pop=False):
"""return value associated to `key` in session data"""
if pop:
@@ -206,20 +206,20 @@
return default
else:
return self.data.get(key, default)
-
+
def set_session_data(self, key, value):
"""set value associated to `key` in session data"""
self.data[key] = value
self.__is_dirty = True
-
+
def del_session_data(self, key):
"""remove value associated to `key` in session data"""
try:
del self.data[key]
self.__is_dirty = True
except KeyError:
- pass
-
+ pass
+
def commit(self):
if self.__is_dirty:
self.__save()
@@ -233,7 +233,7 @@
if self.__cnx is not None:
self.__cnx.close()
Delete(self.__record)
-
+
def __save(self):
if self.__is_dirty:
self.__record['data'] = Blob(dumps(self.data))
@@ -243,7 +243,7 @@
def user(self, req=None, props=None):
"""return the User object associated to this connection"""
return self.__user
-
+
import logging
from cubicweb import set_log_methods
@@ -256,7 +256,7 @@
class SessionsCleaner(StartupView):
id = 'cleansessions'
__select__ = none_rset() & match_user_groups('managers')
-
+
def call(self):
# clean web session
session_manager = application.SESSION_MANAGER
@@ -270,7 +270,7 @@
self.w(u'%s remaining sessions<br/>\n' % remaining)
self.w(u'</div>')
-
+
def registration_callback(vreg):
vreg.register(SessionsCleaner)
vreg.register(GAEAuthenticationManager, clear=True)
--- a/goa/db.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/db.py Mon May 18 10:09:06 2009 +0200
@@ -13,11 +13,11 @@
* all methods returning `google.appengine.ext.db.Model` instance(s) will return
`cubicweb.goa.db.Model` instance instead (though you should see almost no
difference since those instances have the same api)
-
+
* class methods returning model instance take a `req` as first argument, unless
they are called through an instance, representing the current request
(accessible through `self.req` on almost all objects)
-
+
* XXX no instance.<modelname>_set attributes, use instance.reverse_<attr name>
instead
* XXX reference property always return a list of objects, not the instance
@@ -47,7 +47,7 @@
from google.appengine.api.datastore_errors import BadKeyError
# XXX remove this dependancy
-from google.appengine.ext import db
+from google.appengine.ext import db
def rset_from_objs(req, objs, attrs=('eid',), rql=None, args=None):
@@ -76,15 +76,15 @@
value = obj[attr]
descr = str(eschema.destination(attr))
line.append(value)
- linedescr.append(descr)
+ linedescr.append(descr)
rows.append(line)
description.append(linedescr)
for j, attr in enumerate(attrs):
if attr == 'eid':
entity = vreg.etype_class(eschema.type)(req, rset, i, j)
- rset._get_entity_cache_ = {(i, j): entity}
+ rset._get_entity_cache_ = {(i, j): entity}
rset.rowcount = len(rows)
- req.decorate_rset(rset)
+ req.decorate_rset(rset)
return rset
@@ -102,7 +102,7 @@
return wrapped(cls, req, *args, **kwargs)
return iclassmethod(wrapper)
-
+
class gaedbmetaentity(metaentity):
"""metaclass for goa.db.Model classes: filter entity / db model part,
put aside the db model part for later creation of db model class.
@@ -139,15 +139,15 @@
class Model(entities.AnyEntity):
id = 'Any'
__metaclass__ = gaedbmetaentity
-
+
row = col = 0
-
+
@classmethod
def __initialize__(cls):
super(Model, cls).__initialize__()
cls._attributes = frozenset(rschema for rschema in cls.e_schema.subject_relations()
if rschema.is_final())
-
+
def __init__(self, *args, **kwargs):
# db.Model prototype:
# __init__(self, parent=None, key_name=None, **kw)
@@ -168,7 +168,7 @@
val = val._dbmodel
kwargs[key] = val.key()
self._gaeinitargs = (args, kwargs)
-
+
def __repr__(self):
return '<ModelEntity %s %s %s at %s>' % (
self.e_schema, self.eid, self.keys(), id(self))
@@ -179,7 +179,7 @@
tschema = self.e_schema.destination(attr)
if tschema == 'String':
if len(value) > 500:
- value = Text(value)
+ value = Text(value)
elif tschema == 'Password':
# if value is a Binary instance, this mean we got it
# from a query result and so it is already encrypted
@@ -203,7 +203,7 @@
value = self._cubicweb_to_datastore(attr, value)
gaedict[attr] = value
return gaedict
-
+
def to_gae_model(self):
dbmodel = self._dbmodel
dbmodel.update(self._to_gae_dict())
@@ -211,7 +211,7 @@
@property
@cached
- def _dbmodel(self):
+ def _dbmodel(self):
if self.has_eid():
assert self._gaeinitargs is None
try:
@@ -240,7 +240,7 @@
if '_app' in kwargs:
assert _app is None
_app = kwargs.pop('_app')
-
+
for key, value in kwargs.iteritems():
if key in self._attributes:
values['s_'+key] = value
@@ -267,10 +267,10 @@
value will be prefixed by 'key_' to build the actual key name.
"""
return None
-
+
def metainformation(self):
return {'type': self.id, 'source': {'uri': 'system'}, 'extid': None}
-
+
def view(self, vid, __registry='views', **kwargs):
"""shortcut to apply a view on this entity"""
return self.vreg.render(__registry, vid, self.req, rset=self.rset,
@@ -282,7 +282,7 @@
if needcheck:
return 'eid', False
return mainattr, needcheck
-
+
def get_value(self, name):
try:
value = self[name]
@@ -306,7 +306,7 @@
return True
except BadKeyError:
return False
-
+
def complete(self, skip_bytes=True):
pass
@@ -319,7 +319,7 @@
objs = Query(str(targettype)).Run()
return rset_from_objs(self.req, objs, ('eid',),
'Any X WHERE X is %s' % targettype)
-
+
def key(self):
return Key(self.eid)
@@ -334,7 +334,7 @@
'Any X WHERE X eid %(x)s', {'x': self.eid})
self.row = self.col = 0
return dbmodel
-
+
@needrequest
def get(cls, req, keys):
# if check if this is a dict.key call
@@ -393,7 +393,7 @@
def dynamic_properties(self):
raise NotImplementedError('use eschema')
-
+
def is_saved(self):
return self.has_eid()
@@ -425,7 +425,7 @@
IntegerProperty = db.IntegerProperty
FloatProperty = db.FloatProperty
ListProperty = db.ListProperty
-SelfReferenceProperty = db.SelfReferenceProperty
+SelfReferenceProperty = db.SelfReferenceProperty
UserProperty = db.UserProperty
--- a/goa/dbinit.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/dbinit.py Mon May 18 10:09:06 2009 +0200
@@ -1,7 +1,7 @@
"""some utility functions for datastore initialization.
:organization: Logilab
-:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -72,7 +72,7 @@
dsrelation = 'o_' + rschema.type
if not dsrelation in gaeentity:
gaeentity[dsrelation] = None
-
+
def fix_entities(schema):
for etype in ('CWUser', 'CWGroup'):
eschema = schema.eschema(etype)
@@ -81,7 +81,7 @@
# XXX o_is on CWEType entity
gaeentity['s_is'] = Key.from_path('CWEType', 'key_' + etype, parent=None)
Put(gaeentity)
-
+
def init_persistent_schema(ssession, schema):
execute = ssession.unsafe_execute
rql = ('INSERT CWEType X: X name %(name)s, X description %(descr)s,'
@@ -105,4 +105,3 @@
execute('INSERT CWProperty X: X pkey %(pk)s, X value%(v)s',
{'pk': u'system.version.%s' % cube,
'v': unicode(config.cube_version(cube))})
-
--- a/goa/dbmyams.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/dbmyams.py Mon May 18 10:09:06 2009 +0200
@@ -5,6 +5,9 @@
- ReferenceProperty.verbose_name, collection_name, etc. (XXX)
XXX proprify this knowing we'll use goa.db
+:organization: Logilab
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
from os.path import join
@@ -68,7 +71,7 @@
# XXX no equivalent to Django's `auto_now`
return dbm2y_default_factory(prop, **kwargs)
-
+
def dbm2y_relation_factory(etype, prop, multiple=False):
"""called if `prop` is a `db.ReferenceProperty`"""
if multiple:
@@ -83,8 +86,8 @@
except AttributeError, ex:
# hack, data_type is still _SELF_REFERENCE_MARKER
return SubjectRelation(etype, cardinality=cardinality)
-
-
+
+
DBM2Y_FACTORY = {
basestring: dbm2y_string_factory,
datastore_types.Text: dbm2y_string_factory,
@@ -107,7 +110,7 @@
self.created = []
self.loaded_files = []
self._instantiate_handlers()
-
+
def finalize(self, register_base_types=False):
return self._build_schema('google-appengine', register_base_types)
@@ -148,11 +151,11 @@
def import_yams_cube_schema(self, templpath):
for filepath in self.get_schema_files(templpath):
self.handle_file(filepath)
-
+
@property
def pyreader(self):
return self._live_handlers['.py']
-
+
import os
from cubicweb import CW_SOFTWARE_ROOT
@@ -183,7 +186,7 @@
'is_', 'is_instance_of',
'read_permission', 'add_permission',
'delete_permission', 'update_permission'):
- loader.import_yams_schema(erschema, 'bootstrap')
+ loader.import_yams_schema(erschema, 'bootstrap')
loader.handle_file(join(SCHEMAS_LIB_DIRECTORY, 'base.py'))
cubes = config['included-yams-cubes']
for cube in reversed(config.expand_cubes(cubes)):
@@ -211,4 +214,3 @@
if getattr(ertype, 'inlined', False):
ertype.inlined = False
return loader.finalize()
-
--- a/goa/gaesource.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/gaesource.py Mon May 18 10:09:06 2009 +0200
@@ -15,7 +15,7 @@
from google.appengine.api.datastore import Key, Entity, Put, Delete
from google.appengine.api import datastore_errors, users
-
+
def _init_groups(guser, euser):
# set default groups
if guser is None:
@@ -82,13 +82,13 @@
gaeentity[relation] = related or None
_mark_modified(session, gaeentity)
-
+
class DatastorePutOp(SingleOperation):
"""delayed put of entities to have less datastore write api calls
* save all modified entities at precommit (should be the first operation
processed, hence the 0 returned by insert_index())
-
+
* in case others precommit operations modify some entities, resave modified
entities at commit. This suppose that no db changes will occurs during
commit event but it should be the case.
@@ -103,10 +103,10 @@
assert not eid in pending
Put(gaeentity)
modified.clear()
-
+
def commit_event(self):
self._put_entities()
-
+
def precommit_event(self):
self._put_entities()
@@ -117,9 +117,9 @@
passwd_rql = "Any P WHERE X is CWUser, X login %(login)s, X upassword P"
auth_rql = "Any X WHERE X is CWUser, X login %(login)s, X upassword %(pwd)s"
_sols = ({'X': 'CWUser', 'P': 'Password'},)
-
+
options = ()
-
+
def __init__(self, repo, appschema, source_config, *args, **kwargs):
AbstractSource.__init__(self, repo, appschema, source_config,
*args, **kwargs)
@@ -128,11 +128,11 @@
self.authenticate = self.authenticate_gauth
else:
self.authenticate = self.authenticate_local
-
+
def reset_caches(self):
"""method called during test to reset potential source caches"""
pass
-
+
def init_creating(self):
pass
@@ -144,7 +144,7 @@
def get_connection(self):
return ConnectionWrapper()
-
+
# ISource interface #######################################################
def compile_rql(self, rql):
@@ -152,7 +152,7 @@
rqlst.restricted_vars = ()
rqlst.children[0].solutions = self._sols
return rqlst
-
+
def set_schema(self, schema):
"""set the application'schema"""
self.interpreter = RQLInterpreter(schema)
@@ -161,13 +161,13 @@
# rql syntax trees used to authenticate users
self._passwd_rqlst = self.compile_rql(self.passwd_rql)
self._auth_rqlst = self.compile_rql(self.auth_rql)
-
+
def support_entity(self, etype, write=False):
"""return true if the given entity's type is handled by this adapter
if write is true, return true only if it's a RW support
"""
return True
-
+
def support_relation(self, rtype, write=False):
"""return true if the given relation's type is handled by this adapter
if write is true, return true only if it's a RW support
@@ -200,7 +200,7 @@
_init_groups(guser, euser)
Put(euser)
return str(euser.key())
-
+
def authenticate_local(self, session, login, password):
"""return CWUser eid for the given login/password if this account is
defined in this source, else raise `AuthenticationError`
@@ -224,8 +224,8 @@
return rset[0][0]
except IndexError:
raise AuthenticationError('bad password')
-
- def syntax_tree_search(self, session, union, args=None, cachekey=None,
+
+ def syntax_tree_search(self, session, union, args=None, cachekey=None,
varmap=None):
"""return result from this source for a rql query (actually from a rql
syntax tree and a solution dictionary mapping each used variable to a
@@ -235,16 +235,16 @@
results, description = self.interpreter.interpret(union, args,
session.datastore_get)
return results # XXX description
-
+
def flying_insert(self, table, session, union, args=None, varmap=None):
raise NotImplementedError
-
+
def add_entity(self, session, entity):
"""add a new entity to the source"""
# do not delay add_entity as other modifications, new created entity
# needs an eid
entity.put()
-
+
def update_entity(self, session, entity):
"""replace an entity in the source"""
gaeentity = entity.to_gae_model()
@@ -253,7 +253,7 @@
for asession in self.repo._sessions.itervalues():
if asession.user.eid == entity.eid:
asession.user.update(dict(gaeentity))
-
+
def delete_entity(self, session, etype, eid):
"""delete an entity from the source"""
# do not delay delete_entity as other modifications to ensure
@@ -270,7 +270,7 @@
_radd(session, gaesubj, gaeobj.key(), 's_' + rtype, cards[0])
_radd(session, gaeobj, gaesubj.key(), 'o_' + rtype, cards[1])
_clear_related_cache(session, gaesubj, rtype, gaeobj)
-
+
def delete_relation(self, session, subject, rtype, object):
"""delete a relation from the source"""
gaesubj, gaeobj, cards = _rinfo(session, subject, rtype, object)
@@ -280,7 +280,7 @@
if not object in pending:
_rdel(session, gaeobj, gaesubj.key(), 'o_' + rtype, cards[1])
_clear_related_cache(session, gaesubj, rtype, gaeobj)
-
+
# system source interface #################################################
def eid_type_source(self, session, eid):
@@ -290,7 +290,7 @@
except datastore_errors.BadKeyError:
raise UnknownEid(eid)
return key.kind(), 'system', None
-
+
def create_eid(self, session):
return None # let the datastore generating key
@@ -303,15 +303,14 @@
record from the entities table to the deleted_entities table
"""
pass
-
+
def fti_unindex_entity(self, session, eid):
"""remove text content for entity with the given eid from the full text
index
"""
pass
-
+
def fti_index_entity(self, session, entity):
"""add text content of a created/modified entity to the full text index
"""
pass
-
--- a/goa/goaconfig.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/goaconfig.py Mon May 18 10:09:06 2009 +0200
@@ -1,7 +1,7 @@
"""google appengine configuration
:organization: Logilab
-:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -32,7 +32,7 @@
"""repository and web application in the same twisted process"""
name = 'app'
repo_method = 'inmemory'
- options = merge_options((
+ options = merge_options((
('included-cubes',
{'type' : 'csv',
'default': [],
@@ -75,7 +75,7 @@
'anonymous access using the app.yaml file)',
'group': 'main', 'inputlevel': 1,
}),
-
+
) + WebConfiguration.options + ServerConfiguration.options)
options = [(optname, optdict) for optname, optdict in options
if not optname in UNSUPPORTED_OPTIONS]
@@ -94,10 +94,10 @@
# deactivate some hooks during [pre|post]create scripts execution
# (unique values check, owned_by/created_by relations setup)
free_wheel = True
-
+
if not os.environ.get('APYCOT_ROOT'):
CUBES_DIR = join(CW_SOFTWARE_ROOT, '../cubes')
-
+
def __init__(self, appid, apphome=None):
if apphome is None:
apphome = 'data'
@@ -111,7 +111,7 @@
if key == 'base-url':
return self._base_url
return super(GAEConfiguration, self).__getitem__(key)
-
+
# overriden from cubicweb base configuration
@property
@@ -136,15 +136,15 @@
def instance_md5_version(self):
return ''
-
+
def _init_base_url(self):
pass
-
+
# overriden from cubicweb server configuration
-
+
def sources(self):
return {'system': {'adapter': 'gae'}}
-
+
def load_schema(self, schemaclasses=None, extrahook=None):
try:
return self._schema
@@ -155,10 +155,11 @@
# goa specific
def repo_session(self, sessionid):
return self.repository()._sessions[sessionid]
-
+
def is_anonymous_user(self, login):
if self['use-google-auth']:
from google.appengine.api import users
return users.get_current_user() is None
else:
return login == self.anonymous_user()[0]
+
--- a/goa/goactl.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/goactl.py Mon May 18 10:09:06 2009 +0200
@@ -36,7 +36,7 @@
(join(CW_SOFTWARE_ROOT, 'embedded', 'mx'), 'mx'),
('/usr/share/fckeditor/', 'fckeditor'),
- (join(CW_SOFTWARE_ROOT, 'web', 'data'), join('cubes', 'shared', 'data')),
+ (join(CW_SOFTWARE_ROOT, 'web', 'data'), join('cubes', 'shared', 'data')),
(join(CW_SOFTWARE_ROOT, 'web', 'wdoc'), join('cubes', 'shared', 'wdoc')),
(join(CW_SOFTWARE_ROOT, 'i18n'), join('cubes', 'shared', 'i18n')),
(join(CW_SOFTWARE_ROOT, 'goa', 'tools'), 'tools'),
@@ -60,7 +60,7 @@
'utils.py',
'vregistry.py',
'view.py',
-
+
'common/mail.py',
'common/migration.py',
'common/mixins.py',
@@ -93,12 +93,12 @@
'sobjects/__init__.py',
'sobjects/notification.py',
-
+
# XXX would be necessary for goa.testlib but require more stuff to be added
# such as server.serverconfig and so on (check devtools.__init__)
# 'devtools/__init__.py',
# 'devtools/fake.py',
-
+
'web/__init__.py',
'web/_exceptions.py',
'web/action.py',
@@ -139,7 +139,7 @@
'wsgi/__init__.py',
'wsgi/handler.py',
'wsgi/request.py',
-
+
'goa/__init__.py',
'goa/db.py',
'goa/dbinit.py',
@@ -149,9 +149,9 @@
'goa/gaesource.py',
'goa/rqlinterpreter.py',
'goa/appobjects/__init__.py',
- 'goa/appobjects/components.py',
- 'goa/appobjects/dbmgmt.py',
- 'goa/appobjects/gauthservice.py',
+ 'goa/appobjects/components.py',
+ 'goa/appobjects/dbmgmt.py',
+ 'goa/appobjects/gauthservice.py',
'goa/appobjects/sessions.py',
'schemas/bootstrap.py',
@@ -178,7 +178,7 @@
"""
name = 'newgapp'
arguments = '<application directory>'
-
+
def run(self, args):
if len(args) != 1:
raise BadCommandUsage("exactly one argument is expected")
@@ -196,7 +196,7 @@
create_dir(split(subdirectory)[0])
create_symlink(directory, join(appldir, subdirectory))
create_init_file(join(appldir, 'logilab'), 'logilab')
- # copy supported part of cubicweb
+ # copy supported part of cubicweb
create_dir(join(appldir, 'cubicweb'))
for fpath in COPY_CW_FILES:
target = join(appldir, 'cubicweb', fpath)
--- a/goa/goavreg.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/goavreg.py Mon May 18 10:09:06 2009 +0200
@@ -1,7 +1,7 @@
"""goa specific registry
:organization: Logilab
-:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -19,7 +19,7 @@
return 'cubes.%s.%s' % (cube, module)
class GAERegistry(CubicWebRegistry):
-
+
def set_schema(self, schema):
"""disable reload hooks of cubicweb registry set_schema method"""
self.schema = schema
@@ -37,7 +37,7 @@
for cube in reversed(self.config.cubes()):
self.load_cube(cube)
self.load_application(applroot)
-
+
def load_directory(self, directory, cube, skip=()):
for filename in listdir(directory):
if filename[-3:] == '.py' and not filename in skip:
@@ -70,6 +70,3 @@
# when using db.Model defined schema, the defined class is used as
# entity class as well and so have to be registered
self._import(_pkg_name(cube, 'schema'))
-
-
-
--- a/goa/overrides/mttransforms.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/overrides/mttransforms.py Mon May 18 10:09:06 2009 +0200
@@ -1,7 +1,7 @@
"""mime type transformation engine for cubicweb, based on mtconverter
: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"
@@ -38,7 +38,7 @@
HAS_PIL_TRANSFORMS = False
HAS_PYGMENTS_TRANSFORMS = False
-
+
class html_to_text(Transform):
inputs = HTML_MIMETYPES
output = 'text/plain'
--- a/goa/overrides/rqlannotation.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/overrides/rqlannotation.py Mon May 18 10:09:06 2009 +0200
@@ -1,6 +1,13 @@
+"""
+:organization: Logilab
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+__docformat__ = "restructuredtext en"
+
def set_qdata(getrschema, union, noinvariant):
pass
-
+
class SQLGenAnnotator(object):
def __init__(self, schema):
self.schema = schema
@@ -9,5 +16,5 @@
def annotate(self, rqlst):
rqlst.has_text_query = False
rqlst.need_distinct = False
-
-
+
+
--- a/goa/overrides/server_utils.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/overrides/server_utils.py Mon May 18 10:09:06 2009 +0200
@@ -6,7 +6,7 @@
pass
def join(self):
pass
-
+
class LoopTask(RepoThread):
def cancel(self):
pass
--- a/goa/rqlinterpreter.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/rqlinterpreter.py Mon May 18 10:09:06 2009 +0200
@@ -23,7 +23,7 @@
return Key(key).kind()
def poss_var_types(myvar, ovar, kind, solutions):
- return frozenset(etypes[myvar] for etypes in solutions
+ return frozenset(etypes[myvar] for etypes in solutions
if etypes[ovar] == kind)
def expand_result(results, result, myvar, values, dsget=None):
@@ -84,7 +84,7 @@
string.append('%s: %s' % (k, v))
return '{%s}' % ', '.join(string)
-
+
class EidMismatch(Exception):
def __init__(self, varname, value):
self.varname = varname
@@ -101,45 +101,45 @@
self.operator = operator
self.rtype = rel.r_type
self.var = rel.children[0]
-
+
def __repr__(self):
return '<%s for %s>' % (self.__class__.__name__, self.rel)
-
+
@property
def rhs(self):
return self.rel.children[1].children[0]
-
+
class MultipleRestriction(object):
def __init__(self, restrictions):
self.restrictions = restrictions
-
+
def resolve(self, solutions, fixed):
return _resolve(self.restrictions, solutions, fixed)
-
+
class VariableSelection(Restriction):
def __init__(self, rel, dsget, prefix='s'):
Restriction.__init__(self, rel)
self._dsget = dsget
self._not = self.rel.neged(strict=True)
self._prefix = prefix + '_'
-
+
def __repr__(self):
return '<%s%s for %s>' % (self._prefix[0], self.__class__.__name__, self.rel)
-
+
@property
def searched_var(self):
if self._prefix == 's_':
return self.var.name
return self.rhs.name
-
+
@property
def constraint_var(self):
if self._prefix == 's_':
return self.rhs.name
return self.var.name
-
+
def _possible_values(self, myvar, ovar, entity, solutions, dsprefix):
if self.rtype == 'identity':
return (entity.key(),)
@@ -150,7 +150,7 @@
value = [value]
vartypes = poss_var_types(myvar, ovar, entity.kind(), solutions)
return (v for v in value if v.kind() in vartypes)
-
+
def complete_and_filter(self, solutions, results):
myvar = self.rhs.name
ovar = self.var.name
@@ -173,8 +173,8 @@
expand_result(results, result, myvar, values, self._dsget)
else:
assert self.rhs.name in results[0]
- self.object_complete_and_filter(solutions, results)
-
+ self.object_complete_and_filter(solutions, results)
+
def filter(self, solutions, results):
myvar = self.rhs.name
ovar = self.var.name
@@ -187,10 +187,10 @@
newsols[key] = frozenset(v for v in values)
if self._not:
if result[myvar].key() in newsols[key]:
- results.remove(result)
+ results.remove(result)
elif not result[myvar].key() in newsols[key]:
results.remove(result)
-
+
def object_complete_and_filter(self, solutions, results):
if self._not:
raise NotImplementedError()
@@ -201,7 +201,7 @@
solutions, 'o_')
expand_result(results, result, myvar, values, self._dsget)
-
+
class EidRestriction(Restriction):
def __init__(self, rel, dsget):
Restriction.__init__(self, rel)
@@ -216,7 +216,7 @@
def _get_value(self, fixed):
return fixed[self.constraint_var].key()
-
+
def fill_query(self, fixed, query, operator=None):
restr = '%s%s %s' % (self._prefix, self.rtype, operator or self.operator)
query[restr] = self._get_value(fixed)
@@ -235,7 +235,7 @@
def _get_value(self, fixed):
return None
-
+
def resolve(self, solutions, fixed):
if self.rtype == 'identity':
raise NotImplementedError()
@@ -255,7 +255,7 @@
raise NotImplementedError('LIKE is only supported for prefix search')
self.operator = '>'
self.value = value[:-1]
-
+
def complete_and_filter(self, solutions, results):
# check lhs var first in case this is a restriction
assert self._not
@@ -263,7 +263,7 @@
for result in results[:]:
if result[myvar].get('s_'+rtype) == value:
results.remove(result)
-
+
def _get_value(self, fixed):
return self.value
@@ -294,7 +294,7 @@
@property
def operator(self):
return 'in'
-
+
class TypeRestriction(AttributeRestriction):
def __init__(self, var):
@@ -302,7 +302,7 @@
def __repr__(self):
return '<%s for %s>' % (self.__class__.__name__, self.var)
-
+
def resolve(self, solutions, fixed):
objs = []
for etype in frozenset(etypes[self.var.name] for etypes in solutions):
@@ -330,7 +330,7 @@
self.args = args
self.term = term
self._solution = self.term.stmt.solutions[0]
-
+
def compute(self, result):
"""return (entity type, value) to which self.term is evaluated according
to the given result dictionnary and to query arguments (self.args)
@@ -341,7 +341,7 @@
args = tuple(n.accept(self, result)[1] for n in node.children)
value = self.functions[node.name](*args)
return node.get_type(self._solution, self.args), value
-
+
def visit_variableref(self, node, result):
value = result[node.name]
try:
@@ -350,11 +350,11 @@
except AttributeError:
etype = self._solution[node.name]
return etype, value
-
+
def visit_constant(self, node, result):
return node.get_type(kwargs=self.args), node.eval(self.args)
-
-
+
+
class RQLInterpreter(object):
"""algorithm:
1. visit the restriction clauses and collect restriction for each subject
@@ -369,7 +369,7 @@
for each solution in select'solutions:
1. resolve variables which have attribute restriction
2. resolve relation restriction
- 3. resolve selection and add to global results
+ 3. resolve selection and add to global results
"""
def __init__(self, schema):
self.schema = schema
@@ -379,15 +379,15 @@
'UPPER': lambda x: x.upper()}
for cb in SQL_CONNECT_HOOKS.get('sqlite', []):
cb(self)
-
+
# emulate sqlite connection interface so we can reuse stored procedures
def create_function(self, name, nbargs, func):
self._stored_proc[name] = func
-
+
def create_aggregate(self, name, nbargs, func):
self._stored_proc[name] = func
-
+
def execute(self, operation, parameters=None, eid_key=None, build_descr=True):
rqlst = self.rqlhelper.parse(operation, annotate=True)
try:
@@ -397,7 +397,7 @@
else:
results, description = self.interpret(rqlst, parameters)
return ResultSet(results, operation, parameters, description, rqlst=rqlst)
-
+
def interpret(self, node, kwargs, dsget=None):
if dsget is None:
self._dsget = Get
@@ -417,7 +417,7 @@
results += pres
description += pdescr
return results, description
-
+
def visit_select(self, node, extra):
constraints = {}
if node.where is not None:
@@ -441,7 +441,7 @@
for varname, restrictions in constraints.iteritems():
for restr in restrictions[:]:
if isinstance(restr, EidRestriction):
- assert not varname in fixed
+ assert not varname in fixed
try:
value = restr.resolve(kwargs)
fixed[varname] = value
@@ -455,7 +455,7 @@
if isinstance(restr, AttributeRestriction):
toresolve.setdefault(varname, []).append(restr)
elif isinstance(restr, NotRelationRestriction) or (
- isinstance(restr, RelationRestriction) and
+ isinstance(restr, RelationRestriction) and
not restr.searched_var in fixed and restr.constraint_var in fixed):
toresolve.setdefault(varname, []).append(restr)
else:
@@ -495,7 +495,7 @@
partres.append({varname: value})
elif not varname in partres[0]:
# cartesian product
- for res in partres:
+ for res in partres:
res[varname] = values[0]
for res in partres[:]:
for value in values[1:]:
@@ -503,14 +503,14 @@
res[varname] = value
partres.append(res)
else:
- # union
+ # union
for res in varpartres:
for value in values:
res = res.copy()
res[varname] = value
partres.append(res)
#print 'partres', len(partres)
- #print partres
+ #print partres
# Note: don't check for empty partres since constant selection may still
# produce result at this point
# sort to get RelationRestriction before AttributeSelection
@@ -569,14 +569,14 @@
append_result(res, descr, i, j, value, etype)
#print '--------->', res
return res, descr
-
- def visit_and(self, node, constraints, extra):
+
+ def visit_and(self, node, constraints, extra):
for child in node.children:
child.accept(self, constraints, extra)
def visit_exists(self, node, constraints, extra):
extra['has_exists'] = True
self.visit_and(node, constraints, extra)
-
+
def visit_not(self, node, constraints, extra):
for child in node.children:
child.accept(self, constraints, extra)
@@ -584,7 +584,7 @@
extra.pop(node)
except KeyError:
raise NotImplementedError()
-
+
def visit_relation(self, node, constraints, extra):
if node.is_types_restriction():
return
@@ -600,7 +600,7 @@
self._visit_non_final_neged_relation(rschema, node, constraints)
else:
self._visit_non_final_relation(rschema, node, constraints)
-
+
def _visit_non_final_relation(self, rschema, node, constraints, not_=False):
lhs, rhs = node.get_variable_parts()
for v1, v2, prefix in ((lhs, rhs, 's'), (rhs, lhs, 'o')):
@@ -611,14 +611,14 @@
if nbrels > 1:
constraints.setdefault(v1.name, []).append(
RelationRestriction(node, self._dsget, prefix))
- # just init an empty list for v2 variable to avoid a
+ # just init an empty list for v2 variable to avoid a
# TypeRestriction being added for it
constraints.setdefault(v2.name, [])
break
else:
constraints.setdefault(rhs.name, []).append(
VariableSelection(node, self._dsget, 's'))
-
+
def _visit_non_final_neged_relation(self, rschema, node, constraints):
lhs, rhs = node.get_variable_parts()
for v1, v2, prefix in ((lhs, rhs, 's'), (rhs, lhs, 'o')):
@@ -653,16 +653,16 @@
AttributeInRestriction(node, extra['kwargs']))
else:
raise NotImplementedError()
-
+
def _not_implemented(self, *args, **kwargs):
raise NotImplementedError()
-
+
visit_or = _not_implemented
# shouldn't occurs
visit_set = _not_implemented
visit_insert = _not_implemented
visit_delete = _not_implemented
-
+
from logging import getLogger
from cubicweb import set_log_methods
--- a/goa/skel/loader.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/skel/loader.py Mon May 18 10:09:06 2009 +0200
@@ -4,7 +4,7 @@
from cubicweb import goa
from cubicweb.goa.goaconfig import GAEConfiguration
from cubicweb.goa.dbinit import create_user, create_groups
-
+
# compute application's root directory
APPLROOT = dirname(abspath(__file__))
# apply monkey patches first
--- a/goa/skel/main.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/skel/main.py Mon May 18 10:09:06 2009 +0200
@@ -2,7 +2,7 @@
to change anything here.
:organization: Logilab
-:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
--- a/goa/test/data/views.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/test/data/views.py Mon May 18 10:09:06 2009 +0200
@@ -21,7 +21,7 @@
class MyIndex(StartupView):
id = 'index'
-
+
def call(self):
ctx = template.Context({'user': self.req.user})
return INDEX_TEMPLATE.render(ctx)
--- a/goa/test/unittest_db.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/test/unittest_db.py Mon May 18 10:09:06 2009 +0200
@@ -10,11 +10,11 @@
class Blog(db.Model):
data = db.BlobProperty()
-
+
class DBTest(GAEBasedTC):
config = GAEConfiguration('toto')
config.global_set_option('use-google-auth', False)
-
+
MODEL_CLASSES = (Blog,)
def test_set_none_relation(self):
@@ -25,7 +25,7 @@
def test_euser_key(self):
euser = self.add_entity('CWUser', login=u'toto', upassword='toto')
self.assertEquals(euser.key().name(), 'key_toto')
-
+
def test_egroup_key(self):
egroup = self.add_entity('CWGroup', name=u'toto')
self.assertEquals(egroup.key().name(), 'key_toto')
@@ -40,7 +40,7 @@
text = u'e'*501
entity = self.add_entity('State', name=u'test', description=text)
self.assertIsInstance(entity.description, unicode)
- self.failIf(isinstance(entity.description, Text))
+ self.failIf(isinstance(entity.description, Text))
self.assertEquals(entity.description, text)
def test_long_accentued_text(self):
@@ -48,7 +48,7 @@
text = u'é'*500
entity = self.add_entity('State', name=u'test', description=text)
self.assertIsInstance(entity.description, unicode)
- self.failIf(isinstance(entity.description, Text))
+ self.failIf(isinstance(entity.description, Text))
self.assertEquals(entity.description, text)
def test_blob(self):
@@ -56,10 +56,10 @@
entity = self.add_entity('Blog', data=data)
self.assertIsInstance(entity.data, Binary)
value = entity.data.getvalue()
- self.failIf(isinstance(value, Blob))
+ self.failIf(isinstance(value, Blob))
self.assertEquals(value, data)
-
-
+
+
if __name__ == '__main__':
from logilab.common.testlib import unittest_main
unittest_main()
--- a/goa/test/unittest_editcontroller.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/test/unittest_editcontroller.py Mon May 18 10:09:06 2009 +0200
@@ -12,23 +12,23 @@
class EditControllerTC(GAEBasedTC):
-
+
config = GAEConfiguration('toto')
config.global_set_option('use-google-auth', False)
config.global_set_option('schema-type', 'yams')
config.global_set_option('included-cubes', ())
config.global_set_option('included-yams-cubes', ('blog',))
-
+
MODEL_CLASSES = ()
from cubicweb.web.views import editcontroller
from cubicweb.entities import lib
LOAD_APP_MODULES = (editcontroller, lib)
-
+
def setUp(self):
GAEBasedTC.setUp(self)
self.req = self.request()
self.ctrl = self.get_ctrl(self.req)
-
+
def get_ctrl(self, req):
return self.vreg.select(self.vreg.registry_objects('controllers', 'edit'),
req=req, appli=self)
@@ -69,13 +69,13 @@
"""check behaviour of this controller without any form parameter"""
self.req.form = {}
self.assertRaises(ValidationError, self.publish, self.req)
-
+
def test_validation_unique(self):
- """test creation of two linked entities"""
+ """test creation of two linked entities"""
user = self.user
self.req.form = {'eid': 'X', '__type:X': 'CWUser',
- 'login:X': self.user.login, 'edits-login:X': u'',
- 'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'',
+ 'login:X': self.user.login, 'edits-login:X': u'',
+ 'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'',
}
self.assertRaises(ValidationError, self.publish, self.req)
@@ -155,23 +155,23 @@
self.assertUnorderedIterableEquals([g.eid for g in e.in_group], groupeids)
#stateeids = [eid for eid, in self.req.execute('State S WHERE S name "activated"')]
#self.assertEquals([s.eid for s in e.in_state], stateeids)
-
-
+
+
def test_create_multiple_linked(self):
gueid = self.req.execute('CWGroup G WHERE G name "users"')[0][0]
self.req.form = {'eid': ['X', 'Y'],
-
+
'__type:X': 'CWUser',
'__maineid' : 'X',
- 'login:X': u'adim', 'edits-login:X': u'',
- 'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'',
+ 'login:X': u'adim', 'edits-login:X': u'',
+ 'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'',
'surname:X': u'Di Mascio', 'edits-surname:X': '',
- 'in_group:X': gueid, 'edits-in_group:X': INTERNAL_FIELD_VALUE,
-
+ 'in_group:X': gueid, 'edits-in_group:X': INTERNAL_FIELD_VALUE,
+
'__type:Y': 'EmailAddress',
'address:Y': u'dima@logilab.fr', 'edits-address:Y': '',
- 'use_email:X': 'Y', 'edits-use_email:X': INTERNAL_FIELD_VALUE,
+ 'use_email:X': 'Y', 'edits-use_email:X': INTERNAL_FIELD_VALUE,
}
path, params = self.expect_redirect_publish()
# should be redirected on the created person
@@ -180,17 +180,17 @@
self.assertEquals(e.surname, 'Di Mascio')
email = e.use_email[0]
self.assertEquals(email.address, 'dima@logilab.fr')
-
+
def test_edit_multiple_linked(self):
peid = self.create_user('adim').eid
self.req.form = {'eid': [peid, 'Y'],
'__type:%s'%peid: 'CWUser',
'surname:%s'%peid: u'Di Masci', 'edits-surname:%s'%peid: '',
-
+
'__type:Y': 'EmailAddress',
'address:Y': u'dima@logilab.fr', 'edits-address:Y': '',
'use_email:%s'%peid: 'Y', 'edits-use_email:%s'%peid: INTERNAL_FIELD_VALUE,
-
+
'__redirectrql': 'Any X WHERE X eid %s'%peid,
}
path, params = self.expect_redirect_publish()
@@ -200,14 +200,14 @@
self.assertEquals(e.surname, 'Di Masci')
email = e.use_email[0]
self.assertEquals(email.address, 'dima@logilab.fr')
-
+
emaileid = email.eid
self.req.form = {'eid': [peid, emaileid],
'__type:%s'%peid: 'CWUser',
'surname:%s'%peid: u'Di Masci', 'edits-surname:%s'%peid: 'Di Masci',
'__type:%s'%emaileid: 'EmailAddress',
'address:%s'%emaileid: u'adim@logilab.fr', 'edits-address:%s'%emaileid: 'dima@logilab.fr',
- 'use_email:%s'%peid: emaileid, 'edits-use_email:%s'%peid: emaileid,
+ 'use_email:%s'%peid: emaileid, 'edits-use_email:%s'%peid: emaileid,
'__redirectrql': 'Any X WHERE X eid %s'%peid,
}
path, params = self.expect_redirect_publish()
@@ -220,21 +220,21 @@
email = e.use_email[0]
self.assertEquals(email.address, 'adim@logilab.fr')
-
+
def test_password_confirm(self):
"""test creation of two linked entities
- """
+ """
user = self.user
self.req.form = {'__cloned_eid:X': user.eid,
'eid': 'X', '__type:X': 'CWUser',
- 'login:X': u'toto', 'edits-login:X': u'',
- 'upassword:X': u'toto', 'edits-upassword:X': u'',
+ 'login:X': u'toto', 'edits-login:X': u'',
+ 'upassword:X': u'toto', 'edits-upassword:X': u'',
}
self.assertRaises(ValidationError, self.publish, self.req)
self.req.form = {'__cloned_eid:X': user.eid,
'eid': 'X', '__type:X': 'CWUser',
- 'login:X': u'toto', 'edits-login:X': u'',
- 'upassword:X': u'toto', 'upassword-confirm:X': u'tutu', 'edits-upassword:X': u'',
+ 'login:X': u'toto', 'edits-login:X': u'',
+ 'upassword:X': u'toto', 'upassword-confirm:X': u'tutu', 'edits-upassword:X': u'',
}
self.assertRaises(ValidationError, self.publish, self.req)
@@ -288,7 +288,7 @@
self.assertEquals(rset[0][0], 'FOO')
finally:
del CWUser.custom_login_edit
-
+
def test_redirect_apply_button(self):
redirectrql = rql_for_eid(4012) # whatever
self.req.form = {
@@ -355,21 +355,21 @@
path, params = self.expect_redirect_publish()
self.assertEquals(path, 'view')
self.assertEquals(params, {u'__message': u'entities deleted'})
-
+
def test_nonregr_multiple_empty_email_addr(self):
gueid = self.req.execute('CWGroup G WHERE G name "users"')[0][0]
self.req.form = {'eid': ['X', 'Y'],
-
+
'__type:X': 'CWUser',
- 'login:X': u'adim', 'edits-login:X': u'',
- 'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'',
- 'in_group:X': gueid, 'edits-in_group:X': INTERNAL_FIELD_VALUE,
-
+ 'login:X': u'adim', 'edits-login:X': u'',
+ 'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'',
+ 'in_group:X': gueid, 'edits-in_group:X': INTERNAL_FIELD_VALUE,
+
'__type:Y': 'EmailAddress',
'address:Y': u'', 'edits-address:Y': '',
'alias:Y': u'', 'edits-alias:Y': '',
- 'use_email:X': 'Y', 'edits-use_email:X': INTERNAL_FIELD_VALUE,
+ 'use_email:X': 'Y', 'edits-use_email:X': INTERNAL_FIELD_VALUE,
}
self.assertRaises(ValidationError, self.publish, self.req)
@@ -386,7 +386,7 @@
{'p' : p.eid, 'e' : e.eid})
self.req.form = {'__cloned_eid:X': p.eid,
'eid': 'X', '__type:X': 'CWUser',
- 'login': u'dodo', 'edits-login': u'dodo',
+ 'login': u'dodo', 'edits-login': u'dodo',
'surname:X': u'Boom', 'edits-surname:X': u'',
'__errorurl' : "whatever but required",
}
@@ -405,7 +405,7 @@
finally:
p.__class__.skip_copy_for = old_skips
-
+
if __name__ == '__main__':
from logilab.common.testlib import unittest_main
unittest_main()
--- a/goa/test/unittest_metadata.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/test/unittest_metadata.py Mon May 18 10:09:06 2009 +0200
@@ -7,7 +7,7 @@
from google.appengine.api import datastore
-class Article(db.Model):
+class Article(db.Model):
content = db.TextProperty()
synopsis = db.StringProperty(default='hello')
@@ -15,20 +15,20 @@
diem = db.DateProperty(required=True, auto_now_add=True)
title = db.StringProperty(required=True)
content = db.TextProperty()
- talks_about = db.ReferenceProperty(Article)
- cites = db.SelfReferenceProperty()
+ talks_about = db.ReferenceProperty(Article)
+ cites = db.SelfReferenceProperty()
-
+
class MetaDataTC(GAEBasedTC):
MODEL_CLASSES = (Article, Blog)
-
+
def setUp(self):
GAEBasedTC.setUp(self)
self.req = self.request()
self.a = self.add_entity('Article')
self.p = self.add_entity('CWProperty', pkey=u'ui.language', value=u'en')
self.session.commit()
-
+
def _test_timestamp(self, entity, attr, sleep=0.1):
timestamp = getattr(entity, attr)
self.failUnless(timestamp)
@@ -41,20 +41,20 @@
entity.set_attributes(value=u'en')
self.session.commit()
return timestamp
-
+
def test_creation_date_dbmodel(self):
cdate = self._test_timestamp(self.a, 'creation_date')
self.assertEquals(cdate, self.a.creation_date)
-
+
def test_creation_date_yams(self):
cdate = self._test_timestamp(self.p, 'creation_date')
self.assertEquals(cdate, self.p.creation_date)
-
+
def test_modification_date_dbmodel(self):
mdate = self._test_timestamp(self.a, 'modification_date', sleep=1)
a = self.execute('Any X WHERE X eid %(x)s', {'x': self.a.eid}, 'x').get_entity(0, 0)
self.failUnless(mdate < a.modification_date, (mdate, a.modification_date))
-
+
def test_modification_date_yams(self):
mdate = self._test_timestamp(self.p, 'modification_date', sleep=1)
p = self.execute('Any X WHERE X eid %(x)s', {'x': self.p.eid}, 'x').get_entity(0, 0)
@@ -67,10 +67,10 @@
dbmodel = entity.to_gae_model()
self.assertEquals(len(dbmodel['s_owned_by']), 1)
self.assertIsInstance(dbmodel['s_owned_by'][0], datastore.Key)
-
+
def test_owned_by_dbmodel(self):
self._test_owned_by(self.a)
-
+
def test_owned_by_yams(self):
self._test_owned_by(self.p)
@@ -79,16 +79,16 @@
creator = entity.created_by[0]
self.assertIsInstance(creator, db.Model)
self.assertIsInstance(entity.to_gae_model()['s_created_by'], datastore.Key)
-
+
def test_created_by_dbmodel(self):
self._test_created_by(self.a)
-
+
def test_created_by_dbmodel(self):
self._test_created_by(self.p)
-
+
def test_user_owns_dbmodel(self):
self.failUnless(self.req.user.owns(self.a.eid))
-
+
def test_user_owns_yams(self):
self.failUnless(self.req.user.owns(self.p.eid))
@@ -96,11 +96,11 @@
en = self.execute('Any EN WHERE E name EN, X is E, X eid %(x)s', {'x': self.a.eid}, 'x')[0][0]
self.assertEquals(en, 'Article')
en = self.execute('Any EN WHERE E name EN, X is E, X eid %(x)s', {'x': self.p.eid}, 'x')[0][0]
- self.assertEquals(en, 'CWProperty')
+ self.assertEquals(en, 'CWProperty')
en = self.execute('Any EN WHERE E name EN, X is E, X eid %(x)s', {'x': self.req.user.eid}, 'x')[0][0]
self.assertEquals(en, 'CWUser')
-
+
if __name__ == '__main__':
from logilab.common.testlib import unittest_main
unittest_main()
--- a/goa/test/unittest_rql.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/test/unittest_rql.py Mon May 18 10:09:06 2009 +0200
@@ -32,7 +32,7 @@
# end stored procedure definition #############################################
-class Article(db.Model):
+class Article(db.Model):
content = db.TextProperty()
synopsis = db.StringProperty(default=u'hello')
@@ -40,14 +40,14 @@
diem = db.DateProperty(required=True, auto_now_add=True)
content = db.TextProperty()
itemtype = db.StringProperty(required=True, choices=(u'personal', u'business'))
- talks_about = db.ReferenceProperty(Article)
- cites = db.SelfReferenceProperty()
+ talks_about = db.ReferenceProperty(Article)
+ cites = db.SelfReferenceProperty()
data = db.BlobProperty()
-
+
class RQLTest(GAEBasedTC):
MODEL_CLASSES = (Article, Blog)
-
+
def setUp(self):
GAEBasedTC.setUp(self)
# hack to make talks_about cardinality to ** instead of ?*
@@ -59,13 +59,13 @@
self.execute('SET X talks_about Y WHERE X eid %(x)s, Y eid %(y)s',
{'x': self.blog.eid, 'y': self.article.eid})
self.commit()
-
+
def _check_rset_size(self, rset, row, col):
self.assertEquals(len(rset), row)
self.assertEquals(len(rset[0]), col)
self.assertEquals(len(rset.description), row)
self.assertEquals(len(rset.description[0]), col)
-
+
def _check_blog_rset(self, rset):
self._check_rset_size(rset, 1, 1)
self.assertEquals(rset.description[0][0], 'Blog')
@@ -121,20 +121,20 @@
self.assertEquals(len(rset), 2)
self.assertEquals(rset.description, [('Blog',), ('Blog',)])
-
+
def test_2_attribute_selection_1(self):
rset = self.req.execute('Any X,D,C WHERE X is Blog, X diem D, X content C')
self._check_rset_size(rset, 1, 3)
self.assertEquals(rset[0], [self.blog.eid, today(), u'hop'])
self.assertEquals(rset.description[0], ('Blog', 'Date', 'String'))
self.assertIsInstance(rset[0][1], DateTimeType)
-
+
def test_2_attribute_selection_2(self):
rset = self.req.execute('Any D,C WHERE X is Blog, X diem D, X content C')
self._check_rset_size(rset, 1, 2)
self.assertEquals(rset[0], [today(), u'hop'])
self.assertEquals(rset.description[0], ('Date', 'String'))
-
+
def test_2_attribute_selection_binary(self):
rset = self.req.execute('Any D WHERE X is Blog, X data D')
self._check_rset_size(rset, 1, 1)
@@ -147,19 +147,19 @@
self.assertIsInstance(rset[0][0], Binary)
value = rset[0][0].getvalue()
self.assertIsInstance(value, str)
- self.failIf(isinstance(value, Blob))
+ self.failIf(isinstance(value, Blob))
self.assertEquals(value, 'raw data')
self.assertEquals(rset.description[0], ('Bytes',))
-
+
def test_2_attribute_selection_long_text(self):
self.blog['content'] = text = 'a'*501
self.blog.put()
rset = self.req.execute('Any C WHERE X is Blog, X content C')
self._check_rset_size(rset, 1, 1)
self.assertIsInstance(rset[0][0], unicode)
- self.failIf(isinstance(rset[0][0], Text))
+ self.failIf(isinstance(rset[0][0], Text))
self.assertEquals(rset[0][0], text)
-
+
def test_2_attribute_selection_transformation(self):
rset = self.req.execute('Any X,UPPER(C) WHERE X is Blog, X content C')
self._check_rset_size(rset, 1, 2)
@@ -172,15 +172,15 @@
self._check_blog_rset(rset)
rset = self.req.execute('Any X WHERE X itemtype "business"')
self.assertEquals(len(rset), 0)
-
+
def test_3_ambigous_attribute_restriction_1(self):
rset = self.req.execute('Any X WHERE X content "hello"')
self.assertEquals(len(rset), 0)
-
+
def test_3_ambigous_attribute_restriction_2(self):
rset = self.req.execute('Any X WHERE X content "hop"')
self._check_blog_rset(rset)
-
+
def test_3_ambigous_attribute_restriction_3(self):
article = Article(content=u'hop')
article.put()
@@ -193,11 +193,11 @@
rset = self.req.execute('Any X WHERE X eid %(x)s, X content "hola"',
{'x': self.blog.eid})
self.assertEquals(len(rset), 0)
-
+
def test_3_multiple_attribute_restriction(self):
rset = self.req.execute('Any X WHERE X content "hop", X itemtype "personal"')
self._check_blog_rset(rset)
-
+
def test_3_incoherant_multiple_attribute_restriction(self):
rset = self.req.execute('Any X WHERE X content "hip", X itemtype "personal"')
self.assertEquals(len(rset), 0)
@@ -234,7 +234,7 @@
repo = self.config.repository()
versions = repo.get_versions()
self.assertEquals(versions.keys(), ['cubicweb'])
-
+
def _setup_relation_description(self):
self.article2 = self.add_entity('Article', content=u'hop')
self.blog2 = self.add_entity('Blog', itemtype=u'personal', content=u'hip')
@@ -242,7 +242,7 @@
{'x': self.blog2.eid, 'y': self.article2.eid})
self.blog3 = self.add_entity('Blog', itemtype=u'business', content=u'hep')
self.commit()
-
+
def test_4_relation_restriction_1(self):
self._setup_relation_description()
rset = self.req.execute('Any X WHERE X talks_about Y')
@@ -250,7 +250,7 @@
self.assertUnorderedIterableEquals([r[0] for r in rset],
[self.blog.eid, self.blog2.eid])
self.assertUnorderedIterableEquals([r[0] for r in rset.description], ['Blog', 'Blog'])
-
+
def test_4_relation_restriction_2(self):
self._setup_relation_description()
rset = self.req.execute('Any Y WHERE X talks_about Y')
@@ -259,7 +259,7 @@
[self.article.eid, self.article2.eid])
self.assertUnorderedIterableEquals([r[0] for r in rset.description],
['Article', 'Article'])
-
+
def test_4_relation_restriction_3(self):
self._setup_relation_description()
rset = self.req.execute('Any X,Y WHERE X talks_about Y')
@@ -270,7 +270,7 @@
self.assertUnorderedIterableEquals([tuple(r) for r in rset.description],
[('Blog', 'Article'),
('Blog', 'Article')])
-
+
def test_4_relation_restriction_4(self):
self._setup_relation_description()
rset = self.req.execute('Any X,Y WHERE X talks_about Y, X eid %(x)s',
@@ -278,7 +278,7 @@
self._check_rset_size(rset, 1, 2)
self.assertEquals(rset[0], [self.blog.eid, self.article.eid])
self.assertUnorderedIterableEquals(rset.description[0], ['Blog', 'Article'])
-
+
def test_4_relation_restriction_5(self):
self._setup_relation_description()
rset = self.req.execute('Any X,Y WHERE X talks_about Y, Y eid %(x)s',
@@ -286,7 +286,7 @@
self._check_rset_size(rset, 1, 2)
self.assertEquals(rset[0], [self.blog.eid, self.article.eid])
self.assertUnorderedIterableEquals(rset.description[0], ['Blog', 'Article'])
-
+
def test_4_relation_subject_restriction(self):
self._setup_relation_description()
rset = self.req.execute('Any X,Y WHERE X talks_about Y, X content %(c)s',
@@ -294,7 +294,7 @@
self._check_rset_size(rset, 1, 2)
self.assertEquals(rset[0], [self.blog.eid, self.article.eid])
self.assertUnorderedIterableEquals(rset.description[0], ['Blog', 'Article'])
-
+
def test_4_relation_object_restriction(self):
self._setup_relation_description()
rset = self.req.execute('Any X WHERE X is Blog, X talks_about Y, Y content %(c)s',
@@ -302,7 +302,7 @@
self._check_rset_size(rset, 1, 1)
self.assertEquals(rset[0], [self.blog.eid])
self.assertUnorderedIterableEquals(rset.description[0], ['Blog'])
-
+
def test_4_relation_subject_object_restriction(self):
article2 = self.add_entity('Article', content=u'very interesting')
rset = self.req.execute('Any X,XC WHERE X is Blog, X content XC, X content %(xc)s, '
@@ -311,20 +311,20 @@
self._check_rset_size(rset, 1, 2)
self.assertEquals(rset[0], [self.blog.eid, self.blog.content])
self.assertUnorderedIterableEquals(rset.description[0], ['Blog', 'String'])
-
+
def test_4_relation_subject_object_restriction_no_res(self):
article2 = self.add_entity('Article', content=u'very interesting')
rset = self.req.execute('Any X,XC WHERE X is Blog, X content XC, X content %(xc)s, '
'X talks_about Y, Y content %(c)s',
{'xc': 'hip', 'c': 'very interesting'})
self.assertEquals(len(rset), 0)
-
+
def test_4_relation_subject_object_restriction_no_res_2(self):
rset = self.req.execute('Any X,XC WHERE X is Blog, X content XC, X content %(xc)s, '
'X talks_about Y, Y content %(c)s',
{'xc': 'hop', 'c': 'not interesting'})
self.assertEquals(len(rset), 0)
-
+
def test_4_relation_restriction_7(self):
self._setup_relation_description()
rset = self.req.execute('Any XC,XD,YC WHERE X talks_about Y, Y eid %(x)s,'
@@ -333,7 +333,7 @@
self._check_rset_size(rset, 1, 3)
self.assertEquals(rset[0], [self.blog.content, self.blog.diem, self.article.content])
self.assertUnorderedIterableEquals(rset.description[0], ['String', 'Date', 'String'])
-
+
def test_4_relation_restriction_8(self):
self._setup_relation_description()
rset = self.req.execute('Any X,Y WHERE X cites Y, Y eid %(x)s', {'x': self.blog.eid})
@@ -346,7 +346,7 @@
rset = self.req.execute('Any X,Y WHERE X talks_about Y, X eid %(x)s, Y eid %(y)s',
{'x': self.blog.eid, 'y': article2.eid})
self._check_rset_size(rset, 1, 2)
-
+
def test_4_ambiguous_subject_relation(self):
ye = self.add_entity('YamsEntity')
self.req.execute('SET X ambiguous_relation Y WHERE X eid %(x)s, Y eid %(y)s',
@@ -365,7 +365,7 @@
self._check_rset_size(rset, 2, 1)
self.assertUnorderedIterableEquals([r[0] for r in rset], [self.blog.eid, self.article.eid])
self.assertUnorderedIterableEquals([r[0] for r in rset.description], ['Blog', 'Article'])
-
+
def test_4_relation_selection(self):
req = self.request()
rset = req.execute('Any N WHERE G content N, U talks_about G, U eid %(u)s', {'u': self.blog.eid})
@@ -381,7 +381,7 @@
[[self.blog3.eid, 'hep'],
[self.blog2.eid, 'hip'],
[self.blog.eid, 'hop']])
-
+
def test_5_orderby_desc(self):
self._setup_relation_description()
rset = self.req.execute('Any X,XC ORDERBY XC DESC WHERE X is Blog, X content XC')
@@ -417,7 +417,7 @@
[[self.blog.eid, 'hop', 'personal'],
[self.blog2.eid, 'hip', 'personal'],
[self.blog3.eid, 'hep', 'business']])
-
+
def test_5_orderby_several_terms_mixed_order(self):
self._setup_relation_description()
rset = self.req.execute('Any X,XC,XI ORDERBY XI ASC,XC DESC WHERE X is Blog, X content XC, X itemtype XI')
@@ -449,25 +449,25 @@
'WHERE X is Blog, X itemtype XIT')
self._check_rset_size(rset, 2, 1)
self.assertEquals(rset.rows, [[self.blog.eid], [blog2.eid]])
-
-
+
+
def test_6_limit(self):
self._setup_relation_description()
rset = self.req.execute('Any X LIMIT 2 WHERE X is Blog')
self._check_rset_size(rset, 2, 1)
-
+
def test_6_offset(self):
self._setup_relation_description()
rset = self.req.execute('Any XC ORDERBY XC DESC OFFSET 1 WHERE X is Blog, X content XC')
self._check_rset_size(rset, 2, 1)
self.assertEquals(rset.rows, [['hip'], ['hep']])
-
+
def test_6_limit_and_orderby(self):
self._setup_relation_description()
rset = self.req.execute('Any XC ORDERBY XC LIMIT 2 WHERE X is Blog, X content XC')
self._check_rset_size(rset, 2, 1)
self.assertEquals(rset.rows, [['hep'], ['hip']])
-
+
def test_6_limit_offset_and_orderby(self):
self._setup_relation_description()
rset = self.req.execute('Any XC ORDERBY XC LIMIT 2 OFFSET 0 WHERE X is Blog, X content XC')
@@ -481,7 +481,7 @@
self.assertEquals(rset.rows, [['hop']])
rset = self.req.execute('Any XC ORDERBY XC LIMIT 2 OFFSET 3 WHERE X is Blog, X content XC')
self.failIf(rset)
-
+
def test_7_simple_datetimecast(self):
self._setup_relation_description()
@@ -496,7 +496,7 @@
rset = self.req.execute('Any X WHERE X is Blog, X creation_date <= "%s"'
% _tomorrow.strftime('%Y-%m-%d'))
self._check_rset_size(rset, 3, 1)
-
+
def test_7_identity_relation(self):
rset = self.req.execute('Any X WHERE X identity Y, X eid %(x)s, Y eid %(y)s',
{'x': self.user.eid, 'y': self.user.eid})
@@ -509,13 +509,13 @@
rset = self.req.execute('Any X WHERE X identity Y, X eid %(x)s, Y eid %(y)s',
{'x': self.blog.eid, 'y': blog2.eid})
self.failIf(rset)
-
+
def test_8_not_relation_1(self):
rset = self.req.execute('Any X WHERE X identity U, NOT U in_group G, '
'G name "guests", X eid %(x)s, U eid %(u)s',
{'x': self.user.eid, 'u': self.user.eid})
self._check_rset_size(rset, 1, 1)
- self.assertEquals(rset.rows, [[self.user.eid]])
+ self.assertEquals(rset.rows, [[self.user.eid]])
def test_8_not_relation_linked_subject(self):
rset = self.req.execute('Any X WHERE NOT X talks_about Y, Y eid %(y)s',
@@ -524,7 +524,7 @@
blog2 = self.add_entity('Blog', content=u'hop', itemtype=u'personal')
self.commit()
rset = self.req.execute('Any X WHERE NOT X talks_about Y, Y eid %(y)s',
- {'y': self.article.eid})
+ {'y': self.article.eid})
self._check_rset_size(rset, 1, 1)
self.assertEquals(rset.rows, [[blog2.eid]])
@@ -541,7 +541,7 @@
def test_8_not_relation_linked_attr(self):
self.skip('not yet implemented')
- # TODO: this should generated
+ # TODO: this should generated
# Query(X)[s_talks_about] > "hop" || Query(X)[s_talks_about] < "hop"
article2 = self.add_entity('Article', content=u'hop')
self.req.execute('SET X talks_about Y WHERE X eid %(x)s, Y eid %(y)s',
@@ -564,13 +564,13 @@
rset = self.req.execute('Any Y WHERE NOT X talks_about Y')
self._check_rset_size(rset, 1, 1)
self.assertEquals(rset.rows, [[article2.eid]])
-
+
def test_8_not_relation_final_1(self):
rset = self.req.execute('Any G WHERE G is CWGroup, NOT G name "guests"')
self._check_rset_size(rset, 2, 1)
self.assertUnorderedIterableEquals([g.name for g in rset.entities()],
- ['users', 'managers'])
-
+ ['users', 'managers'])
+
def test_8_not_relation_final_2(self):
rset = self.req.execute('Any GN WHERE G is CWGroup, NOT G name "guests", G name GN')
self._check_rset_size(rset, 2, 1)
@@ -587,8 +587,8 @@
rset = self.req.execute('Any X WHERE X is Blog, EXISTS(X talks_about Y)')
self._check_rset_size(rset, 1, 1)
self.assertEquals(rset.rows, [[self.blog.eid]])
-
-
+
+
def test_error_unknown_eid(self):
rset = self.req.execute('Any X WHERE X eid %(x)s', {'x': '1234'})
self.assertEquals(len(rset), 0)
@@ -603,6 +603,6 @@
rset = self.execute('Any X WHERE Y inlined_relation X, Y eid %(y)s', {'y': eid})
self._check_rset_size(rset, 1, 1)
self.assertEquals(rset[0][0], self.blog.eid)
-
+
if __name__ == '__main__':
unittest_main()
--- a/goa/test/unittest_schema.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/test/unittest_schema.py Mon May 18 10:09:06 2009 +0200
@@ -1,6 +1,6 @@
from cubicweb.goa.testlib import *
-class Article(db.Model):
+class Article(db.Model):
content = db.TextProperty()
synopsis = db.StringProperty(default='hello')
@@ -8,10 +8,10 @@
diem = db.DateProperty(required=True, auto_now_add=True)
title = db.StringProperty(required=True)
content = db.TextProperty()
- talks_about = db.ReferenceProperty(Article)
- cites = db.SelfReferenceProperty()
+ talks_about = db.ReferenceProperty(Article)
+ cites = db.SelfReferenceProperty()
-
+
class SomeViewsTC(GAEBasedTC):
MODEL_CLASSES = (Article, Blog)
@@ -77,7 +77,7 @@
'is', 'is_instance_of', 'modification_date', 'owned_by'])
self.assertUnorderedIterableEquals((str(e) for e in eschema.object_relations()),
('identity',))
-
+
def test_yams_ambiguous_relation(self):
rschema = self.schema['ambiguous_relation']
# only relations defined in the class are actually ordered
@@ -103,7 +103,7 @@
self.assertEquals(rschema.objects(), ('Bytes',))
self.assertEquals(rschema.rproperty('Blog', 'Bytes', 'cardinality'), '?1')
-
+
if __name__ == '__main__':
from logilab.common.testlib import unittest_main
unittest_main()
--- a/goa/test/unittest_views.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/test/unittest_views.py Mon May 18 10:09:06 2009 +0200
@@ -25,28 +25,28 @@
return [mydate]
return []
-
+
class SomeViewsTC(GAEBasedTC):
MODEL_CLASSES = (Blog, )
from cubicweb.web.views import basecontrollers, baseviews, navigation, boxes, calendar
from data import views
LOAD_APP_MODULES = (basecontrollers, baseviews, navigation, boxes, calendar, views)
-
+
def setUp(self):
GAEBasedTC.setUp(self)
self.req = self.request()
self.blog = Blog(title=u'a blog', content=u'hop')
self.blog.put(self.req)
-
+
def test_hcal(self):
self.vreg.render('views', 'hcal', self.req, rset=self.blog.rset)
-
+
def test_django_index(self):
self.vreg.render('views', 'index', self.req, rset=None)
for vid in ('primary', 'secondary', 'oneline', 'incontext', 'outofcontext', 'text'):
setattr(SomeViewsTC, 'test_%s'%vid, lambda self, vid=vid: self.blog.view(vid))
-
+
if __name__ == '__main__':
from logilab.common.testlib import unittest_main
unittest_main()
--- a/goa/testlib.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/testlib.py Mon May 18 10:09:06 2009 +0200
@@ -1,3 +1,10 @@
+"""
+:organization: Logilab
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+__docformat__ = "restructuredtext en"
+
from logilab.common.testlib import TestCase
import os, os.path as osp
@@ -18,7 +25,7 @@
import_appengine_failed = None
except ImportError, exc:
# XXX necessary ?
- class db:
+ class db:
class Model:
pass
class DummyProperty:
@@ -31,7 +38,7 @@
ReferenceProperty = DummyProperty
SelfReferenceProperty = DummyProperty
import_appengine_failed = 'cannot import appengine: %s' % exc
-
+
from cubicweb.devtools.fake import FakeRequest
from cubicweb.goa.goavreg import GAERegistry
@@ -56,11 +63,11 @@
def load_schema_hook(self, loader):
loader.import_yams_cube_schema('data')
-
+
@property
def DS_FILE(self):
return self.DS_TEMPL_FILE.replace('-template', '')
-
+
@property
def DS_TEMPL_FILE(self):
return self._DS_TEMPL_FILE + '_'.join(sorted(cls.__name__ for cls in self.MODEL_CLASSES))
@@ -72,7 +79,7 @@
stub = datastore_file_stub.DatastoreFileStub(self.APP_ID, dsfile,
dsfile+'.history')
apiproxy_stub_map.apiproxy.RegisterStub('datastore_v3', stub)
-
+
def setUp(self):
if import_appengine_failed:
self.skip(import_appengine_failed)
@@ -88,7 +95,7 @@
self._set_ds_file(self.DS_TEMPL_FILE)
# from google.appengine.api import mail_stub
# from google3.apphosting.api import urlfetch_stub
-# from google3.apphosting.api import user_service_stub
+# from google3.apphosting.api import user_service_stub
# # Use a fresh stub UserService.
# apiproxy_stub_map.apiproxy.RegisterStub(
# 'user', user_service_stub.UserServiceStub())
@@ -149,15 +156,15 @@
req = FakeRequest(vreg=self.vreg)
self.session = self.session_manager.open_session(req)
self.user = self.session.user()
-
+
def tearDown(self):
self.session.close()
-
+
def request(self):
req = FakeRequest(vreg=self.vreg)
req.set_connection(self.session, self.user)
return req
-
+
def add_entity(self, etype, **kwargs):
cu = self.session.cursor()
rql = 'INSERT %s X' % etype
@@ -174,7 +181,7 @@
def rollback(self):
self.session.rollback()
-
+
def create_user(self, login, groups=('users',), req=None):
assert not self.config['use-google-auth']
user = self.add_entity('CWUser', upassword=str(login), login=unicode(login))
@@ -190,4 +197,3 @@
req.form['__login'] = login
req.form['__password'] = password or login
return self.session_manager.open_session(req)
-
--- a/goa/tools/generate_schema_img.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/tools/generate_schema_img.py Mon May 18 10:09:06 2009 +0200
@@ -1,6 +1,6 @@
import sys
from os.path import dirname, abspath, join
-from yams import schema2dot
+from yams import schema2dot
APPLROOT = abspath(join(dirname(abspath(__file__)), '..'))
@@ -9,7 +9,7 @@
except ImportError:
sys.path.insert(0, APPLROOT)
import custom
-
+
schema = custom.SCHEMA
skip_rels = ('owned_by', 'created_by', 'identity', 'is', 'is_instance_of')
--- a/goa/tools/laxctl.py Thu May 14 18:12:45 2009 +0200
+++ b/goa/tools/laxctl.py Mon May 18 10:09:06 2009 +0200
@@ -23,7 +23,7 @@
def initialize_vregistry(applroot):
# apply monkey patches first
- from cubicweb.goa import do_monkey_patch
+ from cubicweb.goa import do_monkey_patch
do_monkey_patch()
from cubicweb.goa.goavreg import GAERegistry
from cubicweb.goa.goaconfig import GAEConfiguration
@@ -32,21 +32,21 @@
vreg = GAERegistry(config)
vreg.set_schema(config.load_schema())
return vreg
-
+
def alistdir(directory):
return [osp.join(directory, f) for f in os.listdir(directory)]
class LaxCommand(Command):
"""base command class for all lax commands
- creates vreg, schema and calls
+ creates vreg, schema and calls
"""
min_args = max_args = 0
def run(self, args):
self.vreg = initialize_vregistry(APPLROOT)
self._run(args)
-
+
class GenerateSchemaCommand(LaxCommand):
"""generates the schema's png file"""
@@ -54,7 +54,7 @@
def _run(self, args):
assert not args, 'no argument expected'
- from yams import schema2dot
+ from yams import schema2dot
schema = self.vreg.schema
skip_rels = ('owned_by', 'created_by', 'identity', 'is', 'is_instance_of')
path = osp.join(APPLROOT, 'data', 'schema.png')
@@ -107,7 +107,7 @@
class GetSessionIdHandler(urllib2.HTTPRedirectHandler):
def __init__(self, config):
self.config = config
-
+
def http_error_303(self, req, fp, code, msg, headers):
cookie = SimpleCookie(headers['Set-Cookie'])
sessionid = cookie['__session'].value
@@ -115,7 +115,7 @@
setattr(self.config, 'cookie', '__session=' + sessionid)
return 1 # on exception should be raised
-
+
class URLCommand(LaxCommand):
"""abstract class for commands doing stuff by accessing the web application
"""
@@ -138,7 +138,7 @@
'help': 'user password instead of giving raw cookie string (require '
'lax based authentication).'}),
)
-
+
def _run(self, args):
baseurl = args[0]
if not baseurl.startswith('http'):
@@ -154,9 +154,9 @@
urllib2.install_opener(opener)
data = urlencode(dict(__login=self.config.user,
__password=self.config.password))
- self.open_url(urllib2.Request(baseurl, data))
+ self.open_url(urllib2.Request(baseurl, data))
opener = urllib2.build_opener(NoRedirectHandler())
- urllib2.install_opener(opener)
+ urllib2.install_opener(opener)
self.do_base_url(baseurl)
def build_req(self, url):
@@ -164,7 +164,7 @@
if self.config.cookie:
req.headers['Cookie'] = self.config.cookie
return req
-
+
def open_url(self, req):
try:
return urllib2.urlopen(req)
@@ -194,11 +194,11 @@
msg = remove_html_tags(match.group(1))
print msg
return msg
-
+
def do_base_url(self, baseurl):
raise NotImplementedError()
-
+
class DSInitCommand(URLCommand):
"""initialize the datastore"""
name = 'db-init'
@@ -210,7 +210,7 @@
'help': 'number of seconds to wait between each request to avoid '
'going out of quota.'}),
)
-
+
def do_base_url(self, baseurl):
req = self.build_req(baseurl + '?vid=contentinit')
while True:
@@ -240,8 +240,8 @@
req = self.build_req(baseurl + '?vid=cleansessions')
data = self.open_url(req)
self.extract_message(data)
-
-
+
+
register_commands([GenerateSchemaCommand,
PopulateDataDirCommand,
DSInitCommand,
@@ -250,6 +250,6 @@
def run():
main_run(sys.argv[1:])
-
+
if __name__ == '__main__':
run()
--- a/hercule.py Thu May 14 18:12:45 2009 +0200
+++ b/hercule.py Mon May 18 10:09:06 2009 +0200
@@ -13,11 +13,11 @@
from logilab.common.cli import CLIHelper
from logilab.common.clcommands import BadCommandUsage, pop_arg, register_commands
from cubicweb.toolsutils import CONNECT_OPTIONS, Command
-
+
# result formatter ############################################################
PAGER = os.environ.get('PAGER', 'less')
-
+
def pager_format_results(writer, layout):
"""pipe results to a pager like more or less"""
(r, w) = os.pipe()
@@ -42,8 +42,8 @@
def izip2(list1, list2):
for i in xrange(len(list1)):
yield list1[i] + tuple(list2[i])
-
-def format_results(writer, layout, stream=sys.stdout):
+
+def format_results(writer, layout, stream=sys.stdout):
"""format result as text into the given file like object"""
writer.format(layout, stream)
@@ -60,7 +60,7 @@
return str(value)
# command line querier ########################################################
-
+
class RQLCli(CLIHelper):
"""Interactive command line client for CubicWeb, allowing user to execute
arbitrary RQL queries and to fetch schema information
@@ -74,10 +74,10 @@
'description' : "CubicWeb",
'commit' : "CubicWeb",
'rollback' : "CubicWeb",
- 'autocommit' : "Others",
+ 'autocommit' : "Others",
'debug' : "Others",
})
-
+
def __init__(self, application=None, user=None, password=None,
host=None, debug=0):
CLIHelper.__init__(self, os.path.join(os.environ["HOME"], ".erqlhist"))
@@ -94,7 +94,7 @@
if application is not None:
self.do_connect(application, user, password, host)
self.do_debug(debug)
-
+
def do_connect(self, application, user=None, password=None, host=None):
"""connect to an cubicweb application"""
from cubicweb.dbapi import connect
@@ -113,7 +113,7 @@
self._completer.list = (self.commands.keys() +
self.schema.entities() + ['Any'])
print _('You are now connected to %s') % application
-
+
help_do_connect = ('connect', "connect <application> [<user> [<password> [<host>]]]",
_(do_connect.__doc__))
@@ -127,9 +127,9 @@
self._format = pager_format_results
if self._debug:
print _('Debug level set to %s'%debug)
-
+
help_do_debug = ('debug', "debug [debug_level]", _(do_debug.__doc__))
-
+
def do_description(self):
"""display the description of the latest result"""
if self.rset.description is None:
@@ -139,7 +139,7 @@
for line_desc in self.rset.description])
help_do_description = ('description', "description", _(do_description.__doc__))
-
+
def do_schema(self, name=None):
"""display information about the application schema """
if self.cnx is None:
@@ -159,28 +159,28 @@
done = 1
if done is None:
print _('Unable to find anything named "%s" in the schema !') % name
-
+
help_do_schema = ('schema', "schema [keyword]", _(do_schema.__doc__))
-
+
def do_commit(self):
"""commit the current transaction"""
self.cnx.commit()
help_do_commit = ('commit', "commit", _(do_commit.__doc__))
-
+
def do_rollback(self):
"""rollback the current transaction"""
self.cnx.rollback()
help_do_rollback = ('rollback', "rollback", _(do_rollback.__doc__))
-
+
def do_autocommit(self):
"""toggle autocommit mode"""
self.autocommit = not self.autocommit
help_do_autocommit = ('autocommit', "autocommit", _(do_autocommit.__doc__))
-
+
def handle_line(self, stripped_line):
"""handle non command line :
@@ -232,7 +232,7 @@
"""A command line querier for CubicWeb, using the Relation Query Language.
<application>
- identifier of the application to connect to
+ identifier of the application to connect to
"""
name = 'client'
arguments = '<application>'
@@ -247,7 +247,7 @@
'help': 'file containing a batch of RQL statements to execute.',
}),
)
-
+
def run(self, args):
"""run the command with its specific arguments"""
appid = pop_arg(args, expected_size_after=None)
@@ -271,5 +271,5 @@
cli.handle_line(line)
else:
cli.run()
-
+
register_commands((CubicWebClientCommand,))
--- a/i18n/en.po Thu May 14 18:12:45 2009 +0200
+++ b/i18n/en.po Mon May 18 10:09:06 2009 +0200
@@ -118,10 +118,6 @@
msgid "%s software version of the database"
msgstr ""
-#, python-format
-msgid "%s_perm"
-msgstr ""
-
msgid "**"
msgstr "0..n 0..n"
@@ -200,30 +196,11 @@
msgid "Bytes_plural"
msgstr "Bytes"
-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 "CWAttribute"
+msgstr "Attribute"
+
+msgid "CWAttribute_plural"
+msgstr "Attributes"
msgid "CWCache"
msgstr ""
@@ -249,24 +226,12 @@
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"
@@ -285,13 +250,41 @@
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 "Email body: "
+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 "EmailAddress"
@@ -312,7 +305,7 @@
msgid "Float_plural"
msgstr "Floats"
-msgid "From: "
+msgid "From:"
msgstr ""
msgid "Int"
@@ -330,6 +323,9 @@
msgid "New Bookmark"
msgstr "New bookmark"
+msgid "New CWAttribute"
+msgstr "New attribute"
+
msgid "New CWCache"
msgstr ""
@@ -342,15 +338,9 @@
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"
@@ -360,6 +350,9 @@
msgid "New CWRType"
msgstr "New relation type"
+msgid "New CWRelation"
+msgstr "New relation"
+
msgid "New CWUser"
msgstr "New user"
@@ -396,16 +389,13 @@
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"
@@ -439,7 +429,7 @@
msgid "String_plural"
msgstr "Strings"
-msgid "Subject: "
+msgid "Subject:"
msgstr ""
msgid "Submit bug report"
@@ -466,6 +456,9 @@
msgid "This Bookmark"
msgstr "This bookmark"
+msgid "This CWAttribute"
+msgstr "This attribute"
+
msgid "This CWCache"
msgstr ""
@@ -478,15 +471,9 @@
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"
@@ -496,6 +483,9 @@
msgid "This CWRType"
msgstr "This relation type"
+msgid "This CWRelation"
+msgstr "This relation"
+
msgid "This CWUser"
msgstr "This user"
@@ -669,6 +659,12 @@
msgid "actions_manage_description"
msgstr ""
+msgid "actions_managepermission"
+msgstr ""
+
+msgid "actions_managepermission_description"
+msgstr ""
+
msgid "actions_muledit"
msgstr "modify all"
@@ -741,6 +737,12 @@
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"
@@ -753,18 +755,6 @@
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"
@@ -777,6 +767,12 @@
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"
@@ -807,6 +803,9 @@
msgid "add a Bookmark"
msgstr "add a bookmark"
+msgid "add a CWAttribute"
+msgstr "add an attribute"
+
msgid "add a CWCache"
msgstr ""
@@ -819,15 +818,9 @@
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"
@@ -837,6 +830,9 @@
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"
@@ -1118,9 +1114,6 @@
msgid "click on the box to cancel the deletion"
msgstr ""
-msgid "close all"
-msgstr ""
-
msgid "comment"
msgstr ""
@@ -1190,12 +1183,6 @@
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 ""
@@ -1335,28 +1322,31 @@
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 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 CWProperty (CWProperty for_user CWUser %(linkto)s)"
-msgstr "creating property for user %(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 ""
@@ -1371,7 +1361,8 @@
"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 ""
@@ -1540,6 +1531,9 @@
msgid "destination_state_object"
msgstr "destination of"
+msgid "detach attached file"
+msgstr ""
+
#, python-format
msgid "detach attached file %s"
msgstr ""
@@ -1618,9 +1612,18 @@
msgid "entities deleted"
msgstr ""
+msgid "entity copied"
+msgstr ""
+
+msgid "entity created"
+msgstr ""
+
msgid "entity deleted"
msgstr ""
+msgid "entity edited"
+msgstr ""
+
msgid "entity type"
msgstr ""
@@ -1727,6 +1730,10 @@
msgid "from"
msgstr ""
+#, python-format
+msgid "from %(date)s"
+msgstr ""
+
msgid "from_entity"
msgstr "from entity"
@@ -1751,6 +1758,9 @@
msgid "generic plot"
msgstr ""
+msgid "generic relation to link one entity to another"
+msgstr ""
+
msgid "go back to the index page"
msgstr ""
@@ -2004,6 +2014,11 @@
msgstr ""
msgid ""
+"link a permission to the entity. This permission should be used in the "
+"security definition of the entity's type to be useful."
+msgstr ""
+
+msgid ""
"link a property to the user which want this property customization. Unless "
"you're a site manager, this relation will be handled automatically."
msgstr ""
@@ -2026,11 +2041,6 @@
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 ""
@@ -2046,6 +2056,9 @@
msgid "login"
msgstr ""
+msgid "login or email"
+msgstr ""
+
msgid "login_action"
msgstr "log in"
@@ -2173,7 +2186,7 @@
msgid "no"
msgstr ""
-msgid "no associated epermissions"
+msgid "no associated permissions"
msgstr ""
msgid "no possible transition"
@@ -2362,6 +2375,9 @@
msgid "remove this Bookmark"
msgstr "remove this bookmark"
+msgid "remove this CWAttribute"
+msgstr "remove this attribute"
+
msgid "remove this CWCache"
msgstr ""
@@ -2374,15 +2390,9 @@
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"
@@ -2392,6 +2402,9 @@
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"
@@ -2416,6 +2429,12 @@
msgid "require_group_object"
msgstr "required by"
+msgid "require_permission"
+msgstr ""
+
+msgid "require_permission_object"
+msgstr ""
+
msgid "required attribute"
msgstr ""
@@ -2483,12 +2502,18 @@
msgid "see them all"
msgstr ""
+msgid "see_also"
+msgstr ""
+
msgid "select"
msgstr ""
msgid "select a"
msgstr ""
+msgid "select a key first"
+msgstr ""
+
msgid "select a relation"
msgstr ""
@@ -2547,6 +2572,9 @@
msgid "show meta-data"
msgstr "show the complete schema"
+msgid "sioc"
+msgstr ""
+
msgid "site configuration"
msgstr ""
@@ -2672,6 +2700,10 @@
msgid "to"
msgstr ""
+#, python-format
+msgid "to %(date)s"
+msgstr ""
+
msgid "to associate with"
msgstr ""
@@ -2690,6 +2722,9 @@
msgid "todo_by"
msgstr "to do by"
+msgid "toggle check boxes"
+msgstr ""
+
msgid "transition is not allowed"
msgstr ""
@@ -2904,6 +2939,9 @@
msgid "you have been logged out"
msgstr ""
+msgid "you should probably delete that property"
+msgstr ""
+
#~ msgid "Card"
#~ msgstr "Card"
--- a/i18n/es.po Thu May 14 18:12:45 2009 +0200
+++ b/i18n/es.po Mon May 18 10:09:06 2009 +0200
@@ -123,10 +123,6 @@
msgid "%s software version of the database"
msgstr "versión sistema de la base para %s"
-#, python-format
-msgid "%s_perm"
-msgstr ""
-
msgid "**"
msgstr "0..n 0..n"
@@ -205,30 +201,11 @@
msgid "Bytes_plural"
msgstr "Bytes"
-msgid "Date"
-msgstr "Fecha"
-
-msgid "Date_plural"
-msgstr "Fechas"
-
-msgid "Datetime"
-msgstr "Fecha y hora"
-
-msgid "Datetime_plural"
-msgstr "Fechas y horas"
-
-#, python-format
-msgid "Debug level set to %s"
-msgstr "Nivel de debug puesto a %s"
-
-msgid "Decimal"
-msgstr "Decimal"
-
-msgid "Decimal_plural"
-msgstr "Decimales"
-
-msgid "Do you want to delete the following element(s) ?"
-msgstr "Desea suprimir el(los) elemento(s) siguiente(s)"
+msgid "CWAttribute"
+msgstr "Atributo"
+
+msgid "CWAttribute_plural"
+msgstr "Atributos"
msgid "CWCache"
msgstr "Cache"
@@ -254,24 +231,12 @@
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"
@@ -290,14 +255,42 @@
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"
-msgid "Email body: "
-msgstr "Contenido del correo electrónico : "
+msgid "Date"
+msgstr "Fecha"
+
+msgid "Date_plural"
+msgstr "Fechas"
+
+msgid "Datetime"
+msgstr "Fecha y hora"
+
+msgid "Datetime_plural"
+msgstr "Fechas y horas"
+
+#, python-format
+msgid "Debug level set to %s"
+msgstr "Nivel de debug puesto a %s"
+
+msgid "Decimal"
+msgstr "Decimal"
+
+msgid "Decimal_plural"
+msgstr "Decimales"
+
+msgid "Do you want to delete the following element(s) ?"
+msgstr "Desea suprimir el(los) elemento(s) siguiente(s)"
msgid "EmailAddress"
msgstr "Correo Electrónico"
@@ -317,8 +310,8 @@
msgid "Float_plural"
msgstr "Números flotantes"
-msgid "From: "
-msgstr "De : "
+msgid "From:"
+msgstr ""
msgid "Int"
msgstr "Número entero"
@@ -335,6 +328,9 @@
msgid "New Bookmark"
msgstr "Agregar a Favoritos"
+msgid "New CWAttribute"
+msgstr "Nueva definición de relación final"
+
msgid "New CWCache"
msgstr "Agregar Cache"
@@ -347,15 +343,9 @@
msgid "New CWEType"
msgstr "Agregar tipo de entidad"
-msgid "New CWAttribute"
-msgstr "Nueva definición de relación final"
-
msgid "New CWGroup"
msgstr "Nuevo grupo"
-msgid "New CWRelation"
-msgstr "Nueva definición de relación final"
-
msgid "New CWPermission"
msgstr "Agregar autorización"
@@ -365,6 +355,9 @@
msgid "New CWRType"
msgstr "Agregar tipo de relación"
+msgid "New CWRelation"
+msgstr "Nueva definición de relación final"
+
msgid "New CWUser"
msgstr "Agregar usuario"
@@ -401,17 +394,14 @@
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 "Destinatarios : "
+msgid "Recipients:"
+msgstr ""
msgid "Relations"
msgstr "Relaciones"
@@ -444,8 +434,8 @@
msgid "String_plural"
msgstr "Cadenas de caracteres"
-msgid "Subject: "
-msgstr "Objeto : "
+msgid "Subject:"
+msgstr ""
msgid "Submit bug report"
msgstr "Enviar un reporte de error (bug)"
@@ -471,6 +461,9 @@
msgid "This Bookmark"
msgstr "Este favorito"
+msgid "This CWAttribute"
+msgstr "Esta definición de relación final"
+
msgid "This CWCache"
msgstr "Este Cache"
@@ -483,15 +476,9 @@
msgid "This CWEType"
msgstr "Este tipo de Entidad"
-msgid "This CWAttribute"
-msgstr "Esta definición de relación final"
-
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"
@@ -501,6 +488,9 @@
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"
@@ -692,6 +682,12 @@
msgid "actions_manage_description"
msgstr ""
+msgid "actions_managepermission"
+msgstr ""
+
+msgid "actions_managepermission_description"
+msgstr ""
+
msgid "actions_muledit"
msgstr "Edición múltiple"
@@ -764,6 +760,12 @@
msgid "add Bookmark bookmarked_by CWUser object"
msgstr "Agregar a los favoritos "
+msgid "add CWAttribute constrained_by CWConstraint subject"
+msgstr "Restricción"
+
+msgid "add CWAttribute relation_type CWRType object"
+msgstr "Definición de atributo"
+
msgid "add CWEType add_permission RQLExpression subject"
msgstr "Agregar una autorización"
@@ -776,18 +778,6 @@
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 "Agregar Propiedad"
@@ -800,6 +790,12 @@
msgid "add CWRType read_permission RQLExpression subject"
msgstr "Agregar expresión RQL de lectura"
+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 CWUser in_group CWGroup object"
msgstr "Agregar usuario"
@@ -830,6 +826,9 @@
msgid "add a Bookmark"
msgstr "Agregar un Favorito"
+msgid "add a CWAttribute"
+msgstr "Agregar un tipo de relación"
+
msgid "add a CWCache"
msgstr "Agregar un cache"
@@ -842,15 +841,9 @@
msgid "add a CWEType"
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 CWRelation"
-msgstr "Agregar una relación"
-
msgid "add a CWPermission"
msgstr "Agregar una autorización"
@@ -860,6 +853,9 @@
msgid "add a CWRType"
msgstr "Agregar un tipo de relación"
+msgid "add a CWRelation"
+msgstr "Agregar una relación"
+
msgid "add a CWUser"
msgstr "Agregar un usuario"
@@ -1148,9 +1144,6 @@
msgid "click on the box to cancel the deletion"
msgstr "Seleccione la zona de edición para cancelar la eliminación"
-msgid "close all"
-msgstr ""
-
msgid "comment"
msgstr "Comentario"
@@ -1223,12 +1216,6 @@
msgid "components_rqlinput_description"
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"
@@ -1384,28 +1371,31 @@
msgid "creating Bookmark (Bookmark bookmarked_by CWUser %(linkto)s)"
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 del 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"
+
+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 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 CWUser (CWUser in_group CWGroup %(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)"
+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"
@@ -1422,7 +1412,8 @@
"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)"
+msgid ""
+"creating RQLExpression (CWRType %(linkto)s add_permission RQLExpression)"
msgstr ""
"Creación de una expresión RQL para la autorización de agregar relaciones %"
"(linkto)s"
@@ -1610,6 +1601,9 @@
msgid "destination_state_object"
msgstr "Destino de"
+msgid "detach attached file"
+msgstr "soltar el archivo existente"
+
#, python-format
msgid "detach attached file %s"
msgstr "Quitar archivo adjunto %s"
@@ -1690,9 +1684,18 @@
msgid "entities deleted"
msgstr "Entidades eliminadas"
+msgid "entity copied"
+msgstr ""
+
+msgid "entity created"
+msgstr ""
+
msgid "entity deleted"
msgstr "Entidad eliminada"
+msgid "entity edited"
+msgstr ""
+
msgid "entity type"
msgstr "Tipo de entidad"
@@ -1804,6 +1807,10 @@
msgid "from"
msgstr "De"
+#, python-format
+msgid "from %(date)s"
+msgstr ""
+
msgid "from_entity"
msgstr "De la entidad"
@@ -1828,6 +1835,9 @@
msgid "generic plot"
msgstr "Trazado de curbas estándares"
+msgid "generic relation to link one entity to another"
+msgstr ""
+
msgid "go back to the index page"
msgstr "Regresar a la página de inicio"
@@ -2094,6 +2104,11 @@
msgstr "izquierda"
msgid ""
+"link a permission to the entity. This permission should be used in the "
+"security definition of the entity's type to be useful."
+msgstr ""
+
+msgid ""
"link a property to the user which want this property customization. Unless "
"you're a site manager, this relation will be handled automatically."
msgstr ""
@@ -2119,12 +2134,6 @@
msgid "link a transition to one or more entity type"
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 "ligar hacia cada elemento en"
@@ -2140,6 +2149,9 @@
msgid "login"
msgstr "Clave de acesso"
+msgid "login or email"
+msgstr ""
+
msgid "login_action"
msgstr "Ingresa tus datos"
@@ -2269,8 +2281,8 @@
msgid "no"
msgstr "no"
-msgid "no associated epermissions"
-msgstr "permisos no asociados"
+msgid "no associated permissions"
+msgstr ""
msgid "no possible transition"
msgstr "transición no posible"
@@ -2457,6 +2469,9 @@
msgid "remove this Bookmark"
msgstr "Eliminar este Favorito"
+msgid "remove this CWAttribute"
+msgstr "Eliminar este atributo"
+
msgid "remove this CWCache"
msgstr "Eliminar esta cache de aplicación"
@@ -2469,15 +2484,9 @@
msgid "remove this CWEType"
msgstr "Eliminar este tipo de entidad"
-msgid "remove this CWAttribute"
-msgstr "Eliminar este atributo"
-
msgid "remove this CWGroup"
msgstr "Eliminar este grupo"
-msgid "remove this CWRelation"
-msgstr "Eliminar esta relación"
-
msgid "remove this CWPermission"
msgstr "Eliminar este permiso"
@@ -2487,6 +2496,9 @@
msgid "remove this CWRType"
msgstr "Eliminar esta definición de relación"
+msgid "remove this CWRelation"
+msgstr "Eliminar esta relación"
+
msgid "remove this CWUser"
msgstr "Eliminar este usuario"
@@ -2511,6 +2523,12 @@
msgid "require_group_object"
msgstr "Objeto_grupo_requerido"
+msgid "require_permission"
+msgstr ""
+
+msgid "require_permission_object"
+msgstr ""
+
msgid "required attribute"
msgstr "Atributo requerido"
@@ -2582,12 +2600,18 @@
msgid "see them all"
msgstr "Ver todos"
+msgid "see_also"
+msgstr ""
+
msgid "select"
msgstr "Seleccionar"
msgid "select a"
msgstr "seleccione un"
+msgid "select a key first"
+msgstr ""
+
msgid "select a relation"
msgstr "seleccione una relación"
@@ -2649,6 +2673,9 @@
msgid "show meta-data"
msgstr "mostrar meta-data"
+msgid "sioc"
+msgstr ""
+
msgid "site configuration"
msgstr "configuracion del sitio"
@@ -2775,6 +2802,10 @@
msgid "to"
msgstr "a"
+#, python-format
+msgid "to %(date)s"
+msgstr ""
+
msgid "to associate with"
msgstr "a asociar con"
@@ -2793,6 +2824,9 @@
msgid "todo_by"
msgstr "a hacer por"
+msgid "toggle check boxes"
+msgstr ""
+
msgid "transition is not allowed"
msgstr "transition no permitida"
@@ -3020,6 +3054,9 @@
msgid "you have been logged out"
msgstr "ha terminado la sesion"
+msgid "you should probably delete that property"
+msgstr ""
+
#~ msgid "%s constraint failed"
#~ msgstr "La contrainte %s n'est pas satisfaite"
@@ -3035,15 +3072,30 @@
#~ 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 "Agregar Ficha"
+#~ msgid "Problem occured"
+#~ msgstr "Ha ocurrido un error"
+
#~ 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"
@@ -3069,6 +3121,12 @@
#~ msgid "cancel edition"
#~ msgstr "annuler l'Èdition"
+#~ msgid "components_rss_feed_url"
+#~ msgstr "RSS FEED URL"
+
+#~ msgid "components_rss_feed_url_description"
+#~ msgstr "El espacio para administrar RSS"
+
#~ msgid "content"
#~ msgstr "Contenido"
@@ -3082,9 +3140,6 @@
#~ "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"
@@ -3103,6 +3158,12 @@
#~ msgid "inlined view"
#~ msgstr "Vista incluída (en línea)"
+#~ 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 "linked"
#~ msgstr "liÈ"
@@ -3114,6 +3175,9 @@
#~ msgstr ""
#~ "nombre maximum d'entitÈs liÈes ‡ afficher dans la vue de restriction"
+#~ msgid "no associated epermissions"
+#~ msgstr "permisos no asociados"
+
#~ msgid "owned by"
#~ msgstr "appartient ‡"
--- a/i18n/fr.po Thu May 14 18:12:45 2009 +0200
+++ b/i18n/fr.po Mon May 18 10:09:06 2009 +0200
@@ -123,10 +123,6 @@
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"
@@ -205,30 +201,11 @@
msgid "Bytes_plural"
msgstr "Données binaires"
-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 "CWAttribute"
+msgstr "Attribut"
+
+msgid "CWAttribute_plural"
+msgstr "Attributs"
msgid "CWCache"
msgstr "Cache applicatif"
@@ -254,24 +231,12 @@
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"
@@ -290,14 +255,42 @@
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 "Email body: "
-msgstr "Contenu du courriel : "
+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 "EmailAddress"
msgstr "Adresse électronique"
@@ -317,8 +310,8 @@
msgid "Float_plural"
msgstr "Nombres flottants"
-msgid "From: "
-msgstr "De : "
+msgid "From:"
+msgstr "De :"
msgid "Int"
msgstr "Nombre entier"
@@ -335,6 +328,9 @@
msgid "New Bookmark"
msgstr "Nouveau signet"
+msgid "New CWAttribute"
+msgstr "Nouvelle définition de relation finale"
+
msgid "New CWCache"
msgstr "Nouveau cache applicatif"
@@ -347,15 +343,9 @@
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"
@@ -365,6 +355,9 @@
msgid "New CWRType"
msgstr "Nouveau type de relation"
+msgid "New CWRelation"
+msgstr "Nouvelle définition de relation non finale"
+
msgid "New CWUser"
msgstr "Nouvel utilisateur"
@@ -401,17 +394,14 @@
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"
@@ -444,8 +434,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"
@@ -471,6 +461,9 @@
msgid "This Bookmark"
msgstr "Ce signet"
+msgid "This CWAttribute"
+msgstr "Cette définition de relation finale"
+
msgid "This CWCache"
msgstr "Ce cache applicatif"
@@ -483,15 +476,9 @@
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"
@@ -501,6 +488,9 @@
msgid "This CWRType"
msgstr "Ce type de relation"
+msgid "This CWRelation"
+msgstr "Cette définition de relation non finale"
+
msgid "This CWUser"
msgstr "Cet utilisateur"
@@ -690,6 +680,12 @@
msgid "actions_manage_description"
msgstr ""
+msgid "actions_managepermission"
+msgstr ""
+
+msgid "actions_managepermission_description"
+msgstr ""
+
msgid "actions_muledit"
msgstr "édition multiple"
@@ -762,6 +758,12 @@
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"
@@ -774,18 +776,6 @@
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é"
@@ -798,6 +788,12 @@
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"
@@ -828,6 +824,9 @@
msgid "add a Bookmark"
msgstr "ajouter un signet"
+msgid "add a CWAttribute"
+msgstr "ajouter un type de relation"
+
msgid "add a CWCache"
msgstr "ajouter un cache applicatif"
@@ -840,15 +839,9 @@
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"
@@ -858,6 +851,9 @@
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"
@@ -1146,9 +1142,6 @@
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"
@@ -1221,12 +1214,6 @@
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"
@@ -1383,28 +1370,31 @@
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 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 CWProperty (CWProperty for_user CWUser %(linkto)s)"
-msgstr "création d'une propriété pour l'utilisateur %(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 ""
@@ -1421,7 +1411,8 @@
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"
@@ -1608,6 +1599,9 @@
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"
@@ -1647,7 +1641,7 @@
msgstr "icône de téléchargement"
msgid "download schema as owl"
-msgstr ""
+msgstr "télécharger le schéma OWL"
msgid "edit bookmarks"
msgstr "éditer les signets"
@@ -1688,9 +1682,18 @@
msgid "entities deleted"
msgstr "entités supprimées"
+msgid "entity copied"
+msgstr "entité copiée"
+
+msgid "entity created"
+msgstr "entité créée"
+
msgid "entity deleted"
msgstr "entité supprimée"
+msgid "entity edited"
+msgstr "entité éditée"
+
msgid "entity type"
msgstr "type d'entité"
@@ -1801,6 +1804,10 @@
msgid "from"
msgstr "de"
+#, python-format
+msgid "from %(date)s"
+msgstr "du %(date)s"
+
msgid "from_entity"
msgstr "de l'entité"
@@ -1825,6 +1832,9 @@
msgid "generic plot"
msgstr "tracé de courbes standard"
+msgid "generic relation to link one entity to another"
+msgstr "relation générique pour lier une entité à une autre"
+
msgid "go back to the index page"
msgstr "retourner sur la page d'accueil"
@@ -2093,6 +2103,13 @@
msgstr "gauche"
msgid ""
+"link a permission to the entity. This permission should be used in the "
+"security definition of the entity's type to be useful."
+msgstr ""
+"lie une permission à une entité. Cette permission doit généralement être utilisée "
+"dans la définition de sécurité du type d'entité pour être utile."
+
+msgid ""
"link a property to the user which want this property customization. Unless "
"you're a site manager, this relation will be handled automatically."
msgstr ""
@@ -2118,11 +2135,6 @@
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"
@@ -2138,6 +2150,9 @@
msgid "login"
msgstr "identifiant"
+msgid "login or email"
+msgstr "identifiant ou email"
+
msgid "login_action"
msgstr "identifiez vous"
@@ -2267,8 +2282,8 @@
msgid "no"
msgstr "non"
-msgid "no associated epermissions"
-msgstr "aucune permission spécifique n'est définie"
+msgid "no associated permissions"
+msgstr "aucune permission associée"
msgid "no possible transition"
msgstr "aucune transition possible"
@@ -2335,10 +2350,10 @@
msgstr "ordre"
msgid "owl"
-msgstr ""
+msgstr "owl"
msgid "owlabox"
-msgstr ""
+msgstr "owl ABox"
msgid "owned_by"
msgstr "appartient à"
@@ -2446,7 +2461,7 @@
msgstr "définition"
msgid "relations"
-msgstr ""
+msgstr "relations"
msgid "relations deleted"
msgstr "relations supprimées"
@@ -2457,6 +2472,9 @@
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"
@@ -2469,15 +2487,9 @@
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"
@@ -2487,6 +2499,9 @@
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"
@@ -2511,6 +2526,12 @@
msgid "require_group_object"
msgstr "à les droits"
+msgid "require_permission"
+msgstr "require permission"
+
+msgid "require_permission_object"
+msgstr "permission of"
+
msgid "required attribute"
msgstr "attribut requis"
@@ -2587,12 +2608,18 @@
msgid "see them all"
msgstr "les voir toutes"
+msgid "see_also"
+msgstr "see also"
+
msgid "select"
msgstr "sélectionner"
msgid "select a"
msgstr "sélectionner un"
+msgid "select a key first"
+msgstr "sélectionnez d'abord une clé"
+
msgid "select a relation"
msgstr "sélectionner une relation"
@@ -2654,6 +2681,9 @@
msgid "show meta-data"
msgstr "afficher le schéma complet"
+msgid "sioc"
+msgstr "sioc"
+
msgid "site configuration"
msgstr "configuration du site"
@@ -2780,6 +2810,10 @@
msgid "to"
msgstr "à"
+#, python-format
+msgid "to %(date)s"
+msgstr "au %(date)s"
+
msgid "to associate with"
msgstr "pour associer à"
@@ -2798,6 +2832,9 @@
msgid "todo_by"
msgstr "à faire par"
+msgid "toggle check boxes"
+msgstr "inverser les cases à cocher"
+
msgid "transition is not allowed"
msgstr "transition non permise"
@@ -2865,7 +2902,7 @@
msgstr "clé de propriété inconnue"
msgid "up"
-msgstr ""
+msgstr "haut"
msgid "upassword"
msgstr "mot de passe"
@@ -3023,6 +3060,9 @@
msgid "you have been logged out"
msgstr "vous avez été déconnecté"
+msgid "you should probably delete that property"
+msgstr "vous devriez probablement supprimer cette propriété"
+
#~ msgid "%s constraint failed"
#~ msgstr "La contrainte %s n'est pas satisfaite"
@@ -3038,15 +3078,30 @@
#~ 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"
+#~ msgid "Recipients: "
+#~ msgstr "Destinataires : "
+
+#~ msgid "Subject: "
+#~ msgstr "Sujet : "
+
#~ msgid "This Card"
#~ msgstr "Cette fiche"
@@ -3075,6 +3130,12 @@
#~ msgid "cancel edition"
#~ msgstr "annuler l'édition"
+#~ msgid "close all"
+#~ msgstr "tout fermer"
+
+#~ msgid "components_rss_feed_url"
+#~ msgstr "syndication rss"
+
#~ msgid "content"
#~ msgstr "contenu"
@@ -3088,9 +3149,6 @@
#~ "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"
@@ -3120,6 +3178,9 @@
#~ msgstr ""
#~ "nombre maximum d'entités liées à afficher dans la vue de restriction"
+#~ msgid "no associated epermissions"
+#~ msgstr "aucune permission spécifique n'est définie"
+
#~ msgid "owned by"
#~ msgstr "appartient à"
--- a/interfaces.py Thu May 14 18:12:45 2009 +0200
+++ b/interfaces.py Mon May 18 10:09:06 2009 +0200
@@ -267,6 +267,3 @@
def isioc_items(self):
"""return contained items"""
-
-
-
--- a/misc/cwdesklets/rqlsensor/__init__.py Thu May 14 18:12:45 2009 +0200
+++ b/misc/cwdesklets/rqlsensor/__init__.py Mon May 18 10:09:06 2009 +0200
@@ -52,7 +52,7 @@
output.set('resultbg[%s]' % index, 'black')
webbrowser.open(self._urls[index])
self._send_output(output)
-
+
def __get_connection(self):
try:
return self._v_cnx
@@ -73,8 +73,8 @@
del self._v_cnx
raise
self._urls = []
- output.set('layout', 'vertical, 14')
- output.set('length', rset.rowcount)
+ output.set('layout', 'vertical, 14')
+ output.set('length', rset.rowcount)
i = 0
for line in rset:
output.set('result[%s]' % i, ', '.join([str(v) for v in line[1:]]))
@@ -84,7 +84,7 @@
except:
self._urls.append('')
i += 1
-
+
def __update(self):
output = self._new_output()
try:
@@ -92,12 +92,12 @@
except Exception, ex:
import traceback
traceback.print_exc()
- output.set('layout', 'vertical, 10')
- output.set('length', 1)
+ output.set('layout', 'vertical, 10')
+ output.set('length', 1)
output.set('result[0]', str(ex))
self._send_output(output)
self._add_timer(int(self._get_config('delay'))*1000, self.__update)
-
+
def new_sensor(args):
return RQLSensor(*args)
--- a/misc/cwfs/cwfs.py Thu May 14 18:12:45 2009 +0200
+++ b/misc/cwfs/cwfs.py Mon May 18 10:09:06 2009 +0200
@@ -24,7 +24,7 @@
] ),
})
-
+
DATA = { 'societe': [ ('CETIAD', 'Dijon'),
('EDF_R&D', 'Clamart'),
@@ -58,7 +58,7 @@
self._attr = None
self._rel = None
self._restrictions = []
-
+
def parse(self) :
self._entity = self._components.next()
try:
@@ -97,7 +97,7 @@
for nom, entity in self.schema.get_relations(self._entity) :
yield nom+'/'
yield entity+'/'
-
+
def ls(path) :
p = PathParser(SCHEMA,path)
p.parse()
@@ -113,7 +113,7 @@
self._e_type = None
self._restrictions = []
self._alphabet = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
-
+
def parse(self):
self._var = self._alphabet.pop(0)
self._e_type = self._components.next()
@@ -124,7 +124,7 @@
except StopIteration :
pass
return 'Any %s WHERE %s' % (self._var, ', '.join(self._restrictions))
-
+
def process_entity(self) :
_next = self._components.next()
if _next in self.schema.get_attrs(self._e_type) :
@@ -147,9 +147,9 @@
self._restrictions.append('%s is %s' % (r_var, _next.capitalize()))
except StopIteration:
raise
- self.process_entity()
+ self.process_entity()
-
+
def to_rql(path) :
p = SytPathParser(SCHEMA,path)
return p.parse()
--- a/misc/migration/2.42.1_Any.py Thu May 14 18:12:45 2009 +0200
+++ b/misc/migration/2.42.1_Any.py Mon May 18 10:09:06 2009 +0200
@@ -15,4 +15,4 @@
if 'inline_view' in schema:
# inline_view attribute should have been deleted for a while now....
drop_attribute('CWRelation', 'inline_view')
-
+
--- a/rset.py Thu May 14 18:12:45 2009 +0200
+++ b/rset.py Mon May 18 10:09:06 2009 +0200
@@ -11,7 +11,7 @@
from rql import nodes
from cubicweb import NotAnEntity
-
+
class ResultSet(object):
"""a result set wrap a RQL query result. This object implements a partial
@@ -53,12 +53,12 @@
self.req = None
# actions cache
self._rsetactions = None
-
+
def __str__(self):
if not self.rows:
return '<empty resultset %s>' % self.rql
return '<resultset %s (%s rows)>' % (self.rql, len(self.rows))
-
+
def __repr__(self):
if not self.rows:
return '<empty resultset for %r>' % self.rql
@@ -85,22 +85,22 @@
actions = self.vreg.possible_vobjects('actions', self.req, self, **kwargs)
self._rsetactions[key] = actions
return actions
-
+
def __len__(self):
"""returns the result set's size"""
return self.rowcount
def __nonzero__(self):
return self.rowcount
-
+
def __getitem__(self, i):
"""returns the ith element of the result set"""
return self.rows[i] #ResultSetRow(self.rows[i])
-
+
def __getslice__(self, i, j):
"""returns slice [i:j] of the result set"""
return self.rows[i:j]
-
+
def __iter__(self):
"""Returns an iterator over rows"""
return iter(self.rows)
@@ -126,7 +126,7 @@
:param transformcb:
a callable which should take a row and its type description as
parameters, and return the transformed row and type description.
-
+
:type col: int
:param col: the column index
@@ -199,7 +199,7 @@
def split_rset(self, keyfunc=None, col=0, return_dict=False):
"""Splits the result set in multiple result set according to a given key
-
+
:type keyfunc: callable(entity or FinalType)
:param keyfunc:
a callable which should take a value of the rset in argument and
@@ -256,7 +256,7 @@
:type offset: int
:param offset: the offset index
-
+
:type inplace: bool
:param inplace:
if true, the result set is modified in place, else a new result set
@@ -289,7 +289,7 @@
copy_cache(rset, 'get_entity', self)
rset.limited = (limit, offset)
return rset
-
+
def printable_rql(self, encoded=False):
"""return the result set's origin rql as a string, with arguments
substitued
@@ -301,11 +301,11 @@
if isinstance(rqlstr, unicode):
return rqlstr
return unicode(rqlstr, encoding)
- else:
+ else:
if isinstance(rqlstr, unicode):
return rqlstr.encode(encoding)
return rqlstr
-
+
# client helper methods ###################################################
def entities(self, col=0):
@@ -320,7 +320,7 @@
def get_entity(self, row, col=None):
"""special method for query retreiving a single entity, returns a
partially initialized Entity instance.
-
+
WARNING: due to the cache wrapping this function, you should NEVER
give row as a named parameter (i.e. rset.get_entity(req, 0)
is OK but rset.get_entity(row=0, req=req) isn't
@@ -351,7 +351,7 @@
partially means that only attributes selected in the RQL
query will be directly assigned to the entity.
-
+
:type row,col: int, int
:param row,col:
row and col numbers localizing the entity among the result's table
@@ -427,7 +427,7 @@
@cached
def syntax_tree(self):
- """get the syntax tree for the source query.
+ """get the syntax tree for the source query.
:rtype: rql.stmts.Statement
:return: the RQL syntax tree of the originating query
@@ -441,12 +441,12 @@
else:
rqlst = self.vreg.parse(self.req, self.rql, self.args)
return rqlst
-
+
@cached
def column_types(self, col):
"""return the list of different types in the column with the given col
index default to 0 (ie the first column)
-
+
:type col: int
:param col: the index of the desired column
@@ -483,7 +483,7 @@
etype = self.description[row][col]
if self.vreg.schema.eschema(etype).is_final():
# final type, find a better one to locate the correct subquery
- # (ambiguous if possible)
+ # (ambiguous if possible)
for i in xrange(len(rqlst.children[0].selection)):
if i == col:
continue
@@ -522,7 +522,7 @@
__, rhs = rel.get_variable_parts()
return rhs.eval(self.args)
return None
-
+
def attr_desc_iterator(rqlst, index=0):
"""return an iterator on a list of 2-uple (index, attr_relation)
--- a/schemas/Bookmark.py Thu May 14 18:12:45 2009 +0200
+++ b/schemas/Bookmark.py Mon May 18 10:09:06 2009 +0200
@@ -4,10 +4,10 @@
title = String(required=True, maxsize=128)
path = String(maxsize=512, required=True,
description=_("relative url of the bookmarked page"))
-
+
bookmarked_by = SubjectRelation('CWUser',
description=_("users using this bookmark"))
-
+
class bookmarked_by(MetaUserRelationType):
permissions = {'read': ('managers', 'users', 'guests',),
--- a/schemaviewer.py Thu May 14 18:12:45 2009 +0200
+++ b/schemaviewer.py Mon May 18 10:09:06 2009 +0200
@@ -1,7 +1,7 @@
"""an helper class to display CubicWeb schema using ureports
: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"
--- a/server/__init__.py Thu May 14 18:12:45 2009 +0200
+++ b/server/__init__.py Mon May 18 10:09:06 2009 +0200
@@ -4,7 +4,7 @@
This module contains functions to initialize a new repository.
: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"
--- a/server/checkintegrity.py Thu May 14 18:12:45 2009 +0200
+++ b/server/checkintegrity.py Mon May 18 10:09:06 2009 +0200
@@ -61,7 +61,7 @@
yield container
else:
yield eschema
-
+
def reindex_entities(schema, session):
"""reindex all entities in the repository"""
# deactivate modification_date hook since we don't want them
@@ -103,7 +103,7 @@
# restore Entity.check
Entity.check = _check
-
+
def check_schema(schema, session, eids, fix=1):
"""check serialized schema"""
print 'Checking serialized schema'
@@ -122,7 +122,7 @@
count, cstrname, en, rn)
-
+
def check_text_index(schema, session, eids, fix=1):
"""check all entities registered in the text index"""
print 'Checking text index'
@@ -172,8 +172,8 @@
print >> sys.stderr, ' [FIXED]'
else:
print >> sys.stderr
-
-
+
+
def bad_related_msg(rtype, target, eid, fix):
msg = ' A relation %s with %s eid %s exists but no such entity in sources'
print >> sys.stderr, msg % (rtype, target, eid),
@@ -181,8 +181,8 @@
print >> sys.stderr, ' [FIXED]'
else:
print >> sys.stderr
-
-
+
+
def check_relations(schema, session, eids, fix=1):
"""check all relations registered in the repo system table"""
print 'Checking relations'
--- a/server/hookhelper.py Thu May 14 18:12:45 2009 +0200
+++ b/server/hookhelper.py Mon May 18 10:09:06 2009 +0200
@@ -42,7 +42,7 @@
for session in repo._sessions.values():
if ueid == session.user.eid:
yield session
-
+
# mail related ################################################################
@@ -58,17 +58,17 @@
else:
assert recipients is None
self.to_send = []
- super(SendMailOp, self).__init__(session, **kwargs)
-
+ super(SendMailOp, self).__init__(session, **kwargs)
+
def register(self, session):
previous = super(SendMailOp, self).register(session)
if previous:
self.to_send = previous.to_send + self.to_send
-
+
def commit_event(self):
self.repo.threaded_task(self.sendmails)
- def sendmails(self):
+ def sendmails(self):
server, port = self.config['smtp-host'], self.config['smtp-port']
SMTP_LOCK.acquire()
try:
@@ -89,7 +89,7 @@
smtp.close()
finally:
SMTP_LOCK.release()
-
+
# state related ###############################################################
--- a/server/hooks.py Thu May 14 18:12:45 2009 +0200
+++ b/server/hooks.py Mon May 18 10:09:06 2009 +0200
@@ -18,13 +18,13 @@
def relation_deleted(session, eidfrom, rtype, eidto):
session.add_query_data('pendingrelations', (eidfrom, rtype, eidto))
-
+
# base meta-data handling #####################################################
def setctime_before_add_entity(session, entity):
"""before create a new entity -> set creation and modification date
-
+
this is a conveniency hook, you shouldn't have to disable it
"""
if not 'creation_date' in entity:
@@ -36,9 +36,9 @@
"""update an entity -> set modification date"""
if not 'modification_date' in entity:
entity['modification_date'] = datetime.now()
-
+
class SetCreatorOp(PreCommitOperation):
-
+
def precommit_event(self):
if self.eid in self.session.query_data('pendingeids', ()):
# entity have been created and deleted in the same transaction
@@ -46,7 +46,7 @@
ueid = self.session.user.eid
execute = self.session.unsafe_execute
if not execute('Any X WHERE X created_by U, X eid %(x)s',
- {'x': self.eid}, 'x'):
+ {'x': self.eid}, 'x'):
execute('SET X created_by U WHERE X eid %(x)s, U eid %(u)s',
{'x': self.eid, 'u': ueid}, 'x')
@@ -93,15 +93,15 @@
if session.repo.schema.rschema(rtype).fulltext_container:
FTIndexEntityOp(session, entity=session.entity(eidto))
FTIndexEntityOp(session, entity=session.entity(eidfrom))
-
+
class SyncOwnersOp(PreCommitOperation):
-
+
def precommit_event(self):
self.session.unsafe_execute('SET X owned_by U WHERE C owned_by U, C eid %(c)s,'
'NOT EXISTS(X owned_by U, X eid %(x)s)',
{'c': self.compositeeid, 'x': self.composedeid},
('c', 'x'))
-
+
def sync_owner_after_add_composite_relation(session, eidfrom, rtype, eidto):
"""when adding composite relation, the composed should have the same owners
has the composite
@@ -114,7 +114,7 @@
SyncOwnersOp(session, compositeeid=eidfrom, composedeid=eidto)
elif composite == 'object':
SyncOwnersOp(session, compositeeid=eidto, composedeid=eidfrom)
-
+
def _register_metadata_hooks(hm):
"""register meta-data related hooks on the hooks manager"""
hm.register_hook(setctime_before_add_entity, 'before_add_entity', '')
@@ -127,14 +127,14 @@
hm.register_hook(setis_after_add_entity, 'after_add_entity', '')
if 'CWUser' in hm.schema:
hm.register_hook(setowner_after_add_user, 'after_add_entity', 'CWUser')
-
+
# core hooks ##################################################################
-
+
class DelayedDeleteOp(PreCommitOperation):
"""delete the object of composite relation except if the relation
has actually been redirected to another composite
"""
-
+
def precommit_event(self):
session = self.session
if not self.eid in session.query_data('pendingeids', ()):
@@ -142,7 +142,7 @@
session.unsafe_execute('DELETE %s X WHERE X eid %%(x)s, NOT %s'
% (etype, self.relation),
{'x': self.eid}, 'x')
-
+
def handle_composite_before_del_relation(session, eidfrom, rtype, eidto):
"""delete the object of composite relation"""
composite = rproperty(session, rtype, eidfrom, eidto, 'composite')
@@ -157,7 +157,7 @@
# schema validation hooks #####################################################
-
+
class CheckConstraintsOperation(LateOperation):
"""check a new relation satisfy its constraints
"""
@@ -176,10 +176,10 @@
except NotImplementedError:
self.critical('can\'t check constraint %s, not supported',
constraint)
-
+
def commit_event(self):
pass
-
+
def cstrcheck_after_add_relation(session, eidfrom, rtype, eidto):
"""check the relation satisfy its constraints
@@ -213,7 +213,7 @@
case the relation is being replaced
"""
eid, rtype = None, None
-
+
def precommit_event(self):
# recheck pending eids
if self.eid in self.session.query_data('pendingeids', ()):
@@ -224,18 +224,18 @@
raise ValidationError(self.eid, {self.rtype: msg % {'rtype': self.rtype,
'etype': etype,
'eid': self.eid}})
-
+
def commit_event(self):
pass
-
+
def _rql(self):
raise NotImplementedError()
-
+
class CheckSRelationOp(CheckRequiredRelationOperation):
"""check required subject relation"""
def _rql(self):
return 'Any O WHERE S eid %%(x)s, S %s O' % self.rtype, {'x': self.eid}, 'x'
-
+
class CheckORelationOp(CheckRequiredRelationOperation):
"""check required object relation"""
def _rql(self):
@@ -248,7 +248,7 @@
break
else:
opcls(session, rtype=rtype, eid=eid)
-
+
def cardinalitycheck_after_add_entity(session, entity):
"""check cardinalities are satisfied"""
eid = entity.eid
@@ -283,7 +283,7 @@
def _register_core_hooks(hm):
hm.register_hook(handle_composite_before_del_relation, 'before_delete_relation', '')
hm.register_hook(before_del_group, 'before_delete_entity', 'CWGroup')
-
+
#hm.register_hook(cstrcheck_before_update_entity, 'before_update_entity', '')
hm.register_hook(cardinalitycheck_after_add_entity, 'after_add_entity', '')
hm.register_hook(cardinalitycheck_before_del_relation, 'before_delete_relation', '')
@@ -293,13 +293,13 @@
# user/groups synchronisation #################################################
-
+
class GroupOperation(Operation):
"""base class for group operation"""
geid = None
def __init__(self, session, *args, **kwargs):
"""override to get the group name before actual groups manipulation:
-
+
we may temporarily loose right access during a commit event, so
no query should be emitted while comitting
"""
@@ -318,13 +318,13 @@
except KeyError:
self.error('user %s not in group %s', self.cnxuser, self.group)
return
-
+
def after_del_in_group(session, fromeid, rtype, toeid):
"""modify user permission, need to update users"""
for session_ in get_user_sessions(session.repo, fromeid):
DeleteGroupOp(session, cnxuser=session_.user, geid=toeid)
-
+
class AddGroupOp(GroupOperation):
"""synchronize user when a in_group relation has been added"""
def commit_event(self):
@@ -347,7 +347,7 @@
def __init__(self, session, cnxid):
self.cnxid = cnxid
Operation.__init__(self, session)
-
+
def commit_event(self):
"""the observed connections pool has been commited"""
try:
@@ -359,7 +359,7 @@
"""modify user permission, need to update users"""
for session_ in get_user_sessions(session.repo, eid):
DelUserOp(session, session_.id)
-
+
def _register_usergroup_hooks(hm):
"""register user/group related hooks on the hooks manager"""
hm.register_hook(after_del_user, 'after_delete_entity', 'CWUser')
@@ -430,7 +430,7 @@
def set_initial_state_after_add(session, entity):
SetInitialStateOp(session, entity=entity)
-
+
def _register_wf_hooks(hm):
"""register workflow related hooks on the hooks manager"""
if 'in_state' in hm.schema:
@@ -447,7 +447,7 @@
class DelCWPropertyOp(Operation):
"""a user's custom properties has been deleted"""
-
+
def commit_event(self):
"""the observed connections pool has been commited"""
try:
@@ -457,14 +457,14 @@
class ChangeCWPropertyOp(Operation):
"""a user's custom properties has been added/changed"""
-
+
def commit_event(self):
"""the observed connections pool has been commited"""
self.epropdict[self.key] = self.value
class AddCWPropertyOp(Operation):
"""a user's custom properties has been added/changed"""
-
+
def commit_event(self):
"""the observed connections pool has been commited"""
eprop = self.eprop
@@ -485,7 +485,7 @@
{'x': entity.eid, 'u': session.user.eid}, 'x')
else:
AddCWPropertyOp(session, eprop=entity)
-
+
def after_update_eproperty(session, entity):
key, value = entity.pkey, entity.value
try:
@@ -502,7 +502,7 @@
# site wide properties
ChangeCWPropertyOp(session, epropdict=session.vreg.eprop_values,
key=key, value=value)
-
+
def before_del_eproperty(session, eid):
for eidfrom, rtype, eidto in session.query_data('pendingrelations', ()):
if rtype == 'for_user' and eidfrom == eid:
@@ -524,7 +524,7 @@
for session_ in get_user_sessions(session.repo, toeid):
ChangeCWPropertyOp(session, epropdict=session_.user.properties,
key=key, value=value)
-
+
def before_del_for_user(session, fromeid, rtype, toeid):
key = session.execute('Any K WHERE P eid %(x)s, P pkey K',
{'x': fromeid}, 'x')[0][0]
--- a/server/hooksmanager.py Thu May 14 18:12:45 2009 +0200
+++ b/server/hooksmanager.py Mon May 18 10:09:06 2009 +0200
@@ -28,7 +28,7 @@
"""
__docformat__ = "restructuredtext en"
-ENTITIES_HOOKS = ('before_add_entity', 'after_add_entity',
+ENTITIES_HOOKS = ('before_add_entity', 'after_add_entity',
'before_update_entity', 'after_update_entity',
'before_delete_entity', 'after_delete_entity')
RELATIONS_HOOKS = ('before_add_relation', 'after_add_relation' ,
@@ -42,7 +42,7 @@
"""handle hooks registration and calls
"""
verification_hooks_activated = True
-
+
def __init__(self, schema):
self.set_schema(schema)
@@ -50,20 +50,20 @@
self._hooks = {}
self.schema = schema
self._init_hooks(schema)
-
+
def register_hooks(self, hooks):
"""register a dictionary of hooks :
-
+
{'event': {'entity or relation type': [callbacks list]}}
"""
for event, subevents in hooks.items():
for subevent, callbacks in subevents.items():
for callback in callbacks:
self.register_hook(callback, event, subevent)
-
+
def register_hook(self, function, event, etype=''):
"""register a function to call when <event> occurs
-
+
<etype> is an entity/relation type or an empty string.
If etype is the empty string, the function will be called at each
event, else the function will be called only when event occurs on an
@@ -76,14 +76,14 @@
self._hooks[event][etype].append(function)
self.debug('registered hook %s on %s (%s)', event, etype or 'any',
function.func_name)
-
+
except KeyError:
self.error('can\'t register hook %s on %s (%s)',
event, etype or 'any', function.func_name)
-
+
def unregister_hook(self, function, event, etype=''):
"""register a function to call when <event> occurs
-
+
<etype> is an entity/relation type or an empty string.
If etype is the empty string, the function will be called at each
event, else the function will be called only when event occurs on an
@@ -109,7 +109,7 @@
for hook in self._hooks[__event][__type]:
#print '[%s]'%__type, hook.__name__
hook(*args, **kwargs)
-
+
def _init_hooks(self, schema):
"""initialize the hooks map"""
for hook_event in ENTITIES_HOOKS:
@@ -164,7 +164,7 @@
self.unregister_hook(uniquecstrcheck_before_modification, 'before_update_entity', '')
# self.unregister_hook(tidy_html_fields('before_add_entity'), 'before_add_entity', '')
# self.unregister_hook(tidy_html_fields('before_update_entity'), 'before_update_entity', '')
-
+
def reactivate_verification_hooks(self):
from cubicweb.server.hooks import (cardinalitycheck_after_add_entity,
cardinalitycheck_before_del_relation,
@@ -179,7 +179,7 @@
self.register_hook(uniquecstrcheck_before_modification, 'before_update_entity', '')
# self.register_hook(tidy_html_fields('before_add_entity'), 'before_add_entity', '')
# self.register_hook(tidy_html_fields('before_update_entity'), 'before_update_entity', '')
-
+
from cubicweb.selectors import yes
from cubicweb.appobject import AppObject
@@ -199,16 +199,16 @@
events = None
accepts = None
enabled = True
-
+
def __init__(self, event=None):
super(Hook, self).__init__()
self.event = event
-
+
@classmethod
def registered(cls, vreg):
super(Hook, cls).registered(vreg)
return cls()
-
+
@classmethod
def register_to(cls):
if not cls.enabled:
@@ -232,7 +232,7 @@
continue
yield event, str(eetype)
done.add((event, eetype))
-
+
def make_callback(self, event):
if len(self.events) == 1:
@@ -241,7 +241,7 @@
def call(self):
raise NotImplementedError
-
+
class SystemHook(Hook):
accepts = ('',)
--- a/server/mssteps.py Thu May 14 18:12:45 2009 +0200
+++ b/server/mssteps.py Mon May 18 10:09:06 2009 +0200
@@ -16,7 +16,7 @@
from cubicweb.server.ssplanner import (LimitOffsetMixIn, Step, OneFetchStep,
varmap_test_repr, offset_result)
-AGGR_TRANSFORMS = {'COUNT':'SUM', 'MIN':'MIN', 'MAX':'MAX', 'SUM': 'SUM'}
+AGGR_TRANSFORMS = {'COUNT':'SUM', 'MIN':'MIN', 'MAX':'MAX', 'SUM': 'SUM'}
def remove_clauses(union, keepgroup):
clauses = []
@@ -73,7 +73,7 @@
if lhsvar.name in srqlst.defined_vars:
key = '%s.%s' % (lhsvar.name, rel.r_type)
self.outputmap[key] = self.outputmap[var.name]
-
+
def execute(self):
"""execute this step"""
self.execute_children()
@@ -86,7 +86,7 @@
source.flying_insert(self.table, plan.session, union, plan.args,
self.inputmap)
restore_clauses(union, self.keepgroup, clauses)
-
+
def mytest_repr(self):
"""return a representation of this step suitable for test"""
clauses = remove_clauses(self.union, self.keepgroup)
@@ -104,7 +104,7 @@
finally:
restore_clauses(self.union, self.keepgroup, clauses)
-
+
class AggrStep(LimitOffsetMixIn, Step):
"""step consisting in making aggregat from temporary data in the system
source
@@ -123,7 +123,7 @@
plan.init_temp_table(outputtable, selection, select.solutions[0])
#self.inputmap = inputmap
-
+
def mytest_repr(self):
"""return a representation of this step suitable for test"""
sel = self.select.selection
@@ -167,7 +167,7 @@
clause.append(term.accept(self))
# restaure the tree XXX necessary?
term.name = orig_name
- term.children = orig_children
+ term.children = orig_children
except KeyError:
clause.append(var_name)
else:
@@ -215,28 +215,28 @@
self.plan.create_temp_table(self.outputtable)
sql = 'INSERT INTO %s %s' % (self.outputtable, sql)
return self.plan.sqlexec(sql, self.plan.args)
-
+
def visit_function(self, function):
"""generate SQL name for a function"""
return '%s(%s)' % (function.name,
','.join(c.accept(self) for c in function.children))
-
+
def visit_variableref(self, variableref):
"""get the sql name for a variable reference"""
try:
return self.inputmap[variableref.name]
except KeyError: # XXX duh? explain
return variableref.variable.name
-
+
def visit_constant(self, constant):
"""generate SQL name for a constant"""
assert constant.type == 'Int'
return str(constant.value)
-
+
class UnionStep(LimitOffsetMixIn, Step):
"""union results of child in-memory steps (e.g. OneFetchStep / AggrStep)"""
-
+
def execute(self):
"""execute this step"""
result = []
@@ -258,7 +258,7 @@
if len(result) >= olimit:
return result[:olimit]
return result
-
+
def mytest_repr(self):
"""return a representation of this step suitable for test"""
return (self.__class__.__name__, self.limit, self.offset)
@@ -266,7 +266,7 @@
class IntersectStep(UnionStep):
"""return intersection of results of child in-memory steps (e.g. OneFetchStep / AggrStep)"""
-
+
def execute(self):
"""execute this step"""
result = set()
--- a/server/pool.py Thu May 14 18:12:45 2009 +0200
+++ b/server/pool.py Mon May 18 10:09:06 2009 +0200
@@ -2,7 +2,7 @@
* the rql repository has a limited number of connections pools, each of them
dealing with a set of connections on each source used by the repository
-
+
* operation may be registered by hooks during a transaction, which will be
fired when the pool is commited or rollbacked
@@ -17,7 +17,7 @@
__docformat__ = "restructuredtext en"
import sys
-
+
class ConnectionsPool(object):
"""handle connections on a set of sources, at some point associated to a
user session
@@ -40,7 +40,7 @@
for source, cnx in self.source_cnxs.values():
# let exception propagates
cnx.commit()
-
+
def rollback(self):
"""rollback the current transaction for this user"""
for source, cnx in self.source_cnxs.values():
@@ -64,7 +64,7 @@
cnx.close()
except:
continue
-
+
# internals ###############################################################
def pool_set(self, session):
@@ -75,7 +75,7 @@
"""pool is being reseted"""
for source, cnx in self.source_cnxs.values():
source.pool_reset(cnx)
-
+
def __getitem__(self, uri):
"""subscription notation provide access to sources'cursors"""
try:
@@ -86,7 +86,7 @@
# None possible on sources without cursor support such as ldap
self._cursors[uri] = cursor
return cursor
-
+
def sources(self):
"""return the source objects handled by this pool"""
# implementation details of flying insert requires the system source
@@ -97,11 +97,11 @@
continue
yield source
#return [source_cnx[0] for source_cnx in self.source_cnxs.values()]
-
+
def source(self, uid):
"""return the source object with the given uri"""
return self.source_cnxs[uid][0]
-
+
def connection(self, uid):
"""return the connection on the source object with the given uri"""
return self.source_cnxs[uid][1]
@@ -109,7 +109,7 @@
def reconnect(self, source):
"""reopen a connection for this source"""
source.info('trying to reconnect')
- self.source_cnxs[source.uri] = (source, source.get_connection())
+ self.source_cnxs[source.uri] = (source, source.get_connection())
del self._cursors[source.uri]
def check_connections(self):
@@ -133,11 +133,11 @@
do any heavy computation or raise an exception if the commit can't go.
You can add some new operation during this phase but their precommit
event won't be triggered
-
+
commit:
the pool is preparing to commit. You should avoid to do to expensive
stuff or something that may cause an exception in this event
-
+
revertcommit:
if an operation failed while commited, this event is triggered for
all operations which had their commit event already to let them
@@ -153,7 +153,7 @@
order of operations may be important, and is controlled according to:
* operation's class
"""
-
+
def __init__(self, session, **kwargs):
self.session = session
self.user = session.user
@@ -165,10 +165,10 @@
# execution information
self.processed = None # 'precommit', 'commit'
self.failed = False
-
+
def register(self, session):
session.add_operation(self, self.insert_index())
-
+
def insert_index(self):
"""return the index of the lastest instance which is not a
LateOperation instance
@@ -177,17 +177,17 @@
if isinstance(op, (LateOperation, SingleLastOperation)):
return i
return None
-
+
def handle_event(self, event):
"""delegate event handling to the opertaion"""
getattr(self, event)()
def precommit_event(self):
"""the observed connections pool is preparing a commit"""
-
+
def revertprecommit_event(self):
"""an error went when pre-commiting this operation or a later one
-
+
should revert pre-commit's changes but take care, they may have not
been all considered if it's this operation which failed
"""
@@ -195,17 +195,17 @@
def commit_event(self):
"""the observed connections pool is commiting"""
raise NotImplementedError()
-
+
def revertcommit_event(self):
"""an error went when commiting this operation or a later one
-
+
should revert commit's changes but take care, they may have not
been all considered if it's this operation which failed
"""
-
+
def rollback_event(self):
"""the observed connections pool has been rollbacked
-
+
do nothing by default, the operation will just be removed from the pool
operation list
"""
@@ -226,7 +226,7 @@
class LateOperation(Operation):
"""special operation which should be called after all possible (ie non late)
operations
- """
+ """
def insert_index(self):
"""return the index of the lastest instance which is not a
SingleLastOperation instance
@@ -238,7 +238,7 @@
class SingleOperation(Operation):
- """special operation which should be called once"""
+ """special operation which should be called once"""
def register(self, session):
"""override register to handle cases where this operation has already
been added
@@ -251,7 +251,7 @@
equivalent = None
session.add_operation(self, self.insert_index())
return equivalent
-
+
def equivalent_index(self, operations):
"""return the index of the equivalent operation if any"""
equivalents = [i for i, op in enumerate(operations)
@@ -264,7 +264,7 @@
class SingleLastOperation(SingleOperation):
"""special operation which should be called once and after all other
operations
- """
+ """
def insert_index(self):
return None
--- a/server/querier.py Thu May 14 18:12:45 2009 +0200
+++ b/server/querier.py Mon May 18 10:09:06 2009 +0200
@@ -2,7 +2,7 @@
security checking and data aggregation.
: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"
@@ -84,7 +84,7 @@
#assert len(erqlexprs) == 1
localchecks[varname] = tuple(erqlexprs)
return localchecks
-
+
def noinvariant_vars(restricted, select, nbtrees):
# a variable can actually be invariant if it has not been restricted for
# security reason or if security assertion hasn't modified the possible
@@ -114,12 +114,12 @@
colalias = newselect.get_variable(vref.name, len(aliases))
aliases.append(VariableRef(colalias))
selected.add(vref.name)
-
+
# Plans #######################################################################
class ExecutionPlan(object):
"""the execution model of a rql query, composed of querier steps"""
-
+
def __init__(self, querier, rqlst, args, session):
# original rql syntax tree
self.rqlst = rqlst
@@ -137,11 +137,11 @@
self.schema = querier.schema
self.rqlhelper = querier._rqlhelper
self.sqlannotate = querier.sqlgen_annotate
-
+
def annotate_rqlst(self):
if not self.rqlst.annotated:
self.rqlhelper.annotate(self.rqlst)
-
+
def add_step(self, step):
"""add a step to the plan"""
self.steps.append(step)
@@ -149,10 +149,10 @@
def clean(self):
"""remove temporary tables"""
self.syssource.clean_temp_data(self.session, self.temp_tables)
-
+
def sqlexec(self, sql, args=None):
return self.syssource.sqlexec(self.session, sql, args)
-
+
def execute(self):
"""execute a plan and return resulting rows"""
try:
@@ -162,7 +162,7 @@
return result
finally:
self.clean()
-
+
def init_temp_table(self, table, selected, sol):
"""initialize sql schema and variable map for a temporary table which
will be used to store result for the given rqlst
@@ -175,17 +175,17 @@
table)
self.temp_tables[table] = [outputmap, sqlschema, False]
return outputmap
-
+
def create_temp_table(self, table):
"""create a temporary table to store result for the given rqlst"""
if not self.temp_tables[table][-1]:
sqlschema = self.temp_tables[table][1]
self.syssource.create_temp_table(self.session, table, sqlschema)
self.temp_tables[table][-1] = True
-
+
def preprocess(self, union, security=True):
"""insert security when necessary then annotate rql st for sql generation
-
+
return rqlst to actually execute
"""
#if server.DEBUG:
@@ -279,7 +279,7 @@
are removed, else if the user may read it (eg if an rql expression is
defined for the "read" permission of the related type), the local checks
dict for the solution is updated
-
+
return a dict with entries for each different local check necessary,
with associated solutions as value. A local check is defined by a list
of 2-uple, with variable name as first item and the necessary rql
@@ -346,11 +346,11 @@
self.rqlhelper.annotate(rqlst)
self.preprocess(rqlst, security=False)
return rqlst
-
+
class InsertPlan(ExecutionPlan):
"""an execution model specific to the INSERT rql query
"""
-
+
def __init__(self, querier, rqlst, args, session):
ExecutionPlan.__init__(self, querier, rqlst, args, session)
# save originaly selected variable, we may modify this
@@ -387,7 +387,7 @@
value = rhs.eval(self.args)
eschema = edef.e_schema
attrtype = eschema.subject_relation(rtype).objects(eschema)[0]
- if attrtype == 'Password' and isinstance(value, unicode):
+ if attrtype == 'Password' and isinstance(value, unicode):
value = value.encode('UTF8')
edef[rtype] = value
elif to_build.has_key(str(rhs)):
@@ -397,12 +397,12 @@
to_select.setdefault(edef, []).append( (rtype, rhs, 0) )
return to_select
-
+
def add_entity_def(self, edef):
"""add an entity definition to build"""
edef.querier_pending_relations = {}
self.e_defs[-1].append(edef)
-
+
def add_relation_def(self, rdef):
"""add an relation definition to build"""
self.r_defs.append(rdef)
@@ -410,11 +410,11 @@
self._r_subj_index.setdefault(rdef[0], []).append(rdef)
if not isinstance(rdef[2], int):
self._r_obj_index.setdefault(rdef[2], []).append(rdef)
-
+
def substitute_entity_def(self, edef, edefs):
"""substitute an incomplete entity definition by a list of complete
equivalents
-
+
e.g. on queries such as ::
INSERT Personne X, Societe Y: X nom N, Y nom 'toto', X travaille Y
WHERE U login 'admin', U login N
@@ -455,7 +455,7 @@
for edef in edefs:
result.append( (exp_rdef[0], exp_rdef[1], edef) )
self._expanded_r_defs[rdef] = result
-
+
def _expanded(self, rdef):
"""return expanded value for the given relation definition"""
try:
@@ -463,7 +463,7 @@
except KeyError:
self.r_defs.remove(rdef)
return [rdef]
-
+
def relation_defs(self):
"""return the list for relation definitions to insert"""
for rdefs in self._expanded_r_defs.values():
@@ -471,11 +471,11 @@
yield rdef
for rdef in self.r_defs:
yield rdef
-
+
def insert_entity_defs(self):
"""return eids of inserted entities in a suitable form for the resulting
result set, e.g.:
-
+
e.g. on queries such as ::
INSERT Personne X, Societe Y: X nom N, Y nom 'toto', X travaille Y
WHERE U login 'admin', U login N
@@ -490,7 +490,7 @@
results.append([repo.glob_add_entity(session, edef)
for edef in row])
return results
-
+
def insert_relation_defs(self):
session = self.session
repo = session.repo
@@ -514,18 +514,18 @@
class QuerierHelper(object):
"""helper class to execute rql queries, putting all things together"""
-
+
def __init__(self, repo, schema):
# system info helper
self._repo = repo
# application schema
self.set_schema(schema)
-
+
def set_schema(self, schema):
self.schema = schema
# rql parsing / analysing helper
self._rqlhelper = RQLHelper(schema, special_relations={'eid': 'uid',
- 'has_text': 'fti'})
+ 'has_text': 'fti'})
self._rql_cache = Cache(self._repo.config['rql-cache-size'])
self.cache_hit, self.cache_miss = 0, 0
# rql planner
@@ -535,11 +535,11 @@
from cubicweb.server.ssplanner import SSPlanner
self._planner = SSPlanner(schema, self._rqlhelper)
else:
- from cubicweb.server.msplanner import MSPlanner
+ from cubicweb.server.msplanner import MSPlanner
self._planner = MSPlanner(schema, self._rqlhelper)
# sql generation annotator
self.sqlgen_annotate = SQLGenAnnotator(schema).annotate
-
+
def parse(self, rql, annotate=False):
"""return a rql syntax tree for the given rql"""
try:
@@ -559,7 +559,7 @@
if rqlst.TYPE == 'insert':
return InsertPlan(self, rqlst, args, session)
return ExecutionPlan(self, rqlst, args, session)
-
+
def execute(self, session, rql, args=None, eid_key=None, build_descr=True):
"""execute a rql query, return resulting rows and their description in
a `ResultSet` object
@@ -578,7 +578,7 @@
on INSERT queries, there will be on row with the eid of each inserted
entity
-
+
result for DELETE and SET queries is undefined yet
to maximize the rql parsing/analyzing cache performance, you should
--- a/server/rqlannotation.py Thu May 14 18:12:45 2009 +0200
+++ b/server/rqlannotation.py Mon May 18 10:09:06 2009 +0200
@@ -69,7 +69,7 @@
# "Any X", "Any X, Y WHERE X attr Y"
stinfo['invariant'] = False
continue
- joins = set()
+ joins = set()
invariant = False
for ref in var.references():
rel = ref.relation()
@@ -78,7 +78,7 @@
lhs, rhs = rel.get_parts()
onlhs = ref is lhs
if rel.r_type == 'eid':
- if not (onlhs and len(stinfo['relations']) > 1):
+ if not (onlhs and len(stinfo['relations']) > 1):
break
if not stinfo['constnode']:
joins.add(rel)
@@ -110,9 +110,9 @@
continue
if not stinfo['constnode']:
if rschema.inlined and rel.neged(strict=True):
- # if relation is inlined, can't be invariant if that
+ # if relation is inlined, can't be invariant if that
# variable is used anywhere else.
- # see 'Any P WHERE NOT N ecrit_par P, N eid 512':
+ # see 'Any P WHERE NOT N ecrit_par P, N eid 512':
# sql for 'NOT N ecrit_par P' is 'N.ecrit_par is NULL' so P
# can use N.ecrit_par as principal
if (stinfo['selected'] or len(stinfo['relations']) > 1):
@@ -184,7 +184,7 @@
return iter(_sort(diffscope_rels)).next()
# XXX could use a relation for a different scope if it can't generate
# duplicates, so we would have to check cardinality
- raise CantSelectPrincipal()
+ raise CantSelectPrincipal()
def _select_main_var(relations):
"""given a list of rqlst relations, select one which will be used as main
@@ -265,12 +265,12 @@
return False
try:
data = var.stmt._deamb_data
- except AttributeError:
+ except AttributeError:
data = var.stmt._deamb_data = IsAmbData(self.schema, self.nfdomain)
data.compute(var.stmt)
return data.is_ambiguous(var)
-
+
class IsAmbData(object):
def __init__(self, schema, nfdomain):
self.schema = schema
@@ -288,7 +288,7 @@
self.deambification_map = {}
# not invariant variables (access to final.inlined relation)
self.not_invariants = set()
-
+
def is_ambiguous(self, var):
return var in self.ambiguousvars
@@ -296,7 +296,7 @@
self.varsols[var] &= restricted_domain
if var in self.ambiguousvars and self.varsols[var] == var.stinfo['possibletypes']:
self.ambiguousvars.remove(var)
-
+
def compute(self, rqlst):
# set domains for each variable
for varname, var in rqlst.defined_vars.iteritems():
@@ -334,7 +334,7 @@
except KeyError:
# no relation to deambiguify
continue
-
+
def _debug_print(self):
print 'varsols', dict((x, sorted(str(v) for v in values))
for x, values in self.varsols.iteritems())
@@ -350,7 +350,7 @@
self.maydeambrels[var].add(rel)
except KeyError:
self.maydeambrels[var] = set((rel,))
-
+
def deambiguifying_relation(self, var, rel):
lhs, rhs = rel.get_variable_parts()
onlhs = var is getattr(lhs, 'variable', None)
--- a/server/rqlrewrite.py Thu May 14 18:12:45 2009 +0200
+++ b/server/rqlrewrite.py Mon May 18 10:09:06 2009 +0200
@@ -34,7 +34,7 @@
return newsolutions
class Unsupported(Exception): pass
-
+
class RQLRewriter(object):
"""insert some rql snippets into another rql syntax tree"""
def __init__(self, querier, session):
@@ -51,7 +51,7 @@
raise Unsupported()
if len(self.select.solutions) < len(self.solutions):
raise Unsupported()
-
+
def rewrite(self, select, snippets, solutions, kwargs):
if server.DEBUG:
print '---- rewrite', select, snippets, solutions
@@ -112,7 +112,7 @@
add_types_restriction(self.schema, select)
if server.DEBUG:
print '---- rewriten', select
-
+
def build_variantes(self, newsolutions):
variantes = set()
for sol in newsolutions:
@@ -133,7 +133,7 @@
for variante in variantes:
del variante[(erqlexpr, mainvar, oldvar)]
return variantes
-
+
def insert_snippets(self, snippets, varexistsmap=None):
self.rewritten = {}
for varname, erqlexprs in snippets:
@@ -175,7 +175,7 @@
if varexistsmap is None and not inserted:
# no rql expression found matching rql solutions. User has no access right
raise Unauthorized()
-
+
def insert_snippet(self, varname, snippetrqlst, parent=None):
new = snippetrqlst.where.accept(self)
if new is not None:
@@ -240,7 +240,7 @@
else:
parent.parent.replace(or_, or_.children[0])
self._cleanup_inserted(new)
- raise
+ raise
return new
def _cleanup_inserted(self, node):
@@ -250,7 +250,7 @@
if not vref.variable.stinfo['references']:
# no more references, undefine the variable
del self.select.defined_vars[vref.name]
-
+
def _visit_binary(self, node, cls):
newnode = cls()
for c in node.children:
@@ -270,20 +270,20 @@
return None
newnode = cls()
newnode.append(newc)
- return newnode
-
+ return newnode
+
def visit_and(self, et):
return self._visit_binary(et, nodes.And)
def visit_or(self, ou):
return self._visit_binary(ou, nodes.Or)
-
+
def visit_not(self, node):
return self._visit_unary(node, nodes.Not)
def visit_exists(self, node):
return self._visit_unary(node, nodes.Exists)
-
+
def visit_relation(self, relation):
lhs, rhs = relation.get_variable_parts()
if lhs.name == 'X':
@@ -301,7 +301,7 @@
if relation.r_type in self.rhs_rels and self._may_be_shared(relation, 'subject'):
# ok, can share variable
term = self.rhs_rels[relation.r_type].children[0]
- self._use_outer_term(lhs.name, term)
+ self._use_outer_term(lhs.name, term)
return
rel = nodes.Relation(relation.r_type, relation.optional)
for c in relation.children:
@@ -319,7 +319,7 @@
for c in cmp.children:
cmp_.append(c.accept(self))
return cmp_
-
+
def visit_function(self, function):
"""generate filter name for a function"""
function_ = nodes.Function(function.name)
@@ -371,7 +371,7 @@
for inserted_vref in insertedvar.references():
inserted_vref.parent.replace(inserted_vref, term.copy(self.select))
self.rewritten[key] = term
-
+
def _get_varname_or_term(self, vname):
if vname == 'U':
if self.u_varname is None:
--- a/server/schemahooks.py Thu May 14 18:12:45 2009 +0200
+++ b/server/schemahooks.py Mon May 18 10:09:06 2009 +0200
@@ -21,7 +21,7 @@
from cubicweb.server.pool import Operation, SingleLastOperation, PreCommitOperation
from cubicweb.server.hookhelper import (entity_attr, entity_name,
check_internal_entity)
-
+
# core entity and relation types which can't be removed
CORE_ETYPES = list(BASE_TYPES) + ['CWEType', 'CWRType', 'CWUser', 'CWGroup',
'CWConstraint', 'CWAttribute', 'CWRelation']
@@ -52,7 +52,7 @@
% (table, column)))
session.info('added column %s to table %s', column, table)
except:
- # silent exception here, if this error has not been raised because the
+ # silent exception here, if this error has not been raised because the
# column already exists, index creation will fail anyway
session.exception('error while adding column %s to table %s',
table, column)
@@ -74,7 +74,7 @@
Operation.__init__(self, session, **kwargs)
# every schema operation is triggering a schema update
UpdateSchemaOp(session)
-
+
class EarlySchemaOperation(SchemaOperation):
def insert_index(self):
"""schema operation which are inserted at the begining of the queue
@@ -85,7 +85,7 @@
if not isinstance(op, EarlySchemaOperation):
return i
return i + 1
-
+
class UpdateSchemaOp(SingleLastOperation):
"""the update schema operation:
@@ -93,15 +93,15 @@
operations. It will trigger internal structures rebuilding to consider
schema changes
"""
-
+
def __init__(self, session):
self.repo = session.repo
SingleLastOperation.__init__(self, session)
-
+
def commit_event(self):
self.repo.set_schema(self.repo.schema)
-
+
class DropTableOp(PreCommitOperation):
"""actually remove a database from the application's schema"""
table = None # make pylint happy
@@ -113,7 +113,7 @@
dropped.add(self.table)
self.session.system_sql('DROP TABLE %s' % self.table)
self.info('dropped table %s', self.table)
-
+
class DropColumnOp(PreCommitOperation):
"""actually remove the attribut's column from entity table in the system
database
@@ -130,12 +130,12 @@
except Exception, ex:
# not supported by sqlite for instance
self.error('error while altering table %s: %s', table, ex)
-
+
# deletion ####################################################################
class DeleteCWETypeOp(SchemaOperation):
- """actually remove the entity type from the application's schema"""
+ """actually remove the entity type from the application's schema"""
def commit_event(self):
try:
# del_entity_type also removes entity's relations
@@ -162,9 +162,9 @@
session.execute('DELETE State X WHERE NOT X state_of Y')
session.execute('DELETE Transition X WHERE NOT X transition_of Y')
-
+
class DeleteCWRTypeOp(SchemaOperation):
- """actually remove the relation type from the application's schema"""
+ """actually remove the relation type from the application's schema"""
def commit_event(self):
try:
self.schema.del_relation_type(self.kobj)
@@ -186,7 +186,7 @@
{'x': eid})
DeleteCWRTypeOp(session, name)
-
+
class DelErdefOp(SchemaOperation):
"""actually remove the relation definition from the application's schema"""
def commit_event(self):
@@ -196,7 +196,7 @@
except KeyError:
# relation type may have been already deleted
pass
-
+
def after_del_relation_type(session, rdefeid, rtype, rteid):
"""before deleting a CWAttribute or CWRelation entity:
* if this is a final or inlined relation definition, instantiate an
@@ -223,7 +223,7 @@
# we have to update physical schema systematically for final and inlined
# relations, but only if it's the last instance for this relation type
# for other relations
-
+
if (rschema.is_final() or rschema.inlined):
rset = execute('Any COUNT(X) WHERE X is %s, X relation_type R, '
'R eid %%(x)s, X from_entity E, E name %%(name)s'
@@ -238,16 +238,16 @@
execute('DELETE CWRType X WHERE X eid %(x)s', {'x': rteid}, 'x')
DelErdefOp(session, (subjschema, rschema, objschema))
-
+
# addition ####################################################################
class AddCWETypeOp(EarlySchemaOperation):
- """actually add the entity type to the application's schema"""
+ """actually add the entity type to the application's schema"""
eid = None # make pylint happy
def commit_event(self):
eschema = self.schema.add_entity_type(self.kobj)
eschema.eid = self.eid
-
+
def before_add_eetype(session, entity):
"""before adding a CWEType entity:
* check that we are not using an existing entity type,
@@ -304,25 +304,25 @@
class AddCWRTypeOp(EarlySchemaOperation):
- """actually add the relation type to the application's schema"""
+ """actually add the relation type to the application's schema"""
eid = None # make pylint happy
def commit_event(self):
rschema = self.schema.add_relation_type(self.kobj)
rschema.set_default_groups()
rschema.eid = self.eid
-
+
def before_add_ertype(session, entity):
"""before adding a CWRType entity:
* check that we are not using an existing relation type,
* register an operation to add the relation type to the application's
schema on commit
-
+
We don't know yeat this point if a table is necessary
"""
name = entity['name']
if name in session.repo.schema.relations():
raise RepositoryError('a relation type %s already exists' % name)
-
+
def after_add_ertype(session, entity):
"""after a CWRType entity has been added:
* register an operation to add the relation type to the application's
@@ -340,7 +340,7 @@
class AddErdefOp(EarlySchemaOperation):
"""actually add the attribute relation definition to the application's
schema
- """
+ """
def commit_event(self):
self.schema.add_relation_def(self.kobj)
@@ -350,7 +350,7 @@
'Float': float,
'Password': str,
'String': unicode,
- 'Date' : unicode,
+ 'Date' : unicode,
'Datetime' : unicode,
'Time' : unicode,
}
@@ -362,7 +362,7 @@
* set default on this column if any and possible
* register an operation to add the relation definition to the
application's schema on commit
-
+
constraints are handled by specific hooks
"""
entity = None # make pylint happy
@@ -457,7 +457,7 @@
session = self.session
entity = self.entity
fromentity = entity.from_entity[0]
- relationtype = entity.relation_type[0]
+ relationtype = entity.relation_type[0]
session.execute('SET X ordernum Y+1 WHERE X from_entity SE, SE eid %(se)s, X ordernum Y, X ordernum >= %(order)s, NOT X eid %(x)s',
{'x': entity.eid, 'se': fromentity.eid, 'order': entity.ordernum or 0})
subj, rtype = str(fromentity.name), str(relationtype.name)
@@ -508,7 +508,7 @@
if sql.strip():
self.session.system_sql(sql)
session.add_query_data('createdtables', rtype)
-
+
def after_add_enfrdef(session, entity):
AddCWRelationPreCommitOp(session, entity=entity)
@@ -556,7 +556,7 @@
(self.newname, self.oldname))
sqlexec('UPDATE deleted_entities SET type=%s WHERE type=%s',
(self.newname, self.oldname))
-
+
def commit_event(self):
self.session.repo.schema.rename_entity_type(self.oldname, self.newname)
@@ -575,13 +575,13 @@
sysource.create_index(self.session, table, column)
else:
sysource.drop_index(self.session, table, column)
-
+
def commit_event(self):
# structure should be clean, not need to remove entity's relations
# at this point
self.rschema._rproperties[self.kobj].update(self.values)
-
+
def after_update_erdef(session, entity):
desttype = entity.to_entity[0].name
rschema = session.repo.schema[entity.relation_type[0].name]
@@ -600,7 +600,7 @@
class UpdateRtypeOp(SchemaOperation):
- """actually update some properties of a relation definition"""
+ """actually update some properties of a relation definition"""
rschema = values = entity = None # make pylint happy
def precommit_event(self):
@@ -639,13 +639,13 @@
else:
for etype in rschema.subjects():
try:
- add_inline_relation_column(session, str(etype), rtype)
+ add_inline_relation_column(session, str(etype), rtype)
except Exception, ex:
# the column probably already exists. this occurs when
# the entity's type has just been added or if the column
# has not been previously dropped
self.error('error while altering table %s: %s', etype, ex)
- # copy existant data.
+ # copy existant data.
# XXX don't use, it's not supported by sqlite (at least at when i tried it)
#sqlexec('UPDATE %(etype)s SET %(rtype)s=eid_to '
# 'FROM %(rtype)s_relation '
@@ -667,7 +667,7 @@
# structure should be clean, not need to remove entity's relations
# at this point
self.rschema.__dict__.update(self.values)
-
+
def after_update_ertype(session, entity):
rschema = session.repo.schema.rschema(entity.name)
newvalues = {}
@@ -684,13 +684,13 @@
class ConstraintOp(SchemaOperation):
"""actually update constraint of a relation definition"""
entity = None # make pylint happy
-
+
def prepare_constraints(self, rtype, subjtype, objtype):
constraints = rtype.rproperty(subjtype, objtype, 'constraints')
self.constraints = list(constraints)
rtype.set_rproperty(subjtype, objtype, 'constraints', self.constraints)
return self.constraints
-
+
def precommit_event(self):
rdef = self.entity.reverse_constrained_by[0]
session = self.session
@@ -698,7 +698,7 @@
# is created by AddEN?FRDefPreCommitOp, there is nothing to do here
if rdef.eid in session.query_data('neweids', ()):
self.cancelled = True
- return
+ return
self.cancelled = False
schema = session.repo.schema
subjtype, rtype, objtype = schema.schema_by_eid(rdef.eid)
@@ -723,7 +723,7 @@
elif cstrtype == 'UniqueConstraint':
session.pool.source('system').create_index(
self.session, table, column, unique=True)
-
+
def commit_event(self):
if self.cancelled:
return
@@ -743,7 +743,7 @@
class DelConstraintOp(ConstraintOp):
"""actually remove a constraint of a relation definition"""
rtype = subjtype = objtype = None # make pylint happy
-
+
def precommit_event(self):
self.prepare_constraints(self.rtype, self.subjtype, self.objtype)
cstrtype = self.cstr.type()
@@ -754,7 +754,7 @@
try:
self.session.system_sql('ALTER TABLE %s ALTER COLUMN %s TYPE TEXT'
% (table, column))
- self.info('altered column %s of table %s: now TEXT',
+ self.info('altered column %s of table %s: now TEXT',
column, table)
except Exception, ex:
# not supported by sqlite for instance
@@ -762,7 +762,7 @@
elif cstrtype == 'UniqueConstraint':
self.session.pool.source('system').drop_index(
self.session, table, column, unique=True)
-
+
def commit_event(self):
self.constraints.remove(self.cstr)
@@ -784,7 +784,7 @@
if fromeid in session.query_data('neweids', ()):
session.add_query_data(fromeid, toeid)
-
+
# schema permissions synchronization ##########################################
class PermissionOp(Operation):
@@ -805,7 +805,7 @@
def __init__(self, session, perm, etype_eid, group_eid):
self.group = entity_name(session, group_eid)
PermissionOp.__init__(self, session, perm, etype_eid)
-
+
def commit_event(self):
"""the observed connections pool has been commited"""
try:
@@ -815,7 +815,7 @@
self.error('no schema for %s', self.name)
return
groups = list(erschema.get_groups(self.perm))
- try:
+ try:
groups.index(self.group)
self.warning('group %s already have permission %s on %s',
self.group, self.perm, erschema.type)
@@ -830,7 +830,7 @@
def __init__(self, session, perm, etype_eid, expression):
self.expr = expression
PermissionOp.__init__(self, session, perm, etype_eid)
-
+
def commit_event(self):
"""the observed connections pool has been commited"""
try:
@@ -852,12 +852,12 @@
expr = session.execute('Any EXPR WHERE X eid %(x)s, X expression EXPR',
{'x': object}, 'x')[0][0]
AddRQLExpressionPermissionOp(session, perm, subject, expr)
-
+
-
+
class DelGroupPermissionOp(AddGroupPermissionOp):
"""synchronize schema when a *_permission relation has been deleted from a group"""
-
+
def commit_event(self):
"""the observed connections pool has been commited"""
try:
@@ -867,17 +867,17 @@
self.error('no schema for %s', self.name)
return
groups = list(erschema.get_groups(self.perm))
- try:
+ try:
groups.remove(self.group)
erschema.set_groups(self.perm, groups)
except ValueError:
self.error('can\'t remove permission %s on %s to group %s',
self.perm, erschema.type, self.group)
-
+
class DelRQLExpressionPermissionOp(AddRQLExpressionPermissionOp):
"""synchronize schema when a *_permission relation has been deleted from an rql expression"""
-
+
def commit_event(self):
"""the observed connections pool has been commited"""
try:
@@ -897,7 +897,7 @@
return
erschema.set_rqlexprs(self.perm, rqlexprs)
-
+
def before_del_permission(session, subject, rtype, object):
"""delete entity/relation *_permission, need to update schema
@@ -943,7 +943,7 @@
hm.register_hook(before_del_ertype, 'before_delete_entity', 'CWRType')
hm.register_hook(after_del_relation_type, 'after_delete_relation', 'relation_type')
hm.register_hook(rebuild_infered_relations, 'after_add_relation', 'specializes')
- hm.register_hook(rebuild_infered_relations, 'after_delete_relation', 'specializes')
+ hm.register_hook(rebuild_infered_relations, 'after_delete_relation', 'specializes')
# constraints synchronization hooks
hm.register_hook(after_add_econstraint, 'after_add_entity', 'CWConstraint')
hm.register_hook(after_update_econstraint, 'after_update_entity', 'CWConstraint')
--- a/server/securityhooks.py Thu May 14 18:12:45 2009 +0200
+++ b/server/securityhooks.py Mon May 18 10:09:06 2009 +0200
@@ -24,25 +24,25 @@
if rschema.is_final(): # non final relation are checked by other hooks
# add/delete should be equivalent (XXX: unify them into 'update' ?)
rschema.check_perm(session, 'add', eid)
-
-
+
+
class CheckEntityPermissionOp(LateOperation):
def precommit_event(self):
#print 'CheckEntityPermissionOp', self.session.user, self.entity, self.action
self.entity.check_perm(self.action)
check_entity_attributes(self.session, self.entity)
-
+
def commit_event(self):
pass
-
-
+
+
class CheckRelationPermissionOp(LateOperation):
def precommit_event(self):
self.rschema.check_perm(self.session, self.action, self.fromeid, self.toeid)
-
+
def commit_event(self):
pass
-
+
def after_add_entity(session, entity):
if not session.is_super_session:
CheckEntityPermissionOp(session, entity=entity, action='add')
@@ -56,7 +56,7 @@
except Unauthorized:
entity.clear_local_perm_cache('update')
CheckEntityPermissionOp(session, entity=entity, action='update')
-
+
def before_del_entity(session, eid):
if not session.is_super_session:
eschema = session.repo.schema[session.describe(eid)[0]]
@@ -67,7 +67,7 @@
if rtype in BEFORE_ADD_RELATIONS and not session.is_super_session:
rschema = session.repo.schema[rtype]
rschema.check_perm(session, 'add', fromeid, toeid)
-
+
def after_add_relation(session, fromeid, rtype, toeid):
if not rtype in BEFORE_ADD_RELATIONS and not session.is_super_session:
rschema = session.repo.schema[rtype]
@@ -89,4 +89,4 @@
hm.register_hook(before_add_relation, 'before_add_relation', '')
hm.register_hook(after_add_relation, 'after_add_relation', '')
hm.register_hook(before_del_relation, 'before_delete_relation', '')
-
+
--- a/server/server.py Thu May 14 18:12:45 2009 +0200
+++ b/server/server.py Mon May 18 10:09:06 2009 +0200
@@ -1,7 +1,7 @@
"""Pyro RQL server
: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"
@@ -22,7 +22,7 @@
"""base event"""
# timefunc = staticmethod(localtime)
timefunc = localtime
-
+
def __init__(self, absolute=None, period=None):
# local time tuple
if absolute is None:
@@ -57,10 +57,10 @@
def fire(self, server):
server.repo.shutdown()
server.quiting = True
-
+
class RepositoryServer(object):
-
+
def __init__(self, config, debug=False):
"""make the repository available as a PyRO object"""
self.config = config
@@ -86,7 +86,7 @@
event.update()
except Finished:
self.events.remove(event)
-
+
def run(self, req_timeout=5.0):
"""enter the service loop"""
while self.quiting is None:
@@ -95,7 +95,7 @@
except select.error:
continue
self.trigger_events()
-
+
def quit(self):
"""stop the server"""
self.add_event(QuitEvent())
@@ -105,16 +105,16 @@
necessary
"""
self.daemon = self.repo.pyro_register(host)
-
+
# server utilitities ######################################################
-
+
def install_sig_handlers(self):
"""install signal handlers"""
import signal
self.info('installing signal handlers')
signal.signal(signal.SIGINT, lambda x, y, s=self: s.quit())
signal.signal(signal.SIGTERM, lambda x, y, s=self: s.quit())
-
+
def daemonize(self, pid_file=None):
"""daemonize the process"""
# fork so the parent can exist
--- a/server/sources/ldapuser.py Thu May 14 18:12:45 2009 +0200
+++ b/server/sources/ldapuser.py Mon May 18 10:09:06 2009 +0200
@@ -52,14 +52,14 @@
class LDAPUserSource(AbstractSource):
"""LDAP read-only CWUser source"""
- support_entities = {'CWUser': False}
+ support_entities = {'CWUser': False}
port = None
-
+
cnx_mode = 0
cnx_dn = ''
cnx_pwd = ''
-
+
options = (
('host',
{'type' : 'string',
@@ -119,9 +119,9 @@
'help': 'life time of query cache in minutes (default to two hours).',
'group': 'ldap-source', 'inputlevel': 2,
}),
-
+
)
-
+
def __init__(self, repo, appschema, source_config, *args, **kwargs):
AbstractSource.__init__(self, repo, appschema, source_config,
*args, **kwargs)
@@ -150,8 +150,8 @@
def init(self):
"""method called by the repository once ready to handle request"""
- self.repo.looping_task(self._interval, self.synchronize)
- self.repo.looping_task(self._query_cache.ttl.seconds/10, self._query_cache.clear_expired)
+ self.repo.looping_task(self._interval, self.synchronize)
+ self.repo.looping_task(self._query_cache.ttl.seconds/10, self._query_cache.clear_expired)
def synchronize(self):
"""synchronize content known by this repository with content in the
@@ -169,7 +169,7 @@
for eid, extid in cursor.fetchall():
# if no result found, _search automatically delete entity information
res = self._search(session, extid, BASE)
- if res:
+ if res:
ldapemailaddr = res[0].get(ldap_emailattr)
if ldapemailaddr:
rset = session.execute('EmailAddress X,A WHERE '
@@ -192,13 +192,13 @@
finally:
session.commit()
session.close()
-
+
def get_connection(self):
"""open and return a connection to the source"""
if self._conn is None:
self._connect()
return ConnectionWrapper(self._conn)
-
+
def authenticate(self, session, login, password):
"""return CWUser eid for the given login/password if this account is
defined in this source, else raise `AuthenticationError`
@@ -231,7 +231,7 @@
relname = iter(var.stinfo['relations']).next().r_type
return self.user_rev_attrs.get(relname)
return None
-
+
def prepare_columns(self, mainvars, rqlst):
"""return two list describin how to build the final results
from the result of an ldap search (ie a list of dictionnary)
@@ -270,11 +270,11 @@
# # probably a bug in rql splitting if we arrive here
# raise NotImplementedError
return columns, global_transforms
-
+
def syntax_tree_search(self, session, union,
args=None, cachekey=None, varmap=None, debug=0):
- """return result from this source for a rql query (actually from a rql
- syntax tree and a solution dictionary mapping each used variable to a
+ """return result from this source for a rql query (actually from a rql
+ syntax tree and a solution dictionary mapping each used variable to a
possible type). If cachekey is given, the query necessary to fetch the
results (but not the results themselves) may be cached using this key.
"""
@@ -361,8 +361,8 @@
result = trfunc.apply(result)
#print '--> ldap result', result
return result
-
-
+
+
def _connect(self, userdn=None, userpwd=None):
port, protocol = MODES[self.cnx_mode]
if protocol == 'ldapi':
@@ -444,12 +444,12 @@
result.append(rec_dict)
#print '--->', result
return result
-
+
def before_entity_insertion(self, session, lid, etype, eid):
"""called by the repository when an eid has been attributed for an
entity stored here but the entity has not been inserted in the system
table yet.
-
+
This method must return the an Entity instance representation of this
entity.
"""
@@ -458,7 +458,7 @@
for attr in entity.e_schema.indexable_attributes():
entity[attr] = res[self.user_rev_attrs[attr]]
return entity
-
+
def after_entity_insertion(self, session, dn, entity):
"""called by the repository after an entity stored here has been
inserted in the system table.
@@ -492,13 +492,13 @@
def _insert_email(session, emailaddr, ueid):
session.execute('INSERT EmailAddress X: X address %(addr)s, U primary_email X '
'WHERE U eid %(x)s', {'addr': emailaddr, 'x': ueid}, 'x')
-
+
class GotDN(Exception):
"""exception used when a dn localizing the searched user has been found"""
def __init__(self, dn):
self.dn = dn
-
+
class RQL2LDAPFilter(object):
"""generate an LDAP filter for a rql query"""
def __init__(self, source, session, args=None, mainvars=()):
@@ -510,7 +510,7 @@
args = {}
self._args = args
self.mainvars = mainvars
-
+
def generate(self, selection, mainvarname):
self._filters = res = self._base_filters[:]
self._mainvarname = mainvarname
@@ -527,7 +527,7 @@
if len(res) > 1:
return self._eidfilters, '(&%s)' % ''.join(res)
return self._eidfilters, res[0]
-
+
def visit_and(self, et):
"""generate filter for a AND subtree"""
for c in et.children:
@@ -587,7 +587,7 @@
else:
raise NotImplementedError(relation)
return res
-
+
def _visit_attribute_relation(self, relation):
"""generate filter for an attribute relation"""
lhs, rhs = relation.get_parts()
@@ -623,18 +623,18 @@
def visit_comparison(self, cmp):
"""generate filter for a comparaison"""
- return '%s%s'% (cmp.operator, cmp.children[0].accept(self))
+ return '%s%s'% (cmp.operator, cmp.children[0].accept(self))
def visit_mathexpression(self, mexpr):
"""generate filter for a mathematic expression"""
raise NotImplementedError
-
+
def visit_function(self, function):
"""generate filter name for a function"""
if function.name == 'IN':
return self.visit_in(function)
raise NotImplementedError
-
+
def visit_in(self, function):
grandpapa = function.parent.parent
ldapattr = self._ldap_attrs[grandpapa.r_type]
@@ -649,7 +649,7 @@
else:
part = '(%s=%s)' % (ldapattr, res[0])
return part
-
+
def visit_constant(self, constant):
"""generate filter name for a constant"""
value = constant.value
@@ -667,7 +667,7 @@
else:
value = str(value)
return escape_filter_chars(value)
-
+
def visit_variableref(self, variableref):
"""get the sql name for a variable reference"""
pass
--- a/server/sources/pyrorql.py Thu May 14 18:12:45 2009 +0200
+++ b/server/sources/pyrorql.py Mon May 18 10:09:06 2009 +0200
@@ -342,12 +342,14 @@
cu = session.pool[self.uri]
cu.execute('SET %s WHERE X eid %%(x)s' % ','.join(relations),
kwargs, 'x')
+ self._query_cache.clear()
def delete_entity(self, session, etype, eid):
"""delete an entity from the source"""
cu = session.pool[self.uri]
cu.execute('DELETE %s X WHERE X eid %%(x)s' % etype,
{'x': self.eid2extid(eid, session)}, 'x')
+ self._query_cache.clear()
def add_relation(self, session, subject, rtype, object):
"""add a relation to the source"""
@@ -355,6 +357,7 @@
cu.execute('SET X %s Y WHERE X eid %%(x)s, Y eid %%(y)s' % rtype,
{'x': self.eid2extid(subject, session),
'y': self.eid2extid(object, session)}, ('x', 'y'))
+ self._query_cache.clear()
def delete_relation(self, session, subject, rtype, object):
"""delete a relation from the source"""
@@ -362,6 +365,7 @@
cu.execute('DELETE X %s Y WHERE X eid %%(x)s, Y eid %%(y)s' % rtype,
{'x': self.eid2extid(subject, session),
'y': self.eid2extid(object, session)}, ('x', 'y'))
+ self._query_cache.clear()
class RQL2RQL(object):
--- a/server/sources/rql2sql.py Thu May 14 18:12:45 2009 +0200
+++ b/server/sources/rql2sql.py Mon May 18 10:09:06 2009 +0200
@@ -17,7 +17,7 @@
-> direct join between nonfinal1 and nonfinal2, whatever X,Y, Z (unless
inlined...)
-
+
NOT IMPLEMENTED (and quite hard to implement)
Potential optimization information is collected by the querier, sql generation
@@ -41,7 +41,7 @@
from cubicweb.server.sqlutils import SQL_PREFIX
from cubicweb.server.utils import cleanup_solutions
-def _new_var(select, varname):
+def _new_var(select, varname):
newvar = select.get_variable(varname)
if not 'relations' in newvar.stinfo:
# not yet initialized
@@ -61,7 +61,7 @@
_fill_to_wrap_rel(vref.variable, newselect, towrap, schema)
elif rschema.is_final():
towrap.add( (var, rel) )
-
+
def rewrite_unstable_outer_join(select, solutions, unstable, schema):
"""if some optional variables are unstable, they should be selected in a
subquery. This function check this and rewrite the rql syntax tree if
@@ -104,7 +104,7 @@
var.stinfo['relations'].add(newrel)
var.stinfo['rhsrelations'].add(newrel)
if rel.optional in ('right', 'both'):
- var.stinfo['optrelations'].add(newrel)
+ var.stinfo['optrelations'].add(newrel)
# extract subquery solutions
solutions = [sol.copy() for sol in solutions]
cleanup_solutions(newselect, solutions)
@@ -205,7 +205,7 @@
for vref in term.iget_nodes(VariableRef):
if not vref in groups:
groups.append(vref)
-
+
def fix_selection(rqlst, selectedidx, needwrap, sorts, groups, having):
if sorts:
sort_term_selection(sorts, selectedidx, rqlst, not needwrap and groups)
@@ -230,7 +230,7 @@
self.existssols = existssols
self.unstablevars = unstablevars
self.subtables = {}
-
+
def reset(self, solution):
"""reset some visit variables"""
self.solution = solution
@@ -246,11 +246,11 @@
self.aliases = {}
self.restrictions = []
self._restr_stack = []
-
+
def add_restriction(self, restr):
if restr:
self.restrictions.append(restr)
-
+
def iter_exists_sols(self, exists):
if not exists in self.existssols:
yield 1
@@ -286,8 +286,8 @@
restrictions = self.restrictions
self.restrictions = self._restr_stack.pop()
return restrictions, self.actual_tables.pop()
-
-
+
+
class SQLGenerator(object):
"""
generation of SQL from the fully expanded RQL syntax tree
@@ -295,13 +295,13 @@
Groups and sort are not handled here since they should not be handled at
this level (see cubicweb.server.querier)
-
+
we should not have errors here !
WARNING: a CubicWebSQLGenerator instance is not thread safe, but generate is
protected by a lock
"""
-
+
def __init__(self, schema, dbms_helper, dbencoding='UTF-8'):
self.schema = schema
self.dbms_helper = dbms_helper
@@ -312,7 +312,7 @@
if not self.dbms_helper.union_parentheses_support:
self.union_sql = self.noparen_union_sql
self._lock = threading.Lock()
-
+
def generate(self, union, args=None, varmap=None):
"""return SQL queries and a variable dictionnary from a RQL syntax tree
@@ -355,7 +355,7 @@
sqls = (self.select_sql(select, needalias)
for i, select in enumerate(union.children))
return '\nUNION ALL\n'.join(sqls)
-
+
def select_sql(self, select, needalias=False):
"""return SQL queries and a variable dictionnary from a RQL syntax tree
@@ -388,7 +388,7 @@
# query will be necessary
if groups or select.has_aggregat:
select.select_only_variables()
- needwrap = True
+ needwrap = True
else:
existssols, unstable = {}, ()
state = StateInfo(existssols, unstable)
@@ -441,7 +441,7 @@
sql += '\nHAVING %s' % having
# sort
if sorts:
- sql += '\nORDER BY %s' % ','.join(self._sortterm_sql(sortterm,
+ sql += '\nORDER BY %s' % ','.join(self._sortterm_sql(sortterm,
fselectidx)
for sortterm in sorts)
if fneedwrap:
@@ -497,7 +497,7 @@
return '\nUNION\n'.join(sqls)
else:
return '\nUNION ALL\n'.join(sqls)
-
+
def _selection_sql(self, selected, distinct, needaliasing=False):
clause = []
for term in selected:
@@ -546,7 +546,7 @@
return '(%s)' % ' OR '.join(res)
return res[0]
return ''
-
+
def visit_not(self, node):
self._state.push_scope()
csql = node.children[0].accept(self)
@@ -581,7 +581,7 @@
if not sqls:
return ''
return 'EXISTS(%s)' % ' UNION '.join(sqls)
-
+
def _visit_exists(self, exists):
self._state.push_scope()
restriction = exists.children[0].accept(self)
@@ -593,12 +593,12 @@
return ''
if not tables:
# XXX could leave surrounding EXISTS() in this case no?
- sql = 'SELECT 1 WHERE %s' % restriction
+ sql = 'SELECT 1 WHERE %s' % restriction
else:
sql = 'SELECT 1 FROM %s WHERE %s' % (', '.join(tables), restriction)
return sql
-
+
def visit_relation(self, relation):
"""generate SQL for a relation"""
rtype = relation.r_type
@@ -691,7 +691,7 @@
extrajoin = self._extra_join_sql(relation, '%s.%s' % (rid, relfield), termvar)
if extrajoin:
yield extrajoin
-
+
def _visit_relation(self, relation, rschema):
"""generate SQL for a relation
@@ -718,10 +718,10 @@
"""
left outer join syntax (optional=='right'):
X relation Y?
-
+
right outer join syntax (optional=='left'):
X? relation Y
-
+
full outer join syntaxes (optional=='both'):
X? relation Y?
@@ -834,7 +834,7 @@
lhssql = self._inlined_var_sql(relation.children[0].variable,
relation.r_type)
return '%s%s' % (lhssql, relation.children[1].accept(self, contextrels))
-
+
def _visit_attribute_relation(self, relation):
"""generate SQL for an attribute relation"""
lhs, rhs = relation.get_parts()
@@ -897,7 +897,7 @@
not_ = False
return self.dbms_helper.fti_restriction_sql(alias, const.eval(self._args),
jointo, not_) + restriction
-
+
def visit_comparison(self, cmp, contextrels=None):
"""generate SQL for a comparaison"""
if len(cmp.children) == 2:
@@ -918,7 +918,7 @@
return '%s%s'% (operator, rhs.accept(self, contextrels))
return '%s%s%s'% (lhs.accept(self, contextrels), operator,
rhs.accept(self, contextrels))
-
+
def visit_mathexpression(self, mexpr, contextrels=None):
"""generate SQL for a mathematic expression"""
lhs, rhs = mexpr.get_parts()
@@ -931,11 +931,11 @@
pass
return '(%s %s %s)'% (lhs.accept(self, contextrels), operator,
rhs.accept(self, contextrels))
-
+
def visit_function(self, func, contextrels=None):
"""generate SQL name for a function"""
# function_description will check function is supported by the backend
- sqlname = self.dbms_helper.func_sqlname(func.name)
+ sqlname = self.dbms_helper.func_sqlname(func.name)
return '%s(%s)' % (sqlname, ', '.join(c.accept(self, contextrels)
for c in func.children))
@@ -963,7 +963,7 @@
value = value.encode(self.dbencoding)
self._query_attrs[_id] = value
return '%%(%s)s' % _id
-
+
def visit_variableref(self, variableref, contextrels=None):
"""get the sql name for a variable reference"""
# use accept, .variable may be a variable or a columnalias
@@ -979,7 +979,7 @@
self.add_table(table)
return sql
return colalias._q_sql
-
+
def visit_variable(self, variable, contextrels=None):
"""get the table name and sql string for a variable"""
if contextrels is None and variable.name in self._state.done:
@@ -989,7 +989,7 @@
self._state.done.add(variable.name)
vtablename = None
if contextrels is None and variable.name in self._varmap:
- sql, vtablename = self._var_info(variable)
+ sql, vtablename = self._var_info(variable)
elif variable.stinfo['attrvar']:
# attribute variable (systematically used in rhs of final
# relation(s)), get table name and sql from any rhs relation
@@ -1043,7 +1043,7 @@
# so nothing to return here
pass
return ''
-
+
def _var_info(self, var):
# if current var or one of its attribute is selected , it *must*
# appear in the toplevel's FROM even if we're currently visiting
@@ -1067,7 +1067,7 @@
sql = '%s.%seid' % (table, SQL_PREFIX)
self.add_table('%s%s AS %s' % (SQL_PREFIX, etype, table), table, scope=scope)
return sql, table
-
+
def _inlined_var_sql(self, var, rtype):
try:
sql = self._varmap['%s.%s' % (var.name, rtype)]
@@ -1077,14 +1077,14 @@
sql = '%s.%s%s' % (self._var_table(var), SQL_PREFIX, rtype)
#self._state.done.add(var.name)
return sql
-
+
def _linked_var_sql(self, variable, contextrels=None):
if contextrels is None:
try:
- return self._varmap[variable.name]
+ return self._varmap[variable.name]
except KeyError:
pass
- rel = (contextrels and contextrels.get(variable.name) or
+ rel = (contextrels and contextrels.get(variable.name) or
variable.stinfo.get('principal') or
iter(variable.stinfo['rhsrelations']).next())
linkedvar = rel.children[0].variable
@@ -1096,7 +1096,7 @@
try:
sql = self._varmap['%s.%s' % (linkedvar.name, rel.r_type)]
except KeyError:
- linkedvar.accept(self)
+ linkedvar.accept(self)
sql = '%s.%s%s' % (linkedvar._q_sqltable, SQL_PREFIX, rel.r_type)
return sql
@@ -1107,7 +1107,7 @@
self._state.count += 1
self.add_table('%s AS %s' % (tablename, alias), alias)
return alias
-
+
def add_table(self, table, key=None, scope=-1):
if key is None:
key = table
@@ -1115,7 +1115,7 @@
return
self._state.tables[key] = (len(self._state.actual_tables) - 1, table)
self._state.actual_tables[scope].append(table)
-
+
def replace_tables_by_outer_join(self, substitute, lefttable, *tables):
for table in tables:
try:
@@ -1160,8 +1160,8 @@
for table, outerexpr in self._state.outer_tables.iteritems():
if outerexpr == oldalias:
self._state.outer_tables[table] = newalias
- self._state.outer_tables[table] = newalias
-
+ self._state.outer_tables[table] = newalias
+
def _var_table(self, var):
var.accept(self)#.visit_variable(var)
return var._q_sqltable
@@ -1173,7 +1173,7 @@
assert not self.schema.rschema(relation.r_type).is_final(), relation.r_type
rid = 'rel_%s%s' % (relation.r_type, self._state.count)
# relation's table is belonging to the root scope if it is the principal
- # table of one of it's variable and if that variable belong's to parent
+ # table of one of it's variable and if that variable belong's to parent
# scope
for varref in relation.iget_nodes(VariableRef):
var = varref.variable
@@ -1192,7 +1192,7 @@
relation._q_sqltable = rid
self._state.done.add(relation)
return rid
-
+
def _fti_table(self, relation):
if relation in self._state.done:
try:
@@ -1203,7 +1203,7 @@
alias = self.alias_and_add_table(self.dbms_helper.fti_table)
relation._q_sqltable = alias
return alias
-
+
def _varmap_table_scope(self, select, table):
"""since a varmap table may be used for multiple variable, its scope is
the most outer scope of each variables
--- a/server/ssplanner.py Thu May 14 18:12:45 2009 +0200
+++ b/server/ssplanner.py Mon May 18 10:09:06 2009 +0200
@@ -78,35 +78,35 @@
rel = newroot.add_type_restriction(var, possibletypes)
stinfo['typerels'] = frozenset((rel,))
stinfo['possibletypes'] = possibletypes
-
+
class SSPlanner(object):
"""SingleSourcePlanner: build execution plan for rql queries
optimized for single source repositories
"""
-
+
def __init__(self, schema, rqlhelper):
self.schema = schema
self.rqlhelper = rqlhelper
def build_plan(self, plan):
"""build an execution plan from a RQL query
-
+
do nothing here, dispatch according to the statement type
"""
build_plan = getattr(self, 'build_%s_plan' % plan.rqlst.TYPE)
for step in build_plan(plan, plan.rqlst):
plan.add_step(step)
-
+
def build_select_plan(self, plan, rqlst):
"""build execution plan for a SELECT RQL query. Suppose only one source
is available and so avoid work need for query decomposition among sources
-
+
the rqlst should not be tagged at this point.
"""
plan.preprocess(rqlst)
return (OneFetchStep(plan, rqlst, plan.session.repo.sources),)
-
+
def build_insert_plan(self, plan, rqlst):
"""get an execution plan from an INSERT RQL query"""
# each variable in main variables is a new entity to insert
@@ -123,7 +123,7 @@
step.children += self._compute_relation_steps(plan, rqlst.solutions,
rqlst.where, to_select)
return (step,)
-
+
def _compute_relation_steps(self, plan, solutions, restriction, to_select):
"""handle the selection of relations for an insert query"""
for edef, rdefs in to_select.items():
@@ -146,7 +146,7 @@
step = RelationsStep(plan, edef, rdefs)
step.children += self._select_plan(plan, select, solutions)
yield step
-
+
def build_delete_plan(self, plan, rqlst):
"""get an execution plan from a DELETE RQL query"""
# build a select query to fetch entities to delete
@@ -174,7 +174,7 @@
if etype != 'Any':
select.add_type_restriction(varref.variable, etype)
return self._select_plan(plan, select, solutions)
-
+
def _sel_relation_steps(self, plan, solutions, restriction, relation):
"""handle the selection of relations for a delete query"""
select = Select()
@@ -185,7 +185,7 @@
if restriction is not None:
select.add_restriction(restriction.copy(select))
return self._select_plan(plan, select, solutions)
-
+
def build_set_plan(self, plan, rqlst):
"""get an execution plan from an SET RQL query"""
select = Select()
@@ -222,12 +222,12 @@
return (step,)
# internal methods ########################################################
-
+
def _select_plan(self, plan, select, solutions):
union = Union()
union.append(select)
select.clean_solutions(solutions)
- add_types_restriction(self.schema, select)
+ add_types_restriction(self.schema, select)
self.rqlhelper.annotate(union)
return self.build_select_plan(plan, union)
@@ -260,35 +260,35 @@
self.limit = limit
self.offset = offset or None
-
+
class Step(object):
"""base abstract class for execution step"""
def __init__(self, plan):
self.plan = plan
self.children = []
-
+
def execute_child(self):
assert len(self.children) == 1
return self.children[0].execute()
-
+
def execute_children(self):
for step in self.children:
step.execute()
-
+
def execute(self):
"""execute this step and store partial (eg this step) results"""
raise NotImplementedError()
-
+
def mytest_repr(self):
"""return a representation of this step suitable for test"""
return (self.__class__.__name__,)
-
+
def test_repr(self):
"""return a representation of this step suitable for test"""
return self.mytest_repr() + (
[step.test_repr() for step in self.children],)
-
+
class OneFetchStep(LimitOffsetMixIn, Step):
"""step consisting in fetching data from sources and directly returning
results
@@ -305,7 +305,7 @@
for select in self.union.children:
select.limit = limit
select.offset = offset
-
+
def execute(self):
"""call .syntax_tree_search with the given syntax tree on each
source for each solution
@@ -375,22 +375,22 @@
relations values comes from the latest result, with one columns for
each relation defined in self.r_defs
-
+
for one entity definition, we'll construct N entity, where N is the
number of the latest result
"""
-
+
FINAL = 0
RELATION = 1
REVERSE_RELATION = 2
-
+
def __init__(self, plan, e_def, r_defs):
Step.__init__(self, plan)
# partial entity definition to expand
self.e_def = e_def
# definition of relations to complete
self.r_defs = r_defs
-
+
def execute(self):
"""execute this step"""
base_e_def = self.e_def
@@ -415,7 +415,7 @@
class InsertStep(Step):
"""step consisting in inserting new entities / relations"""
-
+
def execute(self):
"""execute this step"""
for step in self.children:
@@ -444,34 +444,34 @@
pending |= actual
for eid in actual:
delete(session, eid)
-
-
+
+
class DeleteRelationsStep(Step):
"""step consisting in deleting relations"""
def __init__(self, plan, rtype):
Step.__init__(self, plan)
self.rtype = rtype
-
+
def execute(self):
"""execute this step"""
session = self.plan.session
delete = session.repo.glob_delete_relation
for subj, obj in self.execute_child():
delete(session, subj, self.rtype, obj)
-
+
class UpdateStep(Step):
"""step consisting in updating entities / adding relations from relations
definitions and from results fetched in previous step
"""
-
+
def __init__(self, plan, attribute_relations, relations, selected_index):
Step.__init__(self, plan)
self.attribute_relations = attribute_relations
self.relations = relations
self.selected_index = selected_index
-
+
def execute(self):
"""execute this step"""
plan = self.plan
--- a/server/test/data/migrschema/Affaire.py Thu May 14 18:12:45 2009 +0200
+++ b/server/test/data/migrschema/Affaire.py Mon May 18 10:09:06 2009 +0200
@@ -6,7 +6,7 @@
'update': ('managers', 'owners', ERQLExpression('X concerne S, S owned_by U')),
'delete': ('managers', 'owners', ERQLExpression('X concerne S, S owned_by U')),
}
-
+
ref = String(fulltextindexed=True, indexed=True,
constraints=[SizeConstraint(16)])
sujet = String(fulltextindexed=True,
@@ -18,4 +18,4 @@
'add': ('managers', RRQLExpression('U has_update_permission S')),
'delete': ('managers', RRQLExpression('O owned_by U')),
}
-
+
--- a/server/test/data/migrschema/Folder2.py Thu May 14 18:12:45 2009 +0200
+++ b/server/test/data/migrschema/Folder2.py Mon May 18 10:09:06 2009 +0200
@@ -22,4 +22,4 @@
# is_about has been renamed into filed_under
#//* is_about Folder
#* filed_under Folder
-
+
--- a/server/test/data/migrschema/Note.py Thu May 14 18:12:45 2009 +0200
+++ b/server/test/data/migrschema/Note.py Mon May 18 10:09:06 2009 +0200
@@ -1,13 +1,13 @@
class Note(EntityType):
-
+
permissions = {'read': ('managers', 'users', 'guests',),
'update': ('managers', 'owners',),
'delete': ('managers', ),
- 'add': ('managers',
+ 'add': ('managers',
ERQLExpression('X ecrit_part PE, U in_group G, '
'PE require_permission P, P name "add_note", '
'P require_group G'),)}
-
+
date = Datetime()
type = String(maxsize=1)
whatever = Int()
@@ -19,7 +19,7 @@
class ecrit_par(RelationType):
permissions = {'read': ('managers', 'users', 'guests',),
'delete': ('managers', ),
- 'add': ('managers',
+ 'add': ('managers',
RRQLExpression('O require_permission P, P name "add_note", '
'U in_group G, P require_group G'),)
}
--- a/server/test/data/schema/Affaire.py Thu May 14 18:12:45 2009 +0200
+++ b/server/test/data/schema/Affaire.py Mon May 18 10:09:06 2009 +0200
@@ -2,13 +2,13 @@
class Affaire(WorkflowableEntityType):
permissions = {
- 'read': ('managers',
+ 'read': ('managers',
ERQLExpression('X owned_by U'), ERQLExpression('X concerne S?, S owned_by U')),
'add': ('managers', ERQLExpression('X concerne S, S owned_by U')),
'update': ('managers', 'owners', ERQLExpression('X in_state S, S name in ("pitetre", "en cours")')),
'delete': ('managers', 'owners', ERQLExpression('X concerne S, S owned_by U')),
}
-
+
ref = String(fulltextindexed=True, indexed=True,
constraints=[SizeConstraint(16)])
sujet = String(fulltextindexed=True,
@@ -23,12 +23,12 @@
depends_on = SubjectRelation('Affaire')
require_permission = SubjectRelation('CWPermission')
-
+
class concerne(RelationType):
permissions = {
'read': ('managers', 'users', 'guests'),
'add': ('managers', RRQLExpression('U has_update_permission S')),
'delete': ('managers', RRQLExpression('O owned_by U')),
}
-
+
--- a/server/test/data/schema/Societe.py Thu May 14 18:12:45 2009 +0200
+++ b/server/test/data/schema/Societe.py Mon May 18 10:09:06 2009 +0200
@@ -5,10 +5,10 @@
'delete': ('managers', 'owners', ERQLExpression('U login L, X nom L')),
'add': ('managers', 'users',)
}
-
+
nom = String(maxsize=64, fulltextindexed=True)
web = String(maxsize=128)
- type = String(maxsize=128) # attribute in common with Note
+ type = String(maxsize=128) # attribute in common with Note
tel = Int()
fax = Int()
rncs = String(maxsize=128)
--- a/server/test/data/schema/note.py Thu May 14 18:12:45 2009 +0200
+++ b/server/test/data/schema/note.py Mon May 18 10:09:06 2009 +0200
@@ -11,7 +11,7 @@
object = 'State'
cardinality = '1*'
constraints=[RQLConstraint('S is ET, O state_of ET')]
-
+
class wf_info_for(RelationDefinition):
subject = 'TrInfo'
object = 'Note'
--- a/server/test/unittest_checkintegrity.py Thu May 14 18:12:45 2009 +0200
+++ b/server/test/unittest_checkintegrity.py Mon May 18 10:09:06 2009 +0200
@@ -17,6 +17,6 @@
finally:
sys.stderr = sys.__stderr__
sys.stdout = sys.__stdout__
-
+
if __name__ == '__main__':
unittest_main()
--- a/server/test/unittest_config.py Thu May 14 18:12:45 2009 +0200
+++ b/server/test/unittest_config.py Mon May 18 10:09:06 2009 +0200
@@ -13,7 +13,7 @@
@staticmethod
def registry_objects(registry):
return []
-
+
cfg1 = TestServerConfiguration('data/config1')
cfg1.bootstrap_cubes()
cfg2 = TestServerConfiguration('data/config2')
@@ -21,7 +21,7 @@
self.failIf(cfg1.load_hooks(vreg) is cfg2.load_hooks(vreg))
self.failUnless('after_add_relation' in cfg1.load_hooks(vreg))
self.failUnless('after_delete_relation' in cfg2.load_hooks(vreg))
-
+
if __name__ == '__main__':
unittest_main()
--- a/server/test/unittest_hooksmanager.py Thu May 14 18:12:45 2009 +0200
+++ b/server/test/unittest_hooksmanager.py Mon May 18 10:09:06 2009 +0200
@@ -16,7 +16,7 @@
class HooksManagerTC(TestCase):
args = (None,)
kwargs = {'a': 1}
-
+
def setUp(self):
""" called before each test from this class """
self.o = HooksManager(schema)
@@ -32,22 +32,22 @@
self.o.register_hook, self._hook, 'server_startup', 'CWEType')
self.assertRaises(AssertionError,
self.o.register_hook, self._hook, 'server_shutdown', 'CWEType')
-
+
def test_register_hook1(self):
self.o.register_hook(self._hook, 'before_add_entity')
self.o.register_hook(self._hook, 'before_delete_entity', 'Personne')
self._test_called_hooks()
-
+
def test_register_hook2(self):
self.o.register_hook(self._hook, 'before_add_entity', '')
self.o.register_hook(self._hook, 'before_delete_entity', 'Personne')
self._test_called_hooks()
-
+
def test_register_hook3(self):
self.o.register_hook(self._hook, 'before_add_entity', None)
self.o.register_hook(self._hook, 'before_delete_entity', 'Personne')
self._test_called_hooks()
-
+
def test_register_hooks(self):
self.o.register_hooks({'before_add_entity' : {'': [self._hook]},
'before_delete_entity' : {'Personne': [self._hook]},
@@ -62,7 +62,7 @@
self.o.unregister_hook(self._hook, 'after_delete_entity', 'Personne')
# no hook should be called there
self.o.call_hooks('after_delete_entity', 'Personne')
-
+
def _test_called_hooks(self):
self.assertRaises(HookCalled,
@@ -102,9 +102,9 @@
'before_add_relation', 'concerne')
self.assertEquals(self.called, [])
self.o.call_hooks('before_add_relation', 'concerne', 'USER',
- 1, 'concerne', 2)
+ 1, 'concerne', 2)
self.assertEquals(self.called, [(1, 'concerne', 2)])
-
+
def test_after_add_relation(self):
"""make sure after_xxx_relation hooks are deferred"""
self.o.register_hook(self._after_relation_hook,
@@ -115,14 +115,14 @@
self.o.call_hooks('after_add_relation', 'concerne', 'USER',
3, 'concerne', 4)
self.assertEquals(self.called, [(1, 'concerne', 2), (3, 'concerne', 4)])
-
+
def test_before_delete_relation(self):
"""make sure before_xxx_relation hooks are called directly"""
self.o.register_hook(self._before_relation_hook,
'before_delete_relation', 'concerne')
self.assertEquals(self.called, [])
self.o.call_hooks('before_delete_relation', 'concerne', 'USER',
- 1, 'concerne', 2)
+ 1, 'concerne', 2)
self.assertEquals(self.called, [(1, 'concerne', 2)])
def test_after_delete_relation(self):
@@ -166,7 +166,7 @@
schema = schema # set for actual hooks at registration time
events = ('whatever', 'another')
accepts = ('Societe', 'Division')
-
+
class HookTC(RepositoryBasedTC):
def test_inheritance(self):
self.assertEquals(list(MyHook.register_to()),
--- a/server/test/unittest_ldapuser.py Thu May 14 18:12:45 2009 +0200
+++ b/server/test/unittest_ldapuser.py Mon May 18 10:09:06 2009 +0200
@@ -34,14 +34,14 @@
class LDAPUserSourceTC(RepositoryBasedTC):
repo, cnx = repo, cnx
-
+
def patch_authenticate(self):
self._orig_authenticate = LDAPUserSource.authenticate
LDAPUserSource.authenticate = nopwd_authenticate
def setUp(self):
self._prepare()
- # XXX: need this first query else we get 'database is locked' from
+ # XXX: need this first query else we get 'database is locked' from
# sqlite since it doesn't support multiple connections on the same
# database
# so doing, ldap inserted users don't get removed between each test
@@ -50,21 +50,21 @@
# check we get some users from ldap
self.assert_(len(rset) > 1)
self.maxeid = self.execute('Any MAX(X)')[0][0]
-
+
def tearDown(self):
if hasattr(self, '_orig_authenticate'):
LDAPUserSource.authenticate = self._orig_authenticate
RepositoryBasedTC.tearDown(self)
-
+
def test_authenticate(self):
source = self.repo.sources_by_uri['ldapuser']
self.assertRaises(AuthenticationError,
source.authenticate, self.session, 'toto', 'toto')
-
+
def test_synchronize(self):
source = self.repo.sources_by_uri['ldapuser']
source.synchronize()
-
+
def test_base(self):
# check a known one
e = self.execute('CWUser X WHERE X login "syt"').get_entity(0, 0)
@@ -139,7 +139,7 @@
def test_or(self):
rset = self.execute('DISTINCT Any X WHERE X login "syt" OR (X in_group G, G name "managers")')
self.assertEquals(len(rset), 2, rset.rows) # syt + admin
-
+
def test_nonregr_set_owned_by(self):
# test that when a user coming from ldap is triggering a transition
# the related TrInfo has correct owner information
@@ -175,7 +175,7 @@
def test_multiple_entities_from_different_sources(self):
self.create_user('cochon')
self.failUnless(self.execute('Any X,Y WHERE X login "syt", Y login "cochon"'))
-
+
def test_exists1(self):
self.add_entity('CWGroup', name=u'bougloup1')
self.add_entity('CWGroup', name=u'bougloup2')
@@ -241,11 +241,11 @@
self.assertEquals(sorted(rset.rows), [['guests', 'cochon'],
['users', 'cochon'],
['users', 'syt']])
-
+
def test_cd_restriction(self):
rset = self.execute('CWUser X WHERE X creation_date > "2009-02-01"')
self.assertEquals(len(rset), 2) # admin/anon but no ldap user since it doesn't support creation_date
-
+
def test_union(self):
afeids = self.execute('State X')
ueids = self.execute('CWUser X')
@@ -257,21 +257,21 @@
self.create_user('iaminguestsgrouponly', groups=('guests',))
cnx = self.login('iaminguestsgrouponly')
return cnx.cursor()
-
+
def test_security1(self):
cu = self._init_security_test()
rset = cu.execute('Any X WHERE X login "syt"')
self.assertEquals(rset.rows, [])
rset = cu.execute('Any X WHERE X login "iaminguestsgrouponly"')
self.assertEquals(len(rset.rows), 1)
-
+
def test_security2(self):
cu = self._init_security_test()
rset = cu.execute('Any X WHERE X has_text "syt"')
self.assertEquals(rset.rows, [])
rset = cu.execute('Any X WHERE X has_text "iaminguestsgrouponly"')
self.assertEquals(len(rset.rows), 1)
-
+
def test_security3(self):
cu = self._init_security_test()
rset = cu.execute('Any F WHERE X has_text "syt", X firstname F')
@@ -298,13 +298,13 @@
emaileid = self.execute('INSERT EmailAddress X: X address "toto@logilab.org"')[0][0]
self.execute('Any X,AA WHERE X use_email Y, Y eid %(x)s, X modification_date AA',
{'x': emaileid})
-
+
def test_nonregr5(self):
# original jpl query:
# Any X, NOW - CD, P WHERE P is Project, U interested_in P, U is CWUser, U login "sthenault", X concerns P, X creation_date CD ORDERBY CD DESC LIMIT 5
rql = 'Any X, NOW - CD, P ORDERBY CD DESC LIMIT 5 WHERE P bookmarked_by U, U login "%s", P is X, X creation_date CD' % self.session.user.login
self.execute(rql, )#{'x': })
-
+
def test_nonregr6(self):
self.execute('Any B,U,UL GROUPBY B,U,UL WHERE B created_by U?, B is File '
'WITH U,UL BEING (Any U,UL WHERE ME eid %(x)s, (EXISTS(U identity ME) '
@@ -350,33 +350,33 @@
class RQL2LDAPFilterTC(RQLGeneratorTC):
schema = repo.schema
-
+
def setUp(self):
RQLGeneratorTC.setUp(self)
ldapsource = repo.sources[-1]
self.pool = repo._get_pool()
session = mock_object(pool=self.pool)
self.o = RQL2LDAPFilter(ldapsource, session)
-
+
def tearDown(self):
repo._free_pool(self.pool)
RQLGeneratorTC.tearDown(self)
-
+
def test_base(self):
rqlst = self._prepare('CWUser X WHERE X login "toto"').children[0]
self.assertEquals(self.o.generate(rqlst, 'X')[1],
'(&(objectClass=top)(objectClass=posixAccount)(uid=toto))')
-
+
def test_kwargs(self):
rqlst = self._prepare('CWUser X WHERE X login %(x)s').children[0]
self.o._args = {'x': "toto"}
self.assertEquals(self.o.generate(rqlst, 'X')[1],
'(&(objectClass=top)(objectClass=posixAccount)(uid=toto))')
-
+
def test_get_attr(self):
rqlst = self._prepare('Any X WHERE E firstname X, E eid 12').children[0]
self.assertRaises(UnknownEid, self.o.generate, rqlst, 'E')
-
-
+
+
if __name__ == '__main__':
unittest_main()
--- a/server/test/unittest_rqlannotation.py Thu May 14 18:12:45 2009 +0200
+++ b/server/test/unittest_rqlannotation.py Mon May 18 10:09:06 2009 +0200
@@ -9,15 +9,15 @@
class SQLGenAnnotatorTC(BaseQuerierTC):
repo = repo
-
+
def get_max_eid(self):
# no need for cleanup here
return None
def cleanup(self):
# no need for cleanup here
pass
-
- def test_0_1(self):
+
+ def test_0_1(self):
rqlst = self._prepare('Any SEN,RN,OEN WHERE X from_entity SE, SE eid 44, X relation_type R, R eid 139, X to_entity OE, OE eid 42, R name RN, SE name SEN, OE name OEN')
self.assertEquals(rqlst.defined_vars['SE']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['OE']._q_invariant, False)
@@ -25,13 +25,13 @@
self.assertEquals(rqlst.defined_vars['SE'].stinfo['attrvar'], None)
self.assertEquals(rqlst.defined_vars['OE'].stinfo['attrvar'], None)
self.assertEquals(rqlst.defined_vars['R'].stinfo['attrvar'], None)
-
- def test_0_2(self):
+
+ def test_0_2(self):
rqlst = self._prepare('Any O WHERE NOT S ecrit_par O, S eid 1, S inline1 P, O inline2 P')
self.assertEquals(rqlst.defined_vars['P']._q_invariant, True)
self.assertEquals(rqlst.defined_vars['O'].stinfo['attrvar'], None)
- def test_0_4(self):
+ def test_0_4(self):
rqlst = self._prepare('Any A,B,C WHERE A eid 12,A comment B, A ?wf_info_for C')
self.assertEquals(rqlst.defined_vars['A']._q_invariant, False)
self.assert_(rqlst.defined_vars['B'].stinfo['attrvar'])
@@ -40,28 +40,28 @@
{'A': 'TrInfo', 'B': 'String', 'C': 'CWUser'},
{'A': 'TrInfo', 'B': 'String', 'C': 'Note'}])
- def test_0_5(self):
+ def test_0_5(self):
rqlst = self._prepare('Any P WHERE N ecrit_par P, N eid 0')
self.assertEquals(rqlst.defined_vars['N']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['P']._q_invariant, True)
- def test_0_6(self):
+ def test_0_6(self):
rqlst = self._prepare('Any P WHERE NOT N ecrit_par P, N eid 512')
self.assertEquals(rqlst.defined_vars['P']._q_invariant, False)
- def test_0_7(self):
+ def test_0_7(self):
rqlst = self._prepare('Personne X,Y where X nom NX, Y nom NX, X eid XE, not Y eid XE')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
self.assert_(rqlst.defined_vars['XE'].stinfo['attrvar'])
- def test_0_8(self):
+ def test_0_8(self):
rqlst = self._prepare('Any P WHERE X eid 0, NOT X connait P')
self.assertEquals(rqlst.defined_vars['P']._q_invariant, False)
#self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
self.assertEquals(len(rqlst.solutions), 1, rqlst.solutions)
- def test_0_10(self):
+ def test_0_10(self):
rqlst = self._prepare('Any X WHERE X concerne Y, Y is Note')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
@@ -71,78 +71,78 @@
self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True)
- def test_0_12(self):
+ def test_0_12(self):
rqlst = self._prepare('Personne P WHERE P concerne A, A concerne S, S nom "Logilab"')
self.assertEquals(rqlst.defined_vars['P']._q_invariant, True)
self.assertEquals(rqlst.defined_vars['A']._q_invariant, True)
self.assertEquals(rqlst.defined_vars['S']._q_invariant, False)
-
+
def test_1_0(self):
rqlst = self._prepare('Any X,Y WHERE X created_by Y, X eid 5, NOT Y eid 6')
self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True)
-
+
def test_1_1(self):
rqlst = self._prepare('Any X,Y WHERE X created_by Y, X eid 5, NOT Y eid IN (6,7)')
self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True)
-
+
def test_2(self):
rqlst = self._prepare('Any X WHERE X identity Y, Y eid 1')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
-
+
def test_7(self):
rqlst = self._prepare('Personne X,Y where X nom NX, Y nom NX, X eid XE, not Y eid XE')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
-
+
def test_optional_inlined(self):
rqlst = self._prepare('Any X,S where X from_state S?')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['S']._q_invariant, True)
-
+
def test_optional_inlined_2(self):
rqlst = self._prepare('Any N,A WHERE N? inline1 A')
self.assertEquals(rqlst.defined_vars['N']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['A']._q_invariant, False)
-
+
def test_optional_1(self):
rqlst = self._prepare('Any X,S WHERE X travaille S?')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['S']._q_invariant, True)
-
+
def test_greater_eid(self):
rqlst = self._prepare('Any X WHERE X eid > 5')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
-
+
def test_greater_eid_typed(self):
rqlst = self._prepare('Any X WHERE X eid > 5, X is Note')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
-
+
def test_max_eid(self):
rqlst = self._prepare('Any MAX(X)')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
-
+
def test_max_eid_typed(self):
rqlst = self._prepare('Any MAX(X) WHERE X is Note')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
-
+
def test_all_entities(self):
rqlst = self._prepare('Any X')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
-
+
def test_all_typed_entity(self):
rqlst = self._prepare('Any X WHERE X is Note')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
-
+
def test_has_text_1(self):
rqlst = self._prepare('Any X WHERE X has_text "toto tata"')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
self.assertEquals(rqlst.defined_vars['X'].stinfo['principal'].r_type, 'has_text')
-
+
def test_has_text_2(self):
rqlst = self._prepare('Any X WHERE X is Personne, X has_text "coucou"')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
self.assertEquals(rqlst.defined_vars['X'].stinfo['principal'].r_type, 'has_text')
-
+
def test_not_relation_1(self):
# P can't be invariant since deambiguification caused by "NOT X require_permission P"
# is not considered by generated sql (NOT EXISTS(...))
@@ -150,31 +150,31 @@
self.assertEquals(rqlst.defined_vars['P']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['G']._q_invariant, True)
self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
-
+
def test_not_relation_2(self):
rqlst = self._prepare('TrInfo X WHERE X eid 2, NOT X from_state Y, Y is State')
self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True)
self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
-
+
def test_not_relation_3(self):
rqlst = self._prepare('Any X, Y WHERE X eid 1, Y eid in (2, 3)')
self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
-
+
def test_not_relation_4_1(self):
rqlst = self._prepare('Note X WHERE NOT Y evaluee X')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True)
-
+
def test_not_relation_4_2(self):
rqlst = self._prepare('Any X WHERE NOT Y evaluee X')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True)
-
+
def test_not_relation_4_3(self):
rqlst = self._prepare('Any Y WHERE NOT Y evaluee X')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
-
+
def test_not_relation_4_4(self):
rqlst = self._prepare('Any X WHERE NOT Y evaluee X, Y is CWUser')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
@@ -184,7 +184,7 @@
rqlst = self._prepare('Any X WHERE NOT Y evaluee X, Y eid %s, X is Note' % self.ueid)
self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
self.assertEquals(rqlst.solutions, [{'X': 'Note'}])
-
+
def test_not_relation_5_1(self):
rqlst = self._prepare('Any X,Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), NOT X read_permission Y')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
@@ -201,64 +201,64 @@
self.assertEquals(rqlst.defined_vars['A']._q_invariant, True)
def test_not_relation_7(self):
- rqlst = self._prepare('Any K,V WHERE P is CWProperty, P pkey K, P value V, NOT P for_user U')
+ rqlst = self._prepare('Any K,V WHERE P is CWProperty, P pkey K, P value V, NOT P for_user U')
self.assertEquals(rqlst.defined_vars['P']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['U']._q_invariant, True)
-
- def test_exists_1(self):
+
+ def test_exists_1(self):
rqlst = self._prepare('Any U WHERE U eid IN (1,2), EXISTS(X owned_by U)')
self.assertEquals(rqlst.defined_vars['U']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
-
- def test_exists_2(self):
+
+ def test_exists_2(self):
rqlst = self._prepare('Any U WHERE EXISTS(U eid IN (1,2), X owned_by U)')
self.assertEquals(rqlst.defined_vars['U']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
- def test_exists_3(self):
+ def test_exists_3(self):
rqlst = self._prepare('Any U WHERE EXISTS(X owned_by U, X bookmarked_by U)')
self.assertEquals(rqlst.defined_vars['U']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
-
+
def test_exists_4(self):
rqlst = self._prepare('Any X,Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), EXISTS(X read_permission Y)')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
-
+
def test_exists_5(self):
rqlst = self._prepare('DISTINCT Any X,Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), EXISTS(X read_permission Y)')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True)
- def test_not_exists_1(self):
+ def test_not_exists_1(self):
rqlst = self._prepare('Any U WHERE NOT EXISTS(X owned_by U, X bookmarked_by U)')
self.assertEquals(rqlst.defined_vars['U']._q_invariant, False)
- self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
+ self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
- def test_not_exists_2(self):
+ def test_not_exists_2(self):
rqlst = self._prepare('Any X,Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), NOT EXISTS(X read_permission Y)')
self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
- def test_not_exists_distinct_1(self):
+ def test_not_exists_distinct_1(self):
rqlst = self._prepare('DISTINCT Any X,Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), NOT EXISTS(X read_permission Y)')
self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
-
- def test_or_1(self):
+
+ def test_or_1(self):
rqlst = self._prepare('Any X WHERE X concerne B OR C concerne X, B eid 12, C eid 13')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
- def test_or_2(self):
+ def test_or_2(self):
rqlst = self._prepare('Any X WHERE X created_by U, X concerne B OR C concerne X, B eid 12, C eid 13')
self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
- self.assertEquals(rqlst.defined_vars['U']._q_invariant, True)
+ self.assertEquals(rqlst.defined_vars['U']._q_invariant, True)
self.assertEquals(rqlst.defined_vars['X'].stinfo['principal'].r_type, 'created_by')
- def test_or_3(self):
+ def test_or_3(self):
rqlst = self._prepare('Any N WHERE A evaluee N or EXISTS(N todo_by U)')
self.assertEquals(rqlst.defined_vars['N']._q_invariant, False)
- self.assertEquals(rqlst.defined_vars['A']._q_invariant, True)
- self.assertEquals(rqlst.defined_vars['U']._q_invariant, True)
-
+ self.assertEquals(rqlst.defined_vars['A']._q_invariant, True)
+ self.assertEquals(rqlst.defined_vars['U']._q_invariant, True)
+
def test_or_exists_1(self):
# query generated by security rewriting
rqlst = self._prepare('DISTINCT Any A,S WHERE A is Affaire, S nom "chouette", S is IN(Division, Societe, SubDivision),'
@@ -270,13 +270,13 @@
self.assertEquals(rqlst.defined_vars['A']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['S']._q_invariant, False)
- def test_or_exists_2(self):
+ def test_or_exists_2(self):
rqlst = self._prepare('Any U WHERE EXISTS(U in_group G, G name "managers") OR EXISTS(X owned_by U, X bookmarked_by U)')
self.assertEquals(rqlst.defined_vars['U']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['G']._q_invariant, False)
self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
-
- def test_or_exists_3(self):
+
+ def test_or_exists_3(self):
rqlst = self._prepare('Any COUNT(S),CS GROUPBY CS ORDERBY 1 DESC LIMIT 10 '
'WHERE C is Societe, S concerne C, C nom CS, '
'(EXISTS(S owned_by 1)) OR (EXISTS(S documented_by N, N title "published"))')
@@ -286,7 +286,7 @@
'(EXISTS(S owned_by 1)) OR (EXISTS(S documented_by N, N title "published"))')
self.assertEquals(rqlst.defined_vars['S']._q_invariant, True)
- def test_nonregr_ambiguity(self):
+ def test_nonregr_ambiguity(self):
rqlst = self._prepare('Note N WHERE N attachment F')
# N may be an image as well, not invariant
self.assertEquals(rqlst.defined_vars['N']._q_invariant, False)
--- a/server/test/unittest_security.py Thu May 14 18:12:45 2009 +0200
+++ b/server/test/unittest_security.py Mon May 18 10:09:06 2009 +0200
@@ -15,15 +15,15 @@
self.create_user('iaminusersgrouponly')
self.readoriggroups = self.schema['Personne'].get_groups('read')
self.addoriggroups = self.schema['Personne'].get_groups('add')
-
+
def tearDown(self):
RepositoryBasedTC.tearDown(self)
self.schema['Personne'].set_groups('read', self.readoriggroups)
self.schema['Personne'].set_groups('add', self.addoriggroups)
-
+
class LowLevelSecurityFunctionTC(BaseSecurityTC):
-
+
def test_check_read_access(self):
rql = u'Personne U where U nom "managers"'
rqlst = self.repo.querier._rqlhelper.parse(rql).children[0]
@@ -38,7 +38,7 @@
check_read_access,
self.schema, cnx.user(self.current_session()), rqlst, solution)
self.assertRaises(Unauthorized, cu.execute, rql)
-
+
def test_upassword_not_selectable(self):
self.assertRaises(Unauthorized,
self.execute, 'Any X,P WHERE X is CWUser, X upassword P')
@@ -47,10 +47,10 @@
cu = cnx.cursor()
self.assertRaises(Unauthorized,
cu.execute, 'Any X,P WHERE X is CWUser, X upassword P')
-
-
+
+
class SecurityTC(BaseSecurityTC):
-
+
def setUp(self):
BaseSecurityTC.setUp(self)
# implicitly test manager can add some entities
@@ -66,7 +66,7 @@
cu.execute("INSERT Personne X: X nom 'bidule'")
self.assertRaises(Unauthorized, cnx.commit)
self.assertEquals(cu.execute('Personne X').rowcount, 1)
-
+
def test_insert_rql_permission(self):
# test user can only add une affaire related to a societe he owns
cnx = self.login('iaminusersgrouponly')
@@ -82,7 +82,7 @@
cu.execute("INSERT Societe X: X nom 'chouette'")
cu.execute("SET A concerne S WHERE A sujet 'cool', S nom 'chouette'")
cnx.commit()
-
+
def test_update_security_1(self):
cnx = self.login('anon')
cu = cnx.cursor()
@@ -91,7 +91,7 @@
self.assertRaises(Unauthorized, cnx.commit)
self.restore_connection()
self.assertEquals(self.execute('Personne X WHERE X nom "bidulechouette"').rowcount, 0)
-
+
def test_update_security_2(self):
cnx = self.login('anon')
cu = cnx.cursor()
@@ -109,7 +109,7 @@
cu.execute("INSERT Personne X: X nom 'biduuule'")
cu.execute("INSERT Societe X: X nom 'looogilab'")
cu.execute("SET X travaille S WHERE X nom 'biduuule', S nom 'looogilab'")
-
+
def test_update_rql_permission(self):
self.execute("SET A concerne S WHERE A is Affaire, S is Societe")
self.commit()
@@ -121,13 +121,13 @@
cnx.commit()
# to actually get Unauthorized exception, try to update an entity we can read
cu.execute("SET X nom 'toto' WHERE X is Societe")
- self.assertRaises(Unauthorized, cnx.commit)
+ self.assertRaises(Unauthorized, cnx.commit)
cu.execute("INSERT Affaire X: X sujet 'pascool'")
cu.execute("INSERT Societe X: X nom 'chouette'")
cu.execute("SET A concerne S WHERE A sujet 'pascool', S nom 'chouette'")
cu.execute("SET X sujet 'habahsicestcool' WHERE X sujet 'pascool'")
cnx.commit()
-
+
def test_delete_security(self):
# FIXME: sample below fails because we don't detect "owner" can't delete
# user anyway, and since no user with login == 'bidule' exists, no
@@ -139,14 +139,14 @@
cnx = self.login('iaminusersgrouponly')
cu = cnx.cursor()
self.assertRaises(Unauthorized, cu.execute, "DELETE CWGroup Y WHERE Y name 'staff'")
-
+
def test_delete_rql_permission(self):
self.execute("SET A concerne S WHERE A is Affaire, S is Societe")
self.commit()
# test user can only dele une affaire related to a societe he owns
cnx = self.login('iaminusersgrouponly')
cu = cnx.cursor()
- # this won't actually do anything since the selection query won't return anything
+ # this won't actually do anything since the selection query won't return anything
cu.execute("DELETE Affaire X")
cnx.commit()
# to actually get Unauthorized exception, try to delete an entity we can read
@@ -227,7 +227,7 @@
self.assertRaises(Unauthorized, cnx.commit)
# read security test
-
+
def test_read_base(self):
self.schema['Personne'].set_groups('read', ('users', 'managers'))
cnx = self.login('anon')
@@ -256,7 +256,7 @@
self.assertEquals(rset.rows, [[aff2]])
rset = cu.execute('Affaire X WHERE NOT X eid %(x)s', {'x': aff2}, 'x')
self.assertEquals(rset.rows, [])
-
+
def test_read_erqlexpr_has_text1(self):
aff1 = self.execute("INSERT Affaire X: X sujet 'cool'")[0][0]
card1 = self.execute("INSERT Card X: X title 'cool'")[0][0]
@@ -286,7 +286,7 @@
rset = cu.execute('Any N WHERE N has_text "bidule"')
self.assertEquals(len(rset.rows), 1, rset.rows)
rset = cu.execute('Any N WITH N BEING (Any N WHERE N has_text "bidule")')
- self.assertEquals(len(rset.rows), 1, rset.rows)
+ self.assertEquals(len(rset.rows), 1, rset.rows)
def test_read_erqlexpr_optional_rel(self):
self.execute("INSERT Personne X: X nom 'bidule'")
@@ -304,7 +304,7 @@
cnx = self.login('iaminusersgrouponly')
cu = cnx.cursor()
rset = cu.execute('Any COUNT(X) WHERE X is Affaire')
- self.assertEquals(rset.rows, [[0]])
+ self.assertEquals(rset.rows, [[0]])
aff2 = cu.execute("INSERT Affaire X: X sujet 'cool'")[0][0]
soc1 = cu.execute("INSERT Societe X: X nom 'chouette'")[0][0]
cu.execute("SET A concerne S WHERE A is Affaire, S is Societe")
@@ -320,7 +320,7 @@
values = dict(rset)
self.assertEquals(values['Affaire'], 1)
self.assertEquals(values['Societe'], 2)
-
+
def test_attribute_security(self):
# only managers should be able to edit the 'test' attribute of Personne entities
@@ -343,7 +343,7 @@
cu.execute('SET X web "http://www.logilab.org" WHERE X eid %(x)s', {'x': eid}, 'x')
cnx.commit()
cnx.close()
-
+
def test_attribute_security_rqlexpr(self):
# Note.para attribute editable by managers or if the note is in "todo" state
eid = self.execute("INSERT Note X: X para 'bidule', X in_state S WHERE S name 'done'")[0][0]
@@ -384,10 +384,10 @@
self.failUnless(x.creation_date)
cnx.rollback()
-
+
class BaseSchemaSecurityTC(BaseSecurityTC):
"""tests related to the base schema permission configuration"""
-
+
def test_user_can_delete_object_he_created(self):
# even if some other user have changed object'state
cnx = self.login('iaminusersgrouponly')
@@ -400,7 +400,7 @@
self.execute('SET X in_state S WHERE X ref "ARCT01", S name "ben non"')
self.commit()
self.assertEquals(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01"')),
- 2)
+ 2)
self.assertEquals(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01",'
'X owned_by U, U login "admin"')),
1) # TrInfo at the above state change
@@ -426,19 +426,19 @@
self.assert_(cu.execute('CWGroup X'))
# should only be able to read the anonymous user, not another one
origuser = self.session.user
- self.assertRaises(Unauthorized,
+ self.assertRaises(Unauthorized,
cu.execute, 'CWUser X WHERE X eid %(x)s', {'x': origuser.eid}, 'x')
# nothing selected, nothing updated, no exception raised
#self.assertRaises(Unauthorized,
# cu.execute, 'SET X login "toto" WHERE X eid %(x)s',
# {'x': self.user.eid})
-
+
rset = cu.execute('CWUser X WHERE X eid %(x)s', {'x': anon.eid}, 'x')
self.assertEquals(rset.rows, [[anon.eid]])
# but can't modify it
cu.execute('SET X login "toto" WHERE X eid %(x)s', {'x': anon.eid})
self.assertRaises(Unauthorized, cnx.commit)
-
+
def test_in_group_relation(self):
cnx = self.login('iaminusersgrouponly')
cu = cnx.cursor()
@@ -454,7 +454,7 @@
cu = cnx.cursor()
rql = u"SET X owned_by U WHERE U login 'iaminusersgrouponly', X is Personne"
self.assertRaises(Unauthorized, cu.execute, rql)
-
+
def test_bookmarked_by_guests_security(self):
beid1 = self.execute('INSERT Bookmark B: B path "?vid=manage", B title "manage"')[0][0]
beid2 = self.execute('INSERT Bookmark B: B path "?vid=index", B title "index", B bookmarked_by U WHERE U login "anon"')[0][0]
@@ -475,7 +475,7 @@
self.assertRaises(Unauthorized,
cu.execute, 'SET B bookmarked_by U WHERE U eid %(x)s, B eid %(b)s',
{'x': anoneid, 'b': beid1}, 'x')
-
+
def test_ambigous_ordered(self):
cnx = self.login('anon')
@@ -494,7 +494,7 @@
# needed to avoid check_perm error
session.set_pool()
# needed to remove rql expr granting update perm to the user
- self.schema['Affaire'].set_rqlexprs('update', ())
+ self.schema['Affaire'].set_rqlexprs('update', ())
self.assertRaises(Unauthorized,
self.schema['Affaire'].check_perm, session, 'update', eid)
cu = cnx.cursor()
@@ -506,6 +506,6 @@
# the best would probably ValidationError if the transition doesn't exist
# from the current state but Unauthorized if it exists but user can't pass it
self.assertRaises(ValidationError, cu.execute, rql, {'x': cnx.user(self.current_session()).eid}, 'x')
-
+
if __name__ == '__main__':
unittest_main()
--- a/server/test/unittest_session.py Thu May 14 18:12:45 2009 +0200
+++ b/server/test/unittest_session.py Mon May 18 10:09:06 2009 +0200
@@ -6,12 +6,12 @@
def __init__(self, name):
self.name = name
self.children = []
-
+
def get_type(self, solution, args=None):
return solution[self.name]
def as_string(self):
return self.name
-
+
class Function:
def __init__(self, name, varname):
self.name = name
--- a/server/test/unittest_sqlutils.py Thu May 14 18:12:45 2009 +0200
+++ b/server/test/unittest_sqlutils.py Mon May 18 10:09:06 2009 +0200
@@ -20,12 +20,12 @@
def test_init(self):
o = SQLAdapterMixIn(BASE_CONFIG)
self.assertEquals(o.encoding, 'UTF-8')
-
+
def test_init_encoding(self):
config = BASE_CONFIG.copy()
config['db-encoding'] = 'ISO-8859-1'
o = SQLAdapterMixIn(config)
self.assertEquals(o.encoding, 'ISO-8859-1')
-
+
if __name__ == '__main__':
unittest_main()
--- a/server/test/unittest_ssplanner.py Thu May 14 18:12:45 2009 +0200
+++ b/server/test/unittest_ssplanner.py Mon May 18 10:09:06 2009 +0200
@@ -8,7 +8,7 @@
class SSPlannerTC(BasePlannerTC):
repo = repo
_test = test_plan
-
+
def setUp(self):
BasePlannerTC.setUp(self)
self.planner = SSPlanner(self.o.schema, self.o._rqlhelper)
@@ -33,9 +33,9 @@
{'X': 'State', 'XN': 'String'},
{'X': 'Tag', u'XN': 'String'},
{'X': 'Transition', 'XN': 'String'}])],
- None, None,
+ None, None,
[self.system], None, [])])
-
+
def test_groupeded_ambigous_sol(self):
self._test('Any XN,COUNT(X) GROUPBY XN WHERE X name XN',
[('OneFetchStep', [('Any XN,COUNT(X) GROUPBY XN WHERE X name XN',
@@ -52,9 +52,9 @@
{'X': 'State', 'XN': 'String'},
{'X': 'Tag', u'XN': 'String'},
{'X': 'Transition', 'XN': 'String'}])],
- None, None,
+ None, None,
[self.system], None, [])])
-
+
if __name__ == '__main__':
from logilab.common.testlib import unittest_main
unittest_main()
--- a/server/test/unittest_tools.py Thu May 14 18:12:45 2009 +0200
+++ b/server/test/unittest_tools.py Mon May 18 10:09:06 2009 +0200
@@ -6,6 +6,6 @@
import cubicweb.server.server
import cubicweb.server.checkintegrity
import cubicweb.server.serverctl
-
+
if __name__ == '__main__':
unittest_main()
--- a/server/utils.py Thu May 14 18:12:45 2009 +0200
+++ b/server/utils.py Mon May 18 10:09:06 2009 +0200
@@ -46,7 +46,7 @@
for item in seqin[0]:
newcomb = comb + [item] # add next item to current combination
# call rloop w/ remaining seqs, newcomb
- for item in rloop(seqin[1:], newcomb):
+ for item in rloop(seqin[1:], newcomb):
yield item # seqs and newcomb
else: # processing last sequence
yield comb # comb finished, add to list
@@ -95,7 +95,7 @@
self.start()
self.func = auto_restart_func
self.name = func.__name__
-
+
def start(self):
self._t = Timer(self.interval, self.func)
self._t.start()
@@ -120,7 +120,7 @@
Thread.__init__(self, target=auto_remove_func)
self.running_threads = running_threads
self._name = target.__name__
-
+
def start(self):
self.running_threads.append(self)
Thread.start(self)
--- a/setup.py Thu May 14 18:12:45 2009 +0200
+++ b/setup.py Mon May 18 10:09:06 2009 +0200
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# pylint: disable-msg=W0142,W0403,W0404,W0613,W0622,W0622,W0704,R0904,C0103,E0611
#
-# Copyright (c) 2003 LOGILAB S.A. (Paris, FRANCE).
+# Copyright (c) 2003-2009 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This program is free software; you can redistribute it and/or modify it under
@@ -56,7 +56,7 @@
BASE_BLACKLIST = ('CVS', 'debian', 'dist', 'build', '__buildlog')
IGNORED_EXTENSIONS = ('.pyc', '.pyo', '.elc')
-
+
def ensure_scripts(linux_scripts):
"""
@@ -152,7 +152,7 @@
for directory in include_dirs:
dest = join(self.install_dir, base, directory)
export(directory, dest)
-
+
def install(**kwargs):
"""setup entry point"""
if subpackage_of:
@@ -177,6 +177,6 @@
cmdclass={'install_lib': MyInstallLib},
**kwargs
)
-
+
if __name__ == '__main__' :
install()
--- a/skeleton/setup.py Thu May 14 18:12:45 2009 +0200
+++ b/skeleton/setup.py Mon May 18 10:09:06 2009 +0200
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# pylint: disable-msg=W0404,W0622,W0704,W0613,W0152
-# Copyright (c) 2003-2004 LOGILAB S.A. (Paris, FRANCE).
+# Copyright (c) 2003-2009 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This program is free software; you can redistribute it and/or modify it under
@@ -45,6 +45,6 @@
url=web,
data_files=data_files,
**kwargs)
-
+
if __name__ == '__main__' :
install()
--- a/skeleton/test/realdb_test_CUBENAME.py Thu May 14 18:12:45 2009 +0200
+++ b/skeleton/test/realdb_test_CUBENAME.py Mon May 18 10:09:06 2009 +0200
@@ -18,7 +18,7 @@
def test_all_primaries(self):
for rset in self.iter_individual_rsets(limit=50):
yield self.view, 'primary', rset, rset.req.reset_headers()
-
+
## startup views
def test_startup_views(self):
for vid in self.list_startup_views():
--- a/sobjects/email.py Thu May 14 18:12:45 2009 +0200
+++ b/sobjects/email.py Mon May 18 10:09:06 2009 +0200
@@ -1,7 +1,7 @@
"""hooks to ensure use_email / primary_email relations consistency
: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"
@@ -15,50 +15,50 @@
"""
rtype = 'use_email'
fromeid = toeid = None # make pylint happy
-
+
def condition(self):
"""check entity has use_email set for the email address"""
return not self.session.unsafe_execute(
'Any X WHERE X eid %(x)s, X use_email Y, Y eid %(y)s',
{'x': self.fromeid, 'y': self.toeid}, 'x')
-
+
def precommit_event(self):
session = self.session
if self.condition():
session.unsafe_execute(
'SET X %s Y WHERE X eid %%(x)s, Y eid %%(y)s' % self.rtype,
{'x': self.fromeid, 'y': self.toeid}, 'x')
-
+
class SetPrimaryEmailRelationOp(SetUseEmailRelationOp):
rtype = 'primary_email'
-
+
def condition(self):
"""check entity has no primary_email set"""
return not self.session.unsafe_execute(
'Any X WHERE X eid %(x)s, X primary_email Y',
{'x': self.fromeid}, 'x')
-
+
class SetPrimaryEmailHook(Hook):
"""notify when a bug or story or version has its state modified"""
events = ('after_add_relation',)
accepts = ('use_email',)
-
+
def call(self, session, fromeid, rtype, toeid):
subjtype = session.describe(fromeid)[0]
eschema = self.vreg.schema[subjtype]
if 'primary_email' in eschema.subject_relations():
- SetPrimaryEmailRelationOp(session, vreg=self.vreg,
+ SetPrimaryEmailRelationOp(session, vreg=self.vreg,
fromeid=fromeid, toeid=toeid)
class SetUseEmailHook(Hook):
"""notify when a bug or story or version has its state modified"""
events = ('after_add_relation',)
accepts = ('primary_email',)
-
+
def call(self, session, fromeid, rtype, toeid):
subjtype = session.describe(fromeid)[0]
eschema = self.vreg.schema[subjtype]
if 'use_email' in eschema.subject_relations():
- SetUseEmailRelationOp(session, vreg=self.vreg,
+ SetUseEmailRelationOp(session, vreg=self.vreg,
fromeid=fromeid, toeid=toeid)
--- a/sobjects/hooks.py Thu May 14 18:12:45 2009 +0200
+++ b/sobjects/hooks.py Mon May 18 10:09:06 2009 +0200
@@ -15,7 +15,7 @@
"""ensure user logins are stripped"""
events = ('before_add_entity', 'before_update_entity',)
accepts = ('CWUser',)
-
+
def call(self, session, entity):
if 'login' in entity and entity['login']:
entity['login'] = entity['login'].strip()
@@ -30,12 +30,12 @@
{'x': self.beid}, 'x'):
session.unsafe_execute('DELETE Bookmark X WHERE X eid %(x)s',
{'x': self.beid}, 'x')
-
+
class DelBookmarkedByHook(Hook):
"""ensure user logins are stripped"""
events = ('after_delete_relation',)
accepts = ('bookmarked_by',)
-
+
def call(self, session, subj, rtype, obj):
AutoDeleteBookmark(session, beid=subj)
@@ -60,4 +60,3 @@
fmt = entity.get_value(metaattr)
if fmt == 'text/html':
entity[attr] = soup2xhtml(value, session.encoding)
-
--- a/sobjects/test/data/sobjects/__init__.py Thu May 14 18:12:45 2009 +0200
+++ b/sobjects/test/data/sobjects/__init__.py Mon May 18 10:09:06 2009 +0200
@@ -2,5 +2,3 @@
class UserStatusChangeView(StatusChangeMixIn, NotificationView):
accepts = ('CWUser',)
-
-
--- a/sobjects/test/unittest_email.py Thu May 14 18:12:45 2009 +0200
+++ b/sobjects/test/unittest_email.py Mon May 18 10:09:06 2009 +0200
@@ -22,7 +22,7 @@
self.commit()
self.assertEquals(self.execute('Any A WHERE U use_email X, U login "admin", X address A')[0][0],
'admin@logilab.fr')
-
+
if __name__ == '__main__':
from logilab.common.testlib import unittest_main
--- a/sobjects/test/unittest_hooks.py Thu May 14 18:12:45 2009 +0200
+++ b/sobjects/test/unittest_hooks.py Mon May 18 10:09:06 2009 +0200
@@ -13,7 +13,7 @@
{'e': u.eid})[0][0]
self.assertEquals(tname, 'jijoe')
-
+
def test_auto_delete_bookmarks(self):
beid = self.execute('INSERT Bookmark X: X title "hop", X path "view", X bookmarked_by U '
'WHERE U login "admin"')[0][0]
@@ -25,6 +25,6 @@
self.execute('DELETE X bookmarked_by U WHERE U login "anon"')
self.commit()
self.failIf(self.execute('Any X WHERE X eid %(x)s', {'x': beid}, 'x'))
-
+
if __name__ == '__main__':
unittest_main()
--- a/test/data/erqlexpr_on_ertype.py Thu May 14 18:12:45 2009 +0200
+++ b/test/data/erqlexpr_on_ertype.py Mon May 18 10:09:06 2009 +0200
@@ -6,7 +6,7 @@
'delete': ('managers',),
}
toto = SubjectRelation('TuTu')
-
+
class TuTu(EntityType):
permissions = {
'read': ('managers',),
--- a/test/data/rqlexpr_on_ertype_read.py Thu May 14 18:12:45 2009 +0200
+++ b/test/data/rqlexpr_on_ertype_read.py Mon May 18 10:09:06 2009 +0200
@@ -6,7 +6,7 @@
'delete': ('managers',),
}
toto = SubjectRelation('TuTu')
-
+
class TuTu(EntityType):
permissions = {
'read': ('managers',),
--- a/test/data/rrqlexpr_on_attr.py Thu May 14 18:12:45 2009 +0200
+++ b/test/data/rrqlexpr_on_attr.py Mon May 18 10:09:06 2009 +0200
@@ -6,7 +6,7 @@
'delete': ('managers',),
}
attr = String()
-
+
class attr(RelationType):
permissions = {
'read': ('managers', ),
--- a/test/unittest_cwctl.py Thu May 14 18:12:45 2009 +0200
+++ b/test/unittest_cwctl.py Mon May 18 10:09:06 2009 +0200
@@ -19,10 +19,10 @@
sys.stdout = self.stream
def tearDown(self):
sys.stdout = sys.__stdout__
-
+
def test_list(self):
from cubicweb.cwctl import ListCommand
ListCommand().run([])
-
+
if __name__ == '__main__':
unittest_main()
--- a/test/unittest_schema.py Thu May 14 18:12:45 2009 +0200
+++ b/test/unittest_schema.py Mon May 18 10:09:06 2009 +0200
@@ -96,7 +96,7 @@
['Any X WHERE X travaille S, S owned_by U, X eid %(x)s, U eid %(u)s'])
eperson.set_groups('read', ('managers',))
self.assertEqual(eperson.get_groups('read'), set(('managers',)))
-
+
def test_relation_perms(self):
rconcerne = schema.rschema('concerne')
rconcerne.set_default_groups()
@@ -112,19 +112,19 @@
self.assertRaises(RQLSyntaxError, ERQLExpression, '1')
expr = ERQLExpression('X travaille S, S owned_by U')
self.assertEquals(str(expr), 'Any X WHERE X travaille S, S owned_by U, X eid %(x)s, U eid %(u)s')
-
+
def test_rrqlexpression(self):
self.assertRaises(Exception, RRQLExpression, '1')
self.assertRaises(RQLSyntaxError, RRQLExpression, 'O X Y')
expr = RRQLExpression('U has_update_permission O')
self.assertEquals(str(expr), 'Any O WHERE U has_update_permission O, O eid %(o)s, U eid %(u)s')
-
+
loader = CubicWebSchemaLoader()
config = TestConfiguration('data')
config.bootstrap_cubes()
loader.lib_directory = config.schemas_lib_dir()
-
+
class SQLSchemaReaderClassTest(TestCase):
def test_knownValues_include_schema_files(self):
@@ -139,15 +139,15 @@
self.assertEquals(schema.name, 'data')
entities = [str(e) for e in schema.entities()]
entities.sort()
- expected_entities = ['Bookmark', 'Boolean', 'Bytes', 'Card',
+ expected_entities = ['Bookmark', 'Boolean', 'Bytes', 'Card',
'Date', 'Datetime', 'Decimal',
'CWCache', 'CWConstraint', 'CWConstraintType', 'CWEType',
'CWAttribute', 'CWGroup', 'EmailAddress', 'CWRelation',
'CWPermission', 'CWProperty', 'CWRType', 'CWUser',
'File', 'Float', 'Image', 'Int', 'Interval', 'Note',
'Password', 'Personne',
- 'RQLExpression',
- 'Societe', 'State', 'String', 'SubNote', 'Tag', 'Time',
+ 'RQLExpression',
+ 'Societe', 'State', 'String', 'SubNote', 'Tag', 'Time',
'Transition', 'TrInfo']
self.assertListEquals(entities, sorted(expected_entities))
relations = [str(r) for r in schema.relations()]
@@ -155,7 +155,7 @@
expected_relations = ['add_permission', 'address', 'alias',
'allowed_transition', 'bookmarked_by', 'canonical',
- 'cardinality', 'comment', 'comment_format',
+ 'cardinality', 'comment', 'comment_format',
'composite', 'condition', 'connait', 'constrained_by', 'content',
'content_format', 'created_by', 'creation_date', 'cstrtype',
@@ -167,7 +167,7 @@
'final', 'firstname', 'for_user',
'from_entity', 'from_state', 'fulltext_container', 'fulltextindexed',
- 'has_text',
+ 'has_text',
'identical_to', 'identity', 'in_group', 'in_state', 'indexed',
'initial_state', 'inlined', 'internationalizable', 'is', 'is_instance_of',
@@ -179,20 +179,20 @@
'ordernum', 'owned_by',
- 'path', 'pkey', 'prenom', 'primary_email',
+ 'path', 'pkey', 'prenom', 'primary_email',
'read_permission', 'relation_type', 'require_group',
-
+
'specializes', 'state_of', 'surname', 'symetric', 'synopsis',
'tags', 'timestamp', 'title', 'to_entity', 'to_state', 'transition_of', 'travaille', 'type',
'upassword', 'update_permission', 'use_email',
- 'value',
+ 'value',
'wf_info_for', 'wikiid']
-
+
self.assertListEquals(relations, expected_relations)
eschema = schema.eschema('CWUser')
@@ -234,16 +234,16 @@
ex = self.assertRaises(BadSchemaDefinition,
self.loader._build_schema, 'toto', False)
self.assertEquals(str(ex), msg)
-
+
def test_rrqlexpr_on_etype(self):
self._test('rrqlexpr_on_eetype.py', "can't use RRQLExpression on an entity type, use an ERQLExpression (ToTo)")
-
+
def test_erqlexpr_on_rtype(self):
self._test('erqlexpr_on_ertype.py', "can't use ERQLExpression on a relation type, use a RRQLExpression (toto)")
-
+
def test_rqlexpr_on_rtype_read(self):
self._test('rqlexpr_on_ertype_read.py', "can't use rql expression for read permission of a relation type (toto)")
-
+
def test_rrqlexpr_on_attr(self):
self._test('rrqlexpr_on_attr.py', "can't use RRQLExpression on a final relation type (eg attribute relation), use an ERQLExpression (attr)")
--- a/test/unittest_utils.py Thu May 14 18:12:45 2009 +0200
+++ b/test/unittest_utils.py Mon May 18 10:09:06 2009 +0200
@@ -9,7 +9,7 @@
def test_1(self):
self.assertNotEquals(make_uid('xyz'), make_uid('abcd'))
self.assertNotEquals(make_uid('xyz'), make_uid('xyz'))
-
+
def test_2(self):
d = {}
while len(d)<10000:
@@ -18,7 +18,7 @@
self.fail(len(d))
d[uid] = 1
-
+
class UStringIOTC(TestCase):
def test_boolean_value(self):
self.assert_(UStringIO())
@@ -31,7 +31,7 @@
for i in xrange(12):
l.append(i)
self.assertEquals(l, range(2, 12))
-
+
def test_extend(self):
testdata = [(range(5), range(5)),
(range(10), range(10)),
@@ -42,6 +42,6 @@
l.extend(extension)
yield self.assertEquals, l, expected
-
+
if __name__ == '__main__':
unittest_main()
--- a/toolsutils.py Thu May 14 18:12:45 2009 +0200
+++ b/toolsutils.py Mon May 18 10:09:06 2009 +0200
@@ -39,7 +39,7 @@
if ex.errno != errno.EEXIST:
raise
print 'directory %s already exists' % directory
-
+
def create_symlink(source, target):
"""create a symbolic link"""
if exists(target):
@@ -51,7 +51,7 @@
import shutil
print '[copy] %s <-- %s' % (target, source)
shutil.copy2(source, target)
-
+
def rm(whatever):
import shutil
shutil.rmtree(whatever)
@@ -66,7 +66,7 @@
diffs = p_output.read()
if diffs:
if askconfirm:
- print
+ print
print diffs
action = raw_input('replace (N/y/q) ? ').lower()
else:
@@ -120,7 +120,7 @@
show_diffs(tfpath, fpath, askconfirm)
else:
shutil.copyfile(fpath, tfpath)
-
+
def fill_templated_file(fpath, tfpath, context):
fobj = file(tfpath, 'w')
templated = file(fpath).read()
@@ -158,7 +158,7 @@
:param config_file: path to the configuration file
:rtype: dict
- :return: a dictionary with specified values associated to option names
+ :return: a dictionary with specified values associated to option names
"""
from logilab.common.fileutils import lines
config = current = {}
@@ -194,10 +194,10 @@
:type default: str
:param default: default value if the environment variable is not defined
-
+
:type name: str
:param name: the informal name of the path, used for error message
-
+
:rtype: str
:return: the value of the environment variable or the default value
@@ -243,12 +243,12 @@
msg = 'No helper for command %s using %s configuration' % (
cmdname, config.name)
raise ConfigurationError(msg)
-
+
def fail(self, reason):
print "command failed:", reason
sys.exit(1)
-
-
+
+
def main_run(args, doc):
"""command line tool"""
try:
@@ -289,4 +289,4 @@
if not password:
password = getpass('password: ')
return connect(user=user, password=password, host=optconfig.host, database=appid)
-
+
--- a/web/__init__.py Thu May 14 18:12:45 2009 +0200
+++ b/web/__init__.py Mon May 18 10:09:06 2009 +0200
@@ -13,6 +13,8 @@
from datetime import datetime, date, timedelta
from simplejson import dumps
+from logilab.common.deprecation import obsolete
+
from cubicweb.common.uilib import urlquote
from cubicweb.web._exceptions import *
@@ -62,6 +64,7 @@
return json_dumps(function(*args, **kwargs))
return newfunc
+@obsolete('use req.build_ajax_replace_url() instead')
def ajax_replace_url(nodeid, rql, vid=None, swap=False, **extraparams):
"""builds a replacePageChunk-like url
>>> ajax_replace_url('foo', 'Person P')
--- a/web/_exceptions.py Thu May 14 18:12:45 2009 +0200
+++ b/web/_exceptions.py Mon May 18 10:09:06 2009 +0200
@@ -2,7 +2,7 @@
"""exceptions used in the core of the CubicWeb web application
: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"
@@ -11,13 +11,13 @@
class PublishException(CubicWebException):
"""base class for publishing related exception"""
-
+
class RequestError(PublishException):
"""raised when a request can't be served because of a bad input"""
class NothingToEdit(RequestError):
"""raised when an edit request doesn't specify any eid to edit"""
-
+
class NotFound(RequestError):
"""raised when a 404 error should be returned"""
@@ -34,7 +34,7 @@
def __init__(self, status, content=''):
self.status = int(status)
self.content = content
-
+
class ExplicitLogin(AuthenticationError):
"""raised when a bad connection id is given or when an attempt to establish
a connection failed"""
@@ -55,4 +55,3 @@
def dumps(self):
import simplejson
return simplejson.dumps({'reason': self.reason})
-
--- a/web/data/cubicweb.ajax.js Thu May 14 18:12:45 2009 +0200
+++ b/web/data/cubicweb.ajax.js Mon May 18 10:09:06 2009 +0200
@@ -317,6 +317,18 @@
}
}
+/*
+ * fetches `url` and replaces `nodeid`'s content with the result
+ * @param replacemode how the replacement should be done (default is 'replace')
+ * Possible values are :
+ * - 'replace' to replace the node's content with the generated HTML
+ * - 'swap' to replace the node itself with the generated HTML
+ * - 'append' to append the generated HTML to the node's content
+ */
+function loadxhtml(nodeid, url, /* ... */ replacemode) {
+ jQuery('#' + nodeid).loadxhtml(url, null, 'post', replacemode);
+}
+
/* XXX: this function should go in edition.js but as for now, htmlReplace
* references it.
*
--- a/web/formfields.py Thu May 14 18:12:45 2009 +0200
+++ b/web/formfields.py Mon May 18 10:09:06 2009 +0200
@@ -473,9 +473,10 @@
if card in '?1':
kwargs['widget'].attrs.setdefault('size', 1)
if isinstance(cstr, SizeConstraint) and cstr.max is not None:
- if cstr.max > 257:
- kwargs.setdefault('widget', TextArea)
+ if cstr.max < 257:
+ kwargs.setdefault('widget', TextInput())
kwargs['max_length'] = cstr.max
+ kwargs.setdefault('widget', TextArea())
return StringField(**kwargs)
if fieldclass is FileField:
for metadata in ('format', 'encoding'):
--- a/web/httpcache.py Thu May 14 18:12:45 2009 +0200
+++ b/web/httpcache.py Mon May 18 10:09:06 2009 +0200
@@ -42,14 +42,14 @@
def etag(self):
return self.view.id + '/' + ','.join(sorted(self.req.user.groups))
-
+
def max_age(self):
# 0 to actually force revalidation
return 0
-
+
def last_modified(self):
return self.view.last_modified()
-
+
def set_headers(self):
req = self.req
try:
@@ -129,4 +129,4 @@
viewmod.EntityView.http_cache_manager = EntityHTTPCacheManager
viewmod.StartupView.http_cache_manager = MaxAgeHTTPCacheManager
-viewmod.StartupView.cache_max_age = 60*60*2 # stay in http cache for 2 hours by default
+viewmod.StartupView.cache_max_age = 60*60*2 # stay in http cache for 2 hours by default
--- a/web/request.py Thu May 14 18:12:45 2009 +0200
+++ b/web/request.py Mon May 18 10:09:06 2009 +0200
@@ -19,12 +19,14 @@
from logilab.common.decorators import cached
from logilab.common.deprecation import obsolete
+from logilab.mtconverter import html_escape
+
from cubicweb.dbapi import DBAPIRequest
from cubicweb.common.mail import header
from cubicweb.common.uilib import remove_html_tags
from cubicweb.utils import SizeConstrainedList, HTMLHead
-from cubicweb.web import (INTERNAL_FIELD_VALUE, LOGGER, NothingToEdit, RequestError,
- StatusResponse)
+from cubicweb.web import (INTERNAL_FIELD_VALUE, LOGGER, NothingToEdit,
+ RequestError, StatusResponse)
_MARKER = object()
@@ -478,6 +480,23 @@
cssfile = self.datadir_url + cssfile
add_css(cssfile, media)
+ def build_ajax_replace_url(self, nodeid, rql, vid, replacemode='replace',
+ **extraparams):
+ """builds an ajax url that will replace `nodeid`s content
+ :param nodeid: the dom id of the node to replace
+ :param rql: rql to execute
+ :param vid: the view to apply on the resultset
+ :param replacemode: defines how the replacement should be done.
+ Possible values are :
+ - 'replace' to replace the node's content with the generated HTML
+ - 'swap' to replace the node itself with the generated HTML
+ - 'append' to append the generated HTML to the node's content
+ """
+ url = self.build_url('view', rql=rql, vid=vid, __notemplate=1,
+ **extraparams)
+ return "javascript: loadxhtml('%s', '%s', '%s')" % (
+ nodeid, html_escape(url), replacemode)
+
# urls/path management ####################################################
def url(self, includeparams=True):
--- a/web/test/data/schema/testschema.py Thu May 14 18:12:45 2009 +0200
+++ b/web/test/data/schema/testschema.py Mon May 18 10:09:06 2009 +0200
@@ -1,7 +1,7 @@
class Salesterm(EntityType):
described_by_test = SubjectRelation('File', cardinality='1*', composite='subject')
amount = Int(constraints=[IntervalBoundConstraint(0, 100)])
-
+
class tags(RelationDefinition):
subject = 'Tag'
object = ('BlogEntry', 'CWUser')
--- a/web/test/data/views.py Thu May 14 18:12:45 2009 +0200
+++ b/web/test/data/views.py Mon May 18 10:09:06 2009 +0200
@@ -21,6 +21,6 @@
pass
assert req.user.login == login
return orig_publish(self, path, req)
-
+
orig_publish = CubicWebPublisher.main_publish
CubicWebPublisher.main_publish = auto_login_publish
--- a/web/test/test_views.py Thu May 14 18:12:45 2009 +0200
+++ b/web/test/test_views.py Mon May 18 10:09:06 2009 +0200
@@ -22,7 +22,7 @@
class SomeView(AnyRsetView):
id = 'someview'
-
+
def call(self):
self.req.add_js('spam.js')
self.req.add_js('spam.js')
@@ -34,7 +34,7 @@
def test_manual_tests(self):
rset = self.execute('Any P,F,S WHERE P is CWUser, P firstname F, P surname S')
- self.view('table', rset, template=None, displayfilter=True, displaycols=[0,2])
+ self.view('table', rset, template=None, displayfilter=True, displaycols=[0,2])
def test_sortable_js_added(self):
rset = self.execute('CWUser X')
@@ -54,14 +54,13 @@
class ExplicitViewsTest(WebTest):
-
+
def test_unrelateddivs(self):
rset = self.execute('Any X WHERE X is CWUser, X login "admin"')
group = self.add_entity('CWGroup', name=u'R&D')
req = self.request(relation='in_group_subject')
self.view('unrelateddivs', rset, req)
-
-
+
if __name__ == '__main__':
from logilab.common.testlib import unittest_main
--- a/web/test/unittest_application.py Thu May 14 18:12:45 2009 +0200
+++ b/web/test/unittest_application.py Mon May 18 10:09:06 2009 +0200
@@ -44,7 +44,7 @@
class RequestBaseTC(TestCase):
def setUp(self):
self.req = FakeRequest()
-
+
def test_list_arg(self):
"""tests the list_arg() function"""
@@ -73,13 +73,13 @@
self.assertEquals(req.relative_path(False), 'login')
self.assertEquals(req.from_controller(), 'login')
-
+
class UtilsTC(TestCase):
"""test suite for misc application utilities"""
def setUp(self):
self.ctrl = FakeController()
-
+
#def test_which_mapping(self):
# """tests which mapping is used (application or core)"""
# init_mapping()
@@ -95,7 +95,7 @@
self.assertEquals(self.ctrl.execute_linkto(), None)
self.assertEquals(self.ctrl._cursor.executed,
[])
-
+
self.ctrl.set_form({'__linkto' : 'works_for:12_13_14:object',
'eid': 8})
self.ctrl.execute_linkto()
@@ -110,7 +110,7 @@
self.assertEquals(self.ctrl._cursor.executed,
['SET X works_for Y WHERE X eid 8, Y eid %s' % i
for i in (12, 13, 14)])
-
+
self.ctrl.new_cursor()
self.ctrl.req.form = {'__linkto' : 'works_for:12_13_14:object'}
@@ -152,10 +152,10 @@
return path, params
else:
self.fail('expected a Redirect exception')
-
+
def expect_redirect_publish(self, req, path='view'):
return self.expect_redirect(lambda x: self.publish(x, path), req)
-
+
def test_cnx_user_groups_sync(self):
user = self.user()
self.assertEquals(user.groups, set(('managers',)))
@@ -168,16 +168,16 @@
# cleanup
self.execute('DELETE X in_group G WHERE X eid %s, G name "guests"' % user.eid)
self.commit()
-
+
def test_nonregr_publish1(self):
req = self.request(u'CWEType X WHERE X final FALSE, X meta FALSE')
self.app.publish('view', req)
-
+
def test_nonregr_publish2(self):
req = self.request(u'Any count(N) WHERE N todo_by U, N is Note, U eid %s'
% self.user().eid)
self.app.publish('view', req)
-
+
def test_publish_validation_error(self):
req = self.request()
user = self.user()
@@ -204,12 +204,12 @@
def test_validation_error_dont_loose_subentity_data(self):
"""test creation of two linked entities
- """
+ """
req = self.request()
form = {'eid': ['X', 'Y'],
'__type:X': 'CWUser',
# missing required field
- 'login:X': u'', 'edits-login:X': '',
+ 'login:X': u'', 'edits-login:X': '',
'surname:X': u'Mr Ouaoua', 'edits-surname:X': '',
'__type:Y': 'EmailAddress',
# but email address is set
@@ -229,13 +229,13 @@
self.assertEquals(forminfo['errors'].errors, {'login': 'required attribute',
'upassword': 'required attribute'})
self.assertEquals(forminfo['values'], form)
-
+
def _test_cleaned(self, kwargs, injected, cleaned):
req = self.request(**kwargs)
page = self.app.publish('view', req)
self.failIf(injected in page, (kwargs, injected))
self.failUnless(cleaned in page, (kwargs, cleaned))
-
+
def test_nonregr_script_kiddies(self):
"""test against current script injection"""
injected = '<i>toto</i>'
@@ -245,7 +245,7 @@
{'vtitle': injected},
):
yield self._test_cleaned, kwargs, injected, cleaned
-
+
def test_site_wide_eproperties_sync(self):
# XXX work in all-in-one configuration but not in twisted for instance
# in which case we need a kindof repo -> http server notification
@@ -278,7 +278,7 @@
self.failIf(req.cnx is origcnx)
self.assertEquals(req.user.login, 'turlututu')
self.failUnless('turlututu' in page, page)
-
+
# authentication tests ####################################################
def _init_auth(self, authmode, anonuser=None):
@@ -289,7 +289,7 @@
req.cnx = None
sh = self.app.session_handler
# not properly cleaned between tests
- self.open_sessions = sh.session_manager._sessions = {}
+ self.open_sessions = sh.session_manager._sessions = {}
return req, origcnx
def _test_auth_succeed(self, req, origcnx):
@@ -299,16 +299,16 @@
self.assertEquals(len(self.open_sessions), 1, self.open_sessions)
self.assertEquals(cnx.login, origcnx.login)
self.assertEquals(cnx.password, origcnx.password)
- self.assertEquals(cnx.anonymous_connection, False)
+ self.assertEquals(cnx.anonymous_connection, False)
self.assertEquals(path, 'view')
self.assertEquals(params, {'__message': 'welcome %s !' % origcnx.login})
-
+
def _test_auth_fail(self, req):
self.assertRaises(AuthenticationError, self.app.connect, req)
self.assertEquals(req.cnx, None)
- self.assertEquals(len(self.open_sessions), 0)
+ self.assertEquals(len(self.open_sessions), 0)
clear_cache(req, 'get_authorization')
-
+
def test_http_auth_no_anon(self):
req, origcnx = self._init_auth('http')
self._test_auth_fail(req)
@@ -318,7 +318,7 @@
req._headers['Authorization'] = 'basic %s' % authstr
self._test_auth_succeed(req, origcnx)
self.assertRaises(AuthenticationError, self.publish, req, 'logout')
- self.assertEquals(len(self.open_sessions), 0)
+ self.assertEquals(len(self.open_sessions), 0)
def test_cookie_auth_no_anon(self):
req, origcnx = self._init_auth('cookie')
@@ -331,7 +331,7 @@
req.form['__password'] = origcnx.password
self._test_auth_succeed(req, origcnx)
self.assertRaises(AuthenticationError, self.publish, req, 'logout')
- self.assertEquals(len(self.open_sessions), 0)
+ self.assertEquals(len(self.open_sessions), 0)
def test_login_by_email(self):
login = self.request().user.login
@@ -351,17 +351,17 @@
req.form['__password'] = origcnx.password
self._test_auth_succeed(req, origcnx)
self.assertRaises(AuthenticationError, self.publish, req, 'logout')
- self.assertEquals(len(self.open_sessions), 0)
+ self.assertEquals(len(self.open_sessions), 0)
def _test_auth_anon(self, req):
self.app.connect(req)
acnx = req.cnx
self.assertEquals(len(self.open_sessions), 1)
- self.assertEquals(acnx.login, 'anon')
- self.assertEquals(acnx.password, 'anon')
+ self.assertEquals(acnx.login, 'anon')
+ self.assertEquals(acnx.password, 'anon')
self.failUnless(acnx.anonymous_connection)
self._reset_cookie(req)
-
+
def _reset_cookie(self, req):
# preparing the suite of the test
# set session id in cookie
@@ -371,15 +371,15 @@
clear_cache(req, 'get_authorization')
# reset cnx as if it was a new incoming request
req.cnx = None
-
+
def _test_anon_auth_fail(self, req):
- self.assertEquals(len(self.open_sessions), 1)
+ self.assertEquals(len(self.open_sessions), 1)
self.app.connect(req)
self.assertEquals(req.message, 'authentication failure')
self.assertEquals(req.cnx.anonymous_connection, True)
- self.assertEquals(len(self.open_sessions), 1)
+ self.assertEquals(len(self.open_sessions), 1)
self._reset_cookie(req)
-
+
def test_http_auth_anon_allowed(self):
req, origcnx = self._init_auth('http', 'anon')
self._test_auth_anon(req)
@@ -390,8 +390,8 @@
req._headers['Authorization'] = 'basic %s' % authstr
self._test_auth_succeed(req, origcnx)
self.assertRaises(AuthenticationError, self.publish, req, 'logout')
- self.assertEquals(len(self.open_sessions), 0)
-
+ self.assertEquals(len(self.open_sessions), 0)
+
def test_cookie_auth_anon_allowed(self):
req, origcnx = self._init_auth('cookie', 'anon')
self._test_auth_anon(req)
@@ -402,7 +402,7 @@
req.form['__password'] = origcnx.password
self._test_auth_succeed(req, origcnx)
self.assertRaises(AuthenticationError, self.publish, req, 'logout')
- self.assertEquals(len(self.open_sessions), 0)
+ self.assertEquals(len(self.open_sessions), 0)
if __name__ == '__main__':
--- a/web/test/unittest_urlrewrite.py Thu May 14 18:12:45 2009 +0200
+++ b/web/test/unittest_urlrewrite.py Mon May 18 10:09:06 2009 +0200
@@ -35,7 +35,7 @@
('/doc/(.+?)/?$', dict(fid='\\1', vid='wdoc')),
('/changelog/?$', dict(vid='changelog')),
# now in SchemaBasedRewriter
- #('/search/(.+)$', dict(rql=r'Any X WHERE X has_text "\1"')),
+ #('/search/(.+)$', dict(rql=r'Any X WHERE X has_text "\1"')),
])
@@ -94,8 +94,8 @@
pmid, rset = rewriter.rewrite(req, u'/DaLToN/JoE')
self.assertEquals(len(rset), 1)
self.assertEquals(rset[0][0], self.p1.eid)
-
-
+
+
if __name__ == '__main__':
unittest_main()
--- a/web/test/unittest_views_actions.py Thu May 14 18:12:45 2009 +0200
+++ b/web/test/unittest_views_actions.py Mon May 18 10:09:06 2009 +0200
@@ -20,6 +20,6 @@
rset = self.execute('Any X WHERE X login "anon"', req=req)
self.failIf([action for action in self.vreg.possible_vobjects('actions', req, rset)
if action.id == 'sendemail'])
-
+
if __name__ == '__main__':
unittest_main()
--- a/web/test/unittest_views_baseforms.py Thu May 14 18:12:45 2009 +0200
+++ b/web/test/unittest_views_baseforms.py Mon May 18 10:09:06 2009 +0200
@@ -31,7 +31,7 @@
def setup_database(self):
self.create_user('joe')
-
+
def _build_creation_form(self, etype):
req = self.request()
req.next_tabindex()
@@ -44,10 +44,10 @@
view.w = buffer.write
view.edit_form(entity, {})
return buffer.getvalue()
-
+
def _test_view_for(self, etype, expected):
self.assertTextEquals(expected, cleanup_text(self._build_creation_form(etype)))
-
+
def test_base(self):
self._test_view_for('CWGroup', '''\
<form id="entityForm" class="entityForm" cubicweb:target="eformframe"
@@ -198,7 +198,7 @@
entity = vreg.etype_class('Salesterm')(req, None, None)
view = vreg.select_view('creation', req, None)
self.failUnless(view.need_multipart(entity))
-
+
def test_nonregr_check_add_permission_on_relation(self):
@@ -214,7 +214,7 @@
self.login('joe')
html = self._build_creation_form('BlogEntry')
self.failIf('name="edits-checked_by:A"' in html)
-
+
from cubicweb.devtools.testlib import WebTest
from cubicweb.devtools.htmlparser import DTDValidator
--- a/web/test/unittest_views_searchrestriction.py Thu May 14 18:12:45 2009 +0200
+++ b/web/test/unittest_views_searchrestriction.py Mon May 18 10:09:06 2009 +0200
@@ -15,7 +15,7 @@
mainvar = prepare_facets_rqlst(rqlst)[0]
insert_attr_select_relation(rqlst.children[0], mainvar, rel, role, attr)
return rqlst.as_string()
-
+
@property
def select(self):
return self.parse('Any B,(NOW - CD),S,V,U,GROUP_CONCAT(TN),VN,P,CD,BMD '
@@ -24,30 +24,30 @@
'B modification_date BMD, T? tags B, T name TN, '
'V? bookmarked_by B, V title VN, B created_by U?, '
'B in_group P, P name "managers"')
-
+
def test_1(self):
self.assertEquals(self._generate(self.select, 'in_state', 'subject', 'name'),
"DISTINCT Any A,C ORDERBY C WHERE B in_group P, P name 'managers', "
"B in_state A, A name C, B is CWUser")
-
+
def test_2(self):
self.assertEquals(self._generate(self.select, 'tags', 'object', 'name'),
"DISTINCT Any A,C ORDERBY C WHERE B in_group P, P name 'managers', "
"A tags B, A name C, B is CWUser")
-
+
def test_3(self):
self.assertEquals(self._generate(self.select, 'created_by', 'subject', 'login'),
"DISTINCT Any A,C ORDERBY C WHERE B in_group P, P name 'managers', "
"B created_by A, A login C, B is CWUser")
-
+
def test_4(self):
self.assertEquals(self._generate(self.parse('Any X WHERE X is CWUser'), 'created_by', 'subject', 'login'),
"DISTINCT Any A,B ORDERBY B WHERE X is CWUser, X created_by A, A login B")
-
+
def test_5(self):
self.assertEquals(self._generate(self.parse('Any X,L WHERE X is CWUser, X login L'), 'created_by', 'subject', 'login'),
"DISTINCT Any A,B ORDERBY B WHERE X is CWUser, X created_by A, A login B")
-
+
def test_nonregr1(self):
select = self.parse('Any T,V WHERE T bookmarked_by V?, '
'V in_state VS, VS name "published", T created_by U')
@@ -77,7 +77,7 @@
self.assertEquals(self._generate(select, 'in_group', 'subject', 'name'),
"DISTINCT Any B,C ORDERBY C WHERE X is CWUser, X in_group B, B name C")
-
+
if __name__ == '__main__':
from logilab.common.testlib import unittest_main
unittest_main()
--- a/web/test/unittest_webconfig.py Thu May 14 18:12:45 2009 +0200
+++ b/web/test/unittest_webconfig.py Mon May 18 10:09:06 2009 +0200
@@ -10,7 +10,7 @@
self.config = ApptestConfiguration('data')
self.config._cubes = ['file']
self.config.load_configuration()
-
+
def test_nonregr_print_css_as_list(self):
"""make sure PRINT_CSS *must* is a list"""
config = self.config
@@ -26,8 +26,8 @@
self.failUnless('file' in self.config.locate_resource(rname).split(os.sep))
cubicwebcsspath = self.config.locate_resource('cubicweb.css').split(os.sep)
self.failUnless('web' in cubicwebcsspath or 'shared' in cubicwebcsspath) # 'shared' if tests under apycot
-
+
if __name__ == '__main__':
unittest_main()
-
+
--- a/web/test/unittest_widgets.py Thu May 14 18:12:45 2009 +0200
+++ b/web/test/unittest_widgets.py Mon May 18 10:09:06 2009 +0200
@@ -1,6 +1,4 @@
-"""cubicweb.common.widget unit tests
-
-"""
+"""cubicweb.common.widget unit tests"""
from datetime import datetime
NOW = datetime.now()
@@ -13,11 +11,11 @@
class WidgetsTC(EnvBasedTC):
-
+
def get_widget(self, etype, rname, rtype):
rschema = self.schema[rname]
return widget(self.vreg, etype, rschema, rtype, role='subject')
-
+
def test_hidden_widget(self):
w = self.get_widget('State', 'eid', 'Int')
@@ -187,7 +185,7 @@
def test_datetime_widget(self):
w = self.get_widget('Personne', 'datenaiss', 'Datetime')
self.assertEquals(w.name, 'datenaiss')
- example = '%s, or without time: %s' % (
+ example = '%s, or without time: %s' % (
NOW.strftime(self.vreg.property_value('ui.datetime-format')),
NOW.strftime(self.vreg.property_value('ui.date-format')))
self.assertEquals(w.render_example(self.request()), example)
@@ -231,8 +229,8 @@
self.assertEquals(w.edit_render(entity),
u'<input type="hidden" name="edits-salary:X" value="__cubicweb_internal_field__"/>\n'
'<input type="text" name="salary:X" value="" accesskey="s" id="salary:X" maxlength="15" size="5" tabindex="0"/>')
-
-
+
+
def test_float_widget_previous_value(self):
w = self.get_widget('Personne', 'salary', 'Float')
self.assertEquals(w.name, 'salary')
@@ -314,7 +312,7 @@
self.assertTextEquals(w.edit_render(entity),
u'<input type="hidden" name="edits-nom:X" value="__cubicweb_internal_field__"/>\n'
u'<input type="text" name="nom:X" value="" cubicweb:dataurl="http://testing.fr/cubicweb/json?pageid=None&mode=remote&fname=getnames" class="widget required" id="nom:X" tabindex="0" cubicweb:loadtype="auto" cubicweb:wdgtype="SuggestField" cubicweb:accesskey="n" cubicweb:maxlength="64" cubicweb:size="40" />')
-
+
finally:
del entity.widgets['nom']
@@ -337,7 +335,7 @@
self.assertTextEquals(w.edit_render(entity),
u'<input type="hidden" name="edits-nom:X" value="__cubicweb_internal_field__"/>\n'
u'<input type="text" name="nom:X" value="a name" cubicweb:dataurl="http://testing.fr/cubicweb/json?pageid=None&mode=remote&fname=getnames" class="widget required" id="nom:X" tabindex="0" cubicweb:loadtype="auto" cubicweb:wdgtype="SuggestField" cubicweb:accesskey="n" cubicweb:maxlength="64" cubicweb:size="40" />')
-
+
finally:
del entity.widgets['nom']
@@ -365,7 +363,7 @@
entity.autocomplete_initfuncs = {'nom' : 'getnames'}
w = self.get_widget(entity, 'travaille', 'Societe')
self.failUnless(isinstance(w, AutoCompletionWidget))
-
-
+
+
if __name__ == '__main__':
unittest_main()
--- a/web/uicfg.py Thu May 14 18:12:45 2009 +0200
+++ b/web/uicfg.py Mon May 18 10:09:06 2009 +0200
@@ -72,7 +72,7 @@
# primary view configuration ##################################################
def dual_role(role):
- return 'object' if role == 'subject' else 'subject'
+ return role == 'subject' and 'object' or 'subject'
def card_from_role(card, role):
if role == 'subject':
--- a/web/views/apacherewrite.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/apacherewrite.py Mon May 18 10:09:06 2009 +0200
@@ -28,7 +28,7 @@
def match(self, **kwargs):
self._match = self.condition.match(kwargs[self.match_part])
return not self._match is None
-
+
def action_rewrite(self, path):
for rgx, replace in self.rules:
if not rgx.match(path) is None:
@@ -45,7 +45,7 @@
def action_stop(self, path):
return path
-
+
class ApacheURLRewrite(Component):
"""inherit from this class with actual rules to activate apache style rewriting
@@ -69,24 +69,24 @@
RewriteRule ^/(data/.*) http://localhost:8080/$1 [L,P]
RewriteRule ^/(json.*) http://localhost:8080/$1 [L,P]
RewriteRule ^/(.*) http://localhost:8080/m_%1/$1 [L,P]
-
+
could be written (considering that no "host rewritting" is necessary):
- class MyAppRules(ApacheURLRewrite):
+ class MyAppRules(ApacheURLRewrite):
rules = [
RewriteCond('logilab\.fr', match='host',
rules=[('/(.*)', r'http://www.logilab.fr/\1')],
action='redirect'),
RewriteCond('(www)\.logilab\.fr', match='host', action='stop'),
RewriteCond('/(data|json)/', match='path', action='stop'),
- RewriteCond('(?P<cat>.*)\.logilab\.fr', match='host',
+ RewriteCond('(?P<cat>.*)\.logilab\.fr', match='host',
rules=[('/(.*)', r'/m_%(cat)s/\1')]),
]
"""
__abstract__ = True
id = 'urlrewriter'
rules = []
-
+
def rewrite(self, host, path):
for cond in self.rules:
if cond.match(host=host, path=path):
--- a/web/views/baseforms.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/baseforms.py Mon May 18 10:09:06 2009 +0200
@@ -24,8 +24,8 @@
from cubicweb.web.views.autoform import AutomaticEntityForm
_ = unicode
-
-
+
+
class EditionForm(FormMixIn, EntityView):
"""primary entity edition form
@@ -34,14 +34,14 @@
name of the attribute being edited. You may use this feature to compute
dynamic default values such as the 'tomorrow' date or the user's login
being connected
- """
+ """
id = 'edition'
__select__ = one_line_rset() & non_final_entity()
title = _('edition')
controller = 'edit'
skip_relations = set()
-
+
EDITION_BODY = u'''\
%(errormsg)s
<form id="%(formid)s" class="entityForm" cubicweb:target="eformframe"
@@ -135,7 +135,7 @@
@property
def formid(self):
return self.id
-
+
def action_title(self, entity):
"""form's title"""
ptitle = self.req._(self.title)
@@ -155,7 +155,7 @@
output.append(u'<input type="hidden" name="%s" value="%s" />'
% (name, value))
return u'\n'.join(output)
-
+
def add_hidden_web_behaviour_params(self, entity):
"""inserts hidden params controlling how errors and redirection
should be handled
@@ -174,8 +174,8 @@
self._hiddens.append( ('__linkto', linkto, '') )
msg = '%s %s' % (msg, self.req._('and linked'))
self._hiddens.append( ('__message', msg, '') )
-
-
+
+
def attributes_form(self, entity, kwargs, include_eid=True):
"""create a form to edit entity's attributes"""
html = []
@@ -208,7 +208,7 @@
# XXX both (add, delete)
return [(rschema, x) for rschema, _, x in entity.relations_by_category(('primary', 'secondary'), 'add')
if rschema != 'eid']
-
+
def relations_form(self, entity, kwargs):
srels_by_cat = entity.srelations_by_category(('generic', 'metadata'), 'add')
if not srels_by_cat:
@@ -267,7 +267,7 @@
w(u'</table>')
w(u'</fieldset>')
return '\n'.join(html)
-
+
def inline_entities_form(self, entity, kwargs):
"""create a form to edit entity's inlined relations"""
result = []
@@ -286,7 +286,7 @@
existant = entity.has_eid() and entity.related(rschema)
if existant:
# display inline-edition view for all existing related entities
- result.append(self.view('inline-edition', existant,
+ result.append(self.view('inline-edition', existant,
ptype=entity.e_schema, peid=entity.eid,
rtype=rschema, role=x, **kwargs))
if x == 'subject':
@@ -318,7 +318,7 @@
return '\n'.join(result)
# should_* method extracted to allow overriding
-
+
def should_inline_relation_form(self, entity, rschema, targettype, role):
return AutomaticEntityForm.rinlined.etype_get(entity.id, rschema, role,
targettype)
@@ -328,10 +328,10 @@
def should_display_add_inline_relation_link(self, rschema, existant, card):
return not existant or card in '+*'
-
+
def reset_url(self, entity):
return entity.absolute_url()
-
+
def on_submit(self, entity):
return u'return freezeFormButtons(\'%s\')' % (self.domid)
@@ -339,7 +339,7 @@
return self.req._('element edited')
-
+
class CreationForm(EditionForm):
__select__ = specified_etype_implements('Any')
# XXX bw compat, use View.registered since we don't want accept_compat
@@ -347,7 +347,7 @@
registered = accepts_etype_compat(View.registered)
id = 'creation'
title = _('creation')
-
+
def call(self, **kwargs):
"""creation view for an entity"""
self.req.add_js( ('cubicweb.ajax.js',) )
@@ -385,16 +385,16 @@
@property
def formid(self):
return 'edition'
-
+
def relations_form(self, entity, kwargs):
return u''
def reset_url(self, entity=None):
return self.build_url(self.req.form.get('etype', '').lower())
-
+
def submited_message(self):
return self.req._('element created')
-
+
def url(self):
"""return the url associated with this view"""
return self.create_url(self.req.form.get('etype'))
@@ -405,21 +405,21 @@
@cached
def card(self, etype):
return self.rschema.rproperty(self.parent_schema, etype, 'cardinality')[0]
-
+
def action_title(self, entity):
return self.rschema.display_name(self.req, self.role)
-
+
def add_hidden_web_behaviour_params(self, entity):
pass
-
+
def edit_form(self, entity, ptype, peid, rtype,
role='subject', **kwargs):
self.rschema = self.schema.rschema(rtype)
- self.role = role
+ self.role = role
self.parent_schema = self.schema.eschema(ptype)
self.parent_eid = peid
super(InlineFormMixIn, self).edit_form(entity, kwargs)
-
+
def should_inline_relation_form(self, entity, rschema, targettype, role):
if rschema == self.rschema:
return False
@@ -455,7 +455,7 @@
}
ctx.update(local_ctx)
return ctx
-
+
class CopyEditionForm(EditionForm):
id = 'copy'
@@ -465,7 +465,7 @@
self.req.add_js(('cubicweb.ajax.js',))
entity = self.complete_entity(row, col, skip_bytes=True)
# make a copy of entity to avoid altering the entity in the
- # request's cache.
+ # request's cache.
self.newentity = copy(entity)
self.copying = self.newentity.eid
self.newentity.eid = None
@@ -482,23 +482,23 @@
@property
def formid(self):
return 'edition'
-
+
def relations_form(self, entity, kwargs):
return u''
def reset_url(self, entity):
return self.build_url('view', rql='Any X WHERE X eid %s' % self.copying)
-
+
def attributes_form(self, entity, kwargs, include_eid=True):
# we don't want __clone_eid on inlined edited entities
if entity.eid == self.newentity.eid:
self._hiddens.append((eid_param('__cloned_eid', entity.eid), self.copying, ''))
return EditionForm.attributes_form(self, entity, kwargs, include_eid)
-
+
def submited_message(self):
return self.req._('element copied')
-
-
+
+
class TableEditForm(FormMixIn, EntityView):
id = 'muledit'
title = _('multiple edit')
@@ -526,7 +526,7 @@
</td>
</tr>
</table>
- </fieldset>
+ </fieldset>
</form>
'''
@@ -535,7 +535,7 @@
%(error)s
<div>%(widget)s</div>
</td>'''
-
+
def call(self, **kwargs):
"""a view to edit multiple entities of the same type
the first column should be the eid
@@ -560,13 +560,13 @@
'oktitle': _('validate modifications on selected items').capitalize(),
'cancelvalue': _('button_reset').capitalize(),
'canceltitle': _('revert changes').capitalize(),
- }
+ }
self.w(self.EDITION_BODY % ctx)
-
-
+
+
def reset_url(self, entity=None):
self.build_url('view', rql=self.rset.printable_rql())
-
+
def edit_form(self, entity):
html = []
w = html.append
--- a/web/views/calendar.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/calendar.py Mon May 18 10:09:06 2009 +0200
@@ -13,7 +13,6 @@
from cubicweb.selectors import implements
from cubicweb.utils import strptime, date_range, todate, todatetime
from cubicweb.view import EntityView
-from cubicweb.web import ajax_replace_url
_ = unicode
@@ -164,13 +163,15 @@
else:
user = None
the_dates = []
- tstart = todate(task.start)
+ tstart = task.start
if tstart:
+ tstart = todate(task.start)
if tstart > lastday:
continue
the_dates = [tstart]
- tstop = todate(task.start)
+ tstop = task.stop
if tstop:
+ tstop = todate(tstop)
if tstop < firstday:
continue
the_dates = [tstop]
@@ -260,10 +261,12 @@
prevdate = curdate - timedelta(31)
nextdate = curdate + timedelta(31)
rql = self.rset.printable_rql()
- prevlink = ajax_replace_url('onemonthcalid', rql, 'onemonthcal',
- year=prevdate.year, month=prevdate.month)
- nextlink = ajax_replace_url('onemonthcalid', rql, 'onemonthcal',
- year=nextdate.year, month=nextdate.month)
+ prevlink = self.req.build_ajax_replace_url('onemonthcalid', rql, 'onemonthcal',
+ year=prevdate.year,
+ month=prevdate.month)
+ nextlink = self.req.build_ajax_replace_url('onemonthcalid', rql, 'onemonthcal',
+ year=nextdate.year,
+ month=nextdate.month)
return prevlink, nextlink
def _build_calendar_cell(self, celldate, rows, curdate):
@@ -348,13 +351,15 @@
continue
done_tasks.append(task)
the_dates = []
- tstart = todate(task.start)
- tstop = todate(task.stop)
+ tstart = task.start
+ tstop = task.stop
if tstart:
+ tstart = todate(tstart)
if tstart > lastday:
continue
the_dates = [tstart]
if tstop:
+ tstop = todate(tstop)
if tstop < firstday:
continue
the_dates = [tstop]
@@ -513,9 +518,11 @@
prevdate = curdate - timedelta(7)
nextdate = curdate + timedelta(7)
rql = self.rset.printable_rql()
- prevlink = ajax_replace_url('oneweekcalid', rql, 'oneweekcal',
- year=prevdate.year, week=prevdate.isocalendar()[1])
- nextlink = ajax_replace_url('oneweekcalid', rql, 'oneweekcal',
- year=nextdate.year, week=nextdate.isocalendar()[1])
+ prevlink = self.req.build_ajax_replace_url('oneweekcalid', rql, 'oneweekcal',
+ year=prevdate.year,
+ week=prevdate.isocalendar()[1])
+ nextlink = self.req.build_ajax_replace_url('oneweekcalid', rql, 'oneweekcal',
+ year=nextdate.year,
+ week=nextdate.isocalendar()[1])
return prevlink, nextlink
--- a/web/views/debug.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/debug.py Mon May 18 10:09:06 2009 +0200
@@ -23,7 +23,7 @@
html_escape(str(key)), html_escape(repr(dict[key]))))
w(u'</ul>')
-
+
class DebugView(StartupView):
id = 'debug'
__select__ = none_rset() & match_user_groups('managers')
--- a/web/views/editcontroller.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/editcontroller.py Mon May 18 10:09:06 2009 +0200
@@ -1,7 +1,7 @@
"""The edit controller, handling form submitting.
: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"
--- a/web/views/embedding.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/embedding.py Mon May 18 10:09:06 2009 +0200
@@ -29,7 +29,7 @@
"""template embeding an external web pages into CubicWeb web interface
"""
id = 'external'
-
+
def call(self, body):
# XXX fallback to HTML 4 mode when embeding ?
self.set_request_content_type()
@@ -92,12 +92,12 @@
"""
id = 'embed'
__select__ = (one_line_rset() & match_search_state('normal')
- & implements(IEmbedable)
+ & implements(IEmbedable)
& score_entity(entity_has_embedable_url))
-
+
title = _('embed')
controller = 'embed'
-
+
def url(self, row=0):
entity = self.rset.get_entity(row, 0)
url = urljoin(self.req.base_url(), entity.embeded_url())
@@ -119,7 +119,7 @@
def __init__(self, prefix, custom_css=None):
self.prefix = prefix
self.custom_css = custom_css
-
+
def __call__(self, match):
original_url = match.group(1)
url = self.prefix + urlquote(original_url, safe='')
@@ -136,7 +136,7 @@
self.embedded_url = embedded_url
self.tag = tag
self.custom_css = custom_css
-
+
def __call__(self, match):
original_url = match.group(1)
if '://' in original_url:
--- a/web/views/error.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/error.py Mon May 18 10:09:06 2009 +0200
@@ -24,5 +24,3 @@
_ = self.req._
self.w(u"<h1>%s</h1>" %
_('an error occured, the request cannot be fulfilled'))
-
-
--- a/web/views/facets.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/facets.py Mon May 18 10:09:06 2009 +0200
@@ -22,7 +22,7 @@
**kwargs):
if view and getattr(view, 'filter_box_context_info', lambda: None)():
return 1
- return 0
+ return 0
class FilterBox(BoxTemplate):
@@ -42,7 +42,7 @@
be used by the facet
"""
return {}
-
+
def _get_context(self, view):
context = getattr(view, 'filter_box_context_info', lambda: None)()
if context:
@@ -52,7 +52,7 @@
vid, divid = None, 'pageContent'
paginate = view and view.need_navigation
return rset, vid, divid, paginate
-
+
def call(self, view=None):
req = self.req
req.add_js( ('cubicweb.ajax.js', 'cubicweb.formfilter.js') )
@@ -109,7 +109,7 @@
return self.vreg.possible_vobjects('facets', self.req, rset,
context='facetbox',
filtered_variable=mainvar)
-
+
# facets ######################################################################
class CreatedByFacet(RelationFacet):
@@ -144,7 +144,7 @@
"""
etypes = self.rset.column_types(0)
return sorted((self.req._(etype), etype) for etype in etypes)
-
+
def add_rql_restrictions(self):
"""add restriction for this facet into the rql syntax tree"""
value = self.req.form.get(self.id)
@@ -162,7 +162,7 @@
@property
def title(self):
return self.req._('has_text')
-
+
def get_widget(self):
"""return the widget instance to use to display this facet
--- a/web/views/ibreadcrumbs.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/ibreadcrumbs.py Mon May 18 10:09:06 2009 +0200
@@ -21,7 +21,7 @@
def bc_title(entity):
textsize = entity.req.property_value('navigation.short-line-size')
return html_escape(cut(entity.dc_title(), textsize))
-
+
class BreadCrumbEntityVComponent(EntityVComponent):
id = 'breadcrumbs'
@@ -52,7 +52,7 @@
self.w(u"\n")
self.wpath_part(parent, entity, i == len(path) - 1)
self.w(u'</span>')
-
+
def wpath_part(self, part, contextentity, last=False):
if isinstance(part, Entity):
if last and part.eid == contextentity.eid:
@@ -67,7 +67,7 @@
else:
textsize = self.req.property_value('navigation.short-line-size')
self.w(cut(unicode(part), textsize))
-
+
class BreadCrumbComponent(BreadCrumbEntityVComponent):
__registry__ = 'components'
--- a/web/views/management.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/management.py Mon May 18 10:09:06 2009 +0200
@@ -33,7 +33,7 @@
_("permission"), _('granted to groups'), _('rql expressions')))
for access_type in access_types:
w(u'<tr>')
- w(u'<td>%s</td>' % _('%s_perm' % access_type))
+ w(u'<td>%s</td>' % self.req.__('%s_perm' % access_type))
groups = eschema.get_groups(access_type)
l = []
groups = [(_(group), group) for group in groups]
--- a/web/views/owl.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/owl.py Mon May 18 10:09:06 2009 +0200
@@ -14,7 +14,7 @@
_ = unicode
-OWL_CARD_MAP = {'1': '<rdf:type rdf:resource="&owl;FunctionalProperty"/>',
+OWL_CARD_MAP = {'1': '<rdf:type rdf:resource="&owl;FunctionalProperty"/>',
'?': '<owl:maxCardinality rdf:datatype="&xsd;int">1</owl:maxCardinality>',
'+': '<owl:minCardinality rdf:datatype="&xsd;int">1</owl:minCardinality>',
'*': ''
@@ -37,7 +37,7 @@
<!DOCTYPE rdf:RDF [
<!ENTITY owl "http://www.w3.org/2002/07/owl#" >
<!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" >
-]>
+]>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
@@ -48,7 +48,7 @@
<owl:Ontology rdf:about="">
<rdfs:comment>
- %(appid)s Cubicweb OWL Ontology
+ %(appid)s Cubicweb OWL Ontology
</rdfs:comment>
</owl:Ontology>'''
@@ -71,7 +71,7 @@
self.visit_schema(skipmeta=skipmeta)
if writeprefix:
self.w(OWL_CLOSING_ROOT)
-
+
def visit_schema(self, skiprels=DEFAULT_SKIP_RELS, skipmeta=True):
"""get a layout for a whole schema"""
entities = sorted([eschema for eschema in self.schema.entities()
@@ -89,8 +89,8 @@
def visit_entityschema(self, eschema, skiprels=()):
"""get a layout for an entity OWL schema"""
- self.w(u'<owl:Class rdf:ID="%s">'% eschema)
- self.w(u'<!-- relations -->')
+ self.w(u'<owl:Class rdf:ID="%s">'% eschema)
+ self.w(u'<!-- relations -->')
for rschema, targetschemas, role in eschema.relation_definitions():
if rschema.type in skiprels:
continue
@@ -113,7 +113,7 @@
''' % (label, cardtag))
self.w(u'<!-- attributes -->')
-
+
for rschema, aschema in eschema.attribute_definitions():
if not (rschema.has_local_role('read') or rschema.has_perm(self.req, 'read')):
continue
@@ -125,10 +125,10 @@
<owl:onProperty rdf:resource="#%s"/>
<rdf:type rdf:resource="&owl;FunctionalProperty"/>
</owl:Restriction>
-</rdfs:subClassOf>'''
+</rdfs:subClassOf>'''
% aname)
self.w(u'</owl:Class>')
-
+
def visit_property_schema(self, eschema, skiprels=()):
"""get a layout for property entity OWL schema"""
for rschema, targetschemas, role in eschema.relation_definitions():
@@ -141,7 +141,7 @@
self.w(u'''<owl:ObjectProperty rdf:ID="%s">
<rdfs:domain rdf:resource="#%s"/>
<rdfs:range rdf:resource="#%s"/>
-</owl:ObjectProperty>
+</owl:ObjectProperty>
''' % (label, eschema, oeschema.type))
def visit_property_object_schema(self, eschema):
@@ -157,15 +157,15 @@
</owl:DatatypeProperty>'''
% (aname, eschema, OWL_TYPE_MAP[aschema.type]))
-
+
class OWLABOXView(EntityView):
'''This view represents a part of the ABOX for a given entity.'''
-
+
id = 'owlabox'
title = _('owlabox')
templatable = False
content_type = 'application/xml' # 'text/xml'
-
+
def call(self):
self.w(OWL_OPENING_ROOT % {'appid': self.schema.name})
for i in xrange(self.rset.rowcount):
@@ -175,9 +175,9 @@
def cell_call(self, row, col, skiprels=DEFAULT_SKIP_RELS):
self.wview('owlaboxitem', self.rset, row=row, col=col, skiprels=skiprels)
-
+
class OWLABOXItemView(EntityView):
- '''This view represents a part of the ABOX for a given entity.'''
+ '''This view represents a part of the ABOX for a given entity.'''
id = 'owlaboxitem'
templatable = False
content_type = 'application/xml' # 'text/xml'
@@ -208,9 +208,9 @@
if not (rschema.has_local_role('read') or rschema.has_perm(self.req, 'read')):
continue
if role == 'object':
- attr = 'reverse_%s' % rschema.type
+ attr = 'reverse_%s' % rschema.type
else:
- attr = rschema.type
+ attr = rschema.type
for x in getattr(entity, attr):
self.w(u'<%s>%s %s</%s>' % (attr, x.id, x.eid, attr))
self.w(u'</%s>'% eschema)
@@ -219,10 +219,9 @@
class DownloadOWLSchemaAction(Action):
id = 'download_as_owl'
__select__ = none_rset() & match_view('schema')
-
+
category = 'mainactions'
title = _('download schema as owl')
-
+
def url(self):
return self.build_url('view', vid='owl')
-
--- a/web/views/searchrestriction.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/searchrestriction.py Mon May 18 10:09:06 2009 +0200
@@ -2,7 +2,7 @@
a search
: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"
--- a/web/views/sessions.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/sessions.py Mon May 18 10:09:06 2009 +0200
@@ -13,7 +13,7 @@
class InMemoryRepositorySessionManager(AbstractSessionManager):
"""manage session data associated to a session identifier"""
-
+
def __init__(self):
AbstractSessionManager.__init__(self)
# XXX require a RepositoryAuthenticationManager which violates
@@ -23,7 +23,7 @@
def current_sessions(self):
return self._sessions.values()
-
+
def get_session(self, req, sessionid):
"""return existing session for the given session identifier"""
if not sessionid in self._sessions:
@@ -47,13 +47,13 @@
def open_session(self, req):
"""open and return a new session for the given request
-
+
:raise ExplicitLogin: if authentication is required
"""
session = self.authmanager.authenticate(req)
self._sessions[session.sessionid] = session
return session
-
+
def close_session(self, session):
"""close session on logout or on invalid session detected (expired out,
corrupted...)
@@ -66,4 +66,3 @@
# already closed, may occurs if the repository session expired but
# not the web session
pass
-
--- a/web/views/tabs.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/tabs.py Mon May 18 10:09:06 2009 +0200
@@ -164,7 +164,7 @@
"""
__select__ = EntityView.__select__ & partial_has_related_entities()
vid = 'list'
-
+
def cell_call(self, row, col):
rset = self.entity(row, col).related(self.rtype, role(self))
self.w(u'<div class="mainInfo">')
--- a/web/views/treeview.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/treeview.py Mon May 18 10:09:06 2009 +0200
@@ -1,22 +1,23 @@
"""Set of tree-building widgets, based on jQuery treeview plugin
:organization: Logilab
-:copyright: 2008-2009 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"
+from logilab.common.decorators import monkeypatch
from logilab.mtconverter import html_escape
+from cubicweb.utils import make_uid
from cubicweb.interfaces import ITree
from cubicweb.selectors import implements
from cubicweb.view import EntityView
-from cubicweb.utils import make_uid
+from cubicweb.web.views.basecontrollers import JSonController
def treecookiename(treeid):
return str('treestate-%s' % treeid)
-
class TreeView(EntityView):
id = 'treeview'
itemvid = 'treeitemview'
@@ -25,27 +26,23 @@
def call(self, subvid=None, treeid=None, initial_load=True):
if subvid is None:
- if 'subvid' in self.req.form:
- subvid = self.req.form.pop('subvid') # consume it
- else:
- subvid = 'oneline'
+ subvid = self.req.form.pop('subvid', 'oneline') # consume it
if treeid is None:
- if 'treeid' in self.req.form:
- treeid = self.req.form.pop('treeid')
- else:
+ treeid = self.req.form.pop('treeid', None)
+ if treeid is None:
+ self.warning('Tree state won\'t be properly restored after next reload')
treeid = make_uid('throw away uid')
- self.warning('Tree state won\'t be properly restored after next reload')
- if initial_load:
+ self.w(u'<ul id="tree-%s" class="%s">' % (treeid, self.css_classes))
+ for rowidx in xrange(len(self.rset)):
+ self.wview(self.itemvid, self.rset, row=rowidx, col=0,
+ vid=subvid, parentvid=self.id, treeid=treeid)
+ self.w(u'</ul>')
+ if initial_load and not self.req.form.get('fname'):
self.req.add_css('jquery.treeview.css')
self.req.add_js(('cubicweb.ajax.js', 'jquery.treeview.js'))
self.req.html_headers.add_onload(u"""
jQuery("#tree-%s").treeview({toggle: toggleTree, prerendered: true});""" % treeid)
- self.w(u'<ul id="tree-%s" class="%s">' % (treeid, self.css_classes))
- for rowidx in xrange(len(self.rset)):
- self.wview(self.itemvid, self.rset, row=rowidx, col=0,
- vid=subvid, parentvid=self.id)
- self.w(u'</ul>')
-
+
class FileTreeView(TreeView):
"""specific version of the treeview to display file trees
@@ -57,8 +54,6 @@
def call(self, subvid=None, treeid=None, initial_load=True):
super(FileTreeView, self).call(treeid=treeid, subvid='filetree-oneline', initial_load=initial_load)
-
-
class FileItemInnerView(EntityView):
"""inner view used by the TreeItemView instead of oneline view
@@ -70,17 +65,18 @@
def cell_call(self, row, col):
entity = self.entity(row, col)
if ITree.is_implemented_by(entity.__class__) and not entity.is_leaf():
- self.w(u'<div class="folder">%s</div>' % entity.view('oneline'))
+ self.w(u'<div class="folder">%s</div>\n' % entity.view('oneline'))
else:
# XXX define specific CSS classes according to mime types
- self.w(u'<div class="file">%s</div>' % entity.view('oneline'))
+ self.w(u'<div class="file">%s</div>\n' % entity.view('oneline'))
class DefaultTreeViewItemView(EntityView):
"""default treeitem view for entities which don't implement ITree"""
id = 'treeitemview'
-
- def cell_call(self, row, col, vid='oneline', parentvid='treeview'):
+
+ def cell_call(self, row, col, vid='oneline', parentvid='treeview', treeid=None):
+ assert treeid is not None
entity = self.entity(row, col)
itemview = self.view(vid, self.rset, row=row, col=col)
if row == len(self.rset) - 1:
@@ -95,33 +91,79 @@
(each item should be expandable if it's not a tree leaf)
"""
id = 'treeitemview'
- __select__ = implements(ITree)
-
- def cell_call(self, row, col, vid='oneline', parentvid='treeview'):
+ __select__ = EntityView.__select__ & implements(ITree) # XXX
+
+ def open_state(self, eeid, treeid):
+ cookies = self.req.get_cookie()
+ treestate = cookies.get(treecookiename(treeid))
+ if treestate:
+ return str(eeid) in treestate.value.split(';')
+ return False
+
+ def cell_call(self, row, col, treeid, vid='oneline', parentvid='treeview'):
+ w = self.w
entity = self.entity(row, col)
- cssclasses = []
- is_leaf = False
- if row == len(self.rset) - 1:
- is_leaf = True
+ liclasses = []
+ is_last = row == len(self.rset) - 1
+ is_open = self.open_state(entity.eid, treeid)
if not hasattr(entity, 'is_leaf') or entity.is_leaf():
- if is_leaf : cssclasses.append('last')
- self.w(u'<li class="%s">' % u' '.join(cssclasses))
+ if is_last:
+ liclasses.append('last')
+ w(u'<li class="%s">' % u' '.join(liclasses))
else:
rql = entity.children_rql() % {'x': entity.eid}
url = html_escape(self.build_url('json', rql=rql, vid=parentvid,
pageid=self.req.pageid,
- subvid=vid,
- noautoload=True))
- cssclasses.append('expandable')
- divclasses = ['hitarea expandable-hitarea']
- if is_leaf :
- cssclasses.append('lastExpandable')
- divclasses.append('lastExpandable-hitarea')
- self.w(u'<li cubicweb:loadurl="%s" class="%s">' % (url, u' '.join(cssclasses)))
- self.w(u'<div class="%s"> </div>' % u' '.join(divclasses))
+ treeid=treeid,
+ fname='view',
+ subvid=vid))
+ divclasses = ['hitarea']
+ if is_open:
+ liclasses.append('collapsable')
+ divclasses.append('collapsable-hitarea')
+ else:
+ liclasses.append('expandable')
+ divclasses.append('expandable-hitarea')
+ if is_last:
+ if is_open:
+ liclasses.append('lastCollapsable')
+ divclasses.append('lastCollapsable-hitarea')
+ else:
+ liclasses.append('lastExpandable')
+ divclasses.append('lastExpandable-hitarea')
+ if is_open:
+ w(u'<li class="%s">' % u' '.join(liclasses))
+ else:
+ w(u'<li cubicweb:loadurl="%s" class="%s">' % (url, u' '.join(liclasses)))
+ divtail = """ onclick="asyncRemoteExec('node_clicked', '%s', '%s')" """ %\
+ (treeid, entity.eid)
+ w(u'<div class="%s"%s></div>' % (u' '.join(divclasses), divtail))
+
# add empty <ul> because jquery's treeview plugin checks for
# sublists presence
- self.w(u'<ul class="placeholder"><li>place holder</li></ul>')
+ if not is_open:
+ w(u'<ul class="placeholder"><li>place holder</li></ul>')
+ # the local node info
self.wview(vid, self.rset, row=row, col=col)
- self.w(u'</li>')
+ if is_open: # => not leaf => rql is defined
+ self.wview(parentvid, self.req.execute(rql), treeid=treeid, initial_load=False)
+ w(u'</li>')
+
+@monkeypatch(JSonController)
+def js_node_clicked(self, treeid, nodeeid):
+ """add/remove eid in treestate cookie"""
+ cookies = self.req.get_cookie()
+ statename = treecookiename(treeid)
+ treestate = cookies.get(statename)
+ if treestate is None:
+ cookies[statename] = nodeeid
+ self.req.set_cookie(cookies, statename)
+ else:
+ marked = set(filter(None, treestate.value.split(';')))
+ if nodeeid in marked:
+ marked.remove(nodeeid)
+ else:
+ marked.add(nodeeid)
+ cookies[statename] = ';'.join(marked)
+ self.req.set_cookie(cookies, statename)
--- a/web/views/urlpublishing.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/urlpublishing.py Mon May 18 10:09:06 2009 +0200
@@ -35,7 +35,7 @@
"""exception used by url evaluators to notify they can't evaluate
a path
"""
-
+
class URLPublisherComponent(Component):
"""associate url's path to view identifier / rql queries,
by applying a chain of urlpathevaluator components.
@@ -50,33 +50,33 @@
something else than `PathDontMatch` will stop the handlers chain.
"""
id = 'urlpublisher'
-
+
def __init__(self, default_method='view'):
super(URLPublisherComponent, self).__init__()
self.default_method = default_method
- evaluators = []
+ evaluators = []
for evaluatorcls in self.vreg.registry_objects('components',
'urlpathevaluator'):
# instantiation needed
evaluator = evaluatorcls(self)
evaluators.append(evaluator)
self.evaluators = sorted(evaluators, key=lambda x: x.priority)
-
+
def process(self, req, path):
"""given an url (essentialy caracterized by a path on the server,
but additional information may be found in the request object), return
a publishing method identifier (eg controller) and an optional result
set
-
+
:type req: `cubicweb.web.Request`
:param req: the request object
-
+
:type path: str
:param path: the path of the resource to publish
:rtype: tuple(str, `cubicweb.common.utils.ResultSet` or None)
:return: the publishing method identifier and an optional result set
-
+
:raise NotFound: if no handler is able to decode the given path
"""
parts = [part for part in path.split('/')
@@ -97,7 +97,7 @@
pmid = self.default_method
return pmid, rset
-
+
class URLPathEvaluator(Component):
__abstract__ = True
id = 'urlpathevaluator'
@@ -136,7 +136,7 @@
raise NotFound()
return None, rset
-
+
class RestPathEvaluator(URLPathEvaluator):
"""handle path with the form::
@@ -149,7 +149,7 @@
for etype in self.schema.entities():
etype = str(etype)
self.etype_map[etype.lower()] = etype
-
+
def evaluate_path(self, req, parts):
if not (0 < len(parts) < 4):
raise PathDontMatch()
@@ -177,7 +177,7 @@
def cls_rset(self, req, cls):
return req.execute(cls.fetch_rql(req.user))
-
+
def attr_rset(self, req, etype, attrname, value):
rql = u'Any X WHERE X is %s, X %s %%(x)s' % (etype, attrname)
if attrname == 'eid':
@@ -211,7 +211,7 @@
except KeyError:
continue
raise PathDontMatch()
-
+
class ActionPathEvaluator(URLPathEvaluator):
"""handle path with the form::
--- a/web/views/vcard.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/vcard.py Mon May 18 10:09:06 2009 +0200
@@ -9,7 +9,7 @@
from cubicweb.selectors import implements
from cubicweb.view import EntityView
-_ = unicode
+_ = unicode
VCARD_PHONE_TYPES = {'home': 'HOME', 'office': 'WORK', 'mobile': 'CELL', 'fax': 'FAX'}
@@ -19,12 +19,12 @@
title = _('vcard')
templatable = False
content_type = 'text/x-vcard'
- __select__ = implements('CWUser')
+ __select__ = implements('CWUser')
def set_request_content_type(self):
"""overriden to set a .vcf filename"""
self.req.set_content_type(self.content_type, filename='vcard.vcf')
-
+
def cell_call(self, row, col):
self.vcard_header()
self.vcard_content(self.complete_entity(row, col))
@@ -33,11 +33,11 @@
def vcard_header(self):
self.w(u'BEGIN:vcard\n')
self.w(u'VERSION:3.0\n')
-
+
def vcard_footer(self):
self.w(u'NOTE:this card has been generated by CubicWeb\n')
self.w(u'END:vcard\n')
-
+
def vcard_content(self, entity):
who = u'%s %s' % (entity.surname or '',
entity.firstname or '')
--- a/web/views/wdoc.py Thu May 14 18:12:45 2009 +0200
+++ b/web/views/wdoc.py Mon May 18 10:09:06 2009 +0200
@@ -53,7 +53,7 @@
node = index[section.attrib['appendto']]
idx = None
return node, idx
-
+
def build_toc(config):
alltocfiles = reversed(tuple(config.locate_all_files('toc.xml')))
maintoc = parse(alltocfiles.next()).getroot()
@@ -61,7 +61,7 @@
index = {}
build_toc_index(maintoc, index)
# insert component documentation into the tree according to their toc.xml
- # file
+ # file
for fpath in alltocfiles:
toc = parse(fpath).getroot()
for section in toc:
@@ -73,7 +73,7 @@
section.parent = node
build_toc_index(section, index)
return index
-
+
def title_for_lang(node, lang):
for title in node.findall('title'):
if title.attrib['{http://www.w3.org/XML/1998/namespace}lang'] == lang:
@@ -88,7 +88,7 @@
__select__ = match_form_params('fid')
id = 'wdoc'
title = _('site documentation')
-
+
def call(self):
fid = self.req.form['fid']
for lang in chain((self.req.lang, self.vreg.property_value('ui.language')),
@@ -107,7 +107,7 @@
else:
self.navigation_links(node)
self.w(u'<div class="hr"></div>')
- self.w(u'<h1>%s</h1>' % (title_for_lang(node, self.req.lang)))
+ self.w(u'<h1>%s</h1>' % (title_for_lang(node, self.req.lang)))
data = open(join(resourcedir, rid)).read()
self.w(rest_publish(self, data))
if node is not None:
@@ -124,17 +124,17 @@
self.w(u'<div class="docnav">\n')
previousidx = brothers.index(node) - 1
if previousidx >= 0:
- self.navsection(brothers[previousidx], 'prev')
- self.navsection(parent, 'up')
+ self.navsection(brothers[previousidx], 'prev')
+ self.navsection(parent, 'up')
nextidx = brothers.index(node) + 1
if nextidx < len(brothers):
- self.navsection(brothers[nextidx], 'next')
+ self.navsection(brothers[nextidx], 'next')
self.w(u'</div>\n')
navinfo = {'prev': ('', 'data/previous.png', _('i18nprevnext_previous')),
'next': ('', 'data/next.png', _('i18nprevnext_next')),
'up': ('', 'data/up.png', _('i18nprevnext_up'))}
-
+
def navsection(self, node, navtype):
htmlclass, imgpath, msgid = self.navinfo[navtype]
self.w(u'<span class="%s">' % htmlclass)
@@ -143,7 +143,7 @@
self.req.build_url('doc/'+node.attrib['resource']),
title_for_lang(node, self.req.lang)))
self.w(u'</span>\n')
-
+
def subsections_links(self, node, first=True):
sub = subsections(node)
if not sub:
@@ -158,7 +158,7 @@
self.subsections_links(child, False)
self.w(u'</li>')
self.w(u'</ul>\n')
-
+
class InlineHelpImageView(StartupView):
@@ -167,7 +167,7 @@
binary = True
templatable = False
content_type = 'image/png'
-
+
def call(self):
fid = self.req.form['fid']
for lang in chain((self.req.lang, self.vreg.property_value('ui.language')),
@@ -185,7 +185,7 @@
id = 'changelog'
title = _('What\'s new?')
maxentries = 25
-
+
def call(self):
rid = 'ChangeLog_%s' % (self.req.lang)
allentries = []
@@ -234,4 +234,3 @@
break
w('') # blank line
self.w(rest_publish(self, '\n'.join(restdata)))
-
--- a/web/webconfig.py Thu May 14 18:12:45 2009 +0200
+++ b/web/webconfig.py Mon May 18 10:09:06 2009 +0200
@@ -22,7 +22,7 @@
('site-title',
{'type' : 'string', 'default': 'unset title',
'help': _('site title'),
- 'sitewide': True, 'group': 'ui',
+ 'sitewide': True, 'group': 'ui',
}),
('main-template',
{'type' : 'string', 'default': 'main-template',
@@ -54,7 +54,7 @@
'help': _('maximum number of entities to display in related combo box'),
'group': 'navigation',
}),
-
+
))
@@ -64,7 +64,7 @@
"""
cubicweb_vobject_path = CubicWebConfiguration.cubicweb_vobject_path | set(['web/views'])
cube_vobject_path = CubicWebConfiguration.cube_vobject_path | set(['views'])
-
+
options = merge_options(CubicWebConfiguration.options + (
('anonymous-user',
{'type' : 'string',
@@ -185,7 +185,7 @@
'interface\'s language according to browser defined preferences',
'group': 'web', 'inputlevel': 2,
}),
-
+
('print-traceback',
{'type' : 'yn',
'default': not CubicWebConfiguration.mode == 'installed',
@@ -206,17 +206,17 @@
def fckeditor_installed(self):
return exists(self.ext_resources['FCKEDITOR_PATH'])
-
+
def eproperty_definitions(self):
for key, pdef in super(WebConfiguration, self).eproperty_definitions():
if key == 'ui.fckeditor' and not self.fckeditor_installed():
continue
yield key, pdef
-
+
# method used to connect to the repository: 'inmemory' / 'pyro'
# Pyro repository by default
repo_method = 'pyro'
-
+
# don't use @cached: we want to be able to disable it while this must still
# be cached
def repository(self, vreg=None):
@@ -235,7 +235,7 @@
def vc_config(self):
return self.repository().get_versions()
-
+
# mapping to external resources (id -> path) (`external_resources` file) ##
ext_resources = {
'FAVICON': 'DATADIR/favicon.ico',
@@ -244,13 +244,13 @@
'HELP': 'DATADIR/help.png',
'CALENDAR_ICON': 'DATADIR/calendar.gif',
'SEARCH_GO':'DATADIR/go.png',
-
+
'FCKEDITOR_PATH': '/usr/share/fckeditor/',
-
+
'IE_STYLESHEETS': ['DATADIR/cubicweb.ie.css'],
'STYLESHEETS': ['DATADIR/cubicweb.css'],
'STYLESHEETS_PRINT': ['DATADIR/cubicweb.print.css'],
-
+
'JAVASCRIPTS': ['DATADIR/jquery.js',
'DATADIR/jquery.corner.js',
'DATADIR/jquery.json.js',
@@ -258,8 +258,8 @@
'DATADIR/cubicweb.python.js',
'DATADIR/cubicweb.htmlhelpers.js'],
}
-
-
+
+
def anonymous_user(self):
"""return a login and password to use for anonymous users. None
may be returned for both if anonymous connections are not allowed
@@ -272,7 +272,7 @@
if user is not None:
user = unicode(user)
return user, passwd
-
+
def has_resource(self, rid):
"""return true if an external resource is defined"""
return bool(self.ext_resources.get(rid))
@@ -281,19 +281,19 @@
def locate_resource(self, rid):
"""return the directory where the given resource may be found"""
return self._fs_locate(rid, 'data')
-
+
@cached
def locate_doc_file(self, fname):
"""return the directory where the given resource may be found"""
return self._fs_locate(fname, 'wdoc')
-
+
def _fs_locate(self, rid, rdirectory):
"""return the directory where the given resource may be found"""
path = [self.apphome] + self.cubes_path() + [join(self.shared_dir())]
for directory in path:
if exists(join(directory, rdirectory, rid)):
return join(directory, rdirectory)
-
+
def locate_all_files(self, rid, rdirectory='wdoc'):
"""return all files corresponding to the given resource"""
path = [self.apphome] + self.cubes_path() + [join(self.shared_dir())]
@@ -308,7 +308,7 @@
# load external resources definition
self._build_ext_resources()
self._init_base_url()
-
+
def _init_base_url(self):
# normalize base url(s)
baseurl = self['base-url']
@@ -341,11 +341,11 @@
# static files handling ###################################################
-
+
@property
def static_directory(self):
return join(self.appdatahome, 'static')
-
+
def static_file_exists(self, rpath):
return exists(join(self.static_directory, rpath))
@@ -365,4 +365,3 @@
def static_file_del(self, rpath):
if self.static_file_exists(rpath):
os.remove(join(self.static_directory, rpath))
-
--- a/web/webctl.py Thu May 14 18:12:45 2009 +0200
+++ b/web/webctl.py Mon May 18 10:09:06 2009 +0200
@@ -12,7 +12,7 @@
class WebCreateHandler(CommandHandler):
cmdname = 'create'
-
+
def bootstrap(self, cubes, inputlevel=0):
"""bootstrap this configuration"""
print '** generic web configuration'
@@ -23,9 +23,8 @@
print '-' * 72
config.input_config('pyro-client', inputlevel)
if confirm('allow anonymous access', False):
- config.global_set_option('anonymous-user', 'anon')
- config.global_set_option('anonymous-password', 'anon')
-
+ config.global_set_option('anonymous-user', 'anon')
+ config.global_set_option('anonymous-password', 'anon')
+
def postcreate(self):
"""hooks called once application's initialization has been completed"""
-
--- a/wsgi/__init__.py Thu May 14 18:12:45 2009 +0200
+++ b/wsgi/__init__.py Mon May 18 10:09:06 2009 +0200
@@ -7,7 +7,7 @@
WSGI corresponding PEP: http://www.python.org/dev/peps/pep-0333/
:organization: Logilab
-:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -25,7 +25,7 @@
return _pformat(obj)
except:
return u'<could not parse>'
-
+
def qs2dict(qs):
"""transforms a query string into a regular python dict"""
result = {}
@@ -35,7 +35,7 @@
def normalize_header(header):
"""returns a normalized header name
-
+
>>> normalize_header('User_Agent')
'User-agent'
"""
@@ -84,4 +84,3 @@
else:
post.setdefault(key, []).append(submessage.get_payload())
return post, files
-
--- a/wsgi/handler.py Thu May 14 18:12:45 2009 +0200
+++ b/wsgi/handler.py Mon May 18 10:09:06 2009 +0200
@@ -1,7 +1,7 @@
"""WSGI request handler for cubicweb
:organization: Logilab
-:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
@@ -74,7 +74,7 @@
def __iter__(self):
return iter(self.body)
-
+
class CubicWebWSGIApplication(object):
@@ -100,7 +100,7 @@
self.url_rewriter = self.appli.vreg.select_component('urlrewriter')
except ObjectNotFound:
self.url_rewriter = None
-
+
def _render(self, req):
"""this function performs the actual rendering
XXX missing: https handling, url rewriting, cache management,
@@ -156,8 +156,8 @@
# 500 Internal server error
return self.redirect(req, req.build_url('error'))
return WSGIResponse(200, req, result)
-
-
+
+
def __call__(self, environ, start_response):
"""WSGI protocol entry point"""
req = CubicWebWsgiRequest(environ, self.appli.vreg, self.base_url)
@@ -170,7 +170,7 @@
self.debug('redirecting to %s', location)
req.set_header('location', str(location))
return WSGIResponse(303, req)
-
+
def request_auth(self, req, loggedout=False):
"""returns the appropriate WSGIResponse to require the user to log in
"""
--- a/wsgi/request.py Thu May 14 18:12:45 2009 +0200
+++ b/wsgi/request.py Mon May 18 10:09:06 2009 +0200
@@ -5,7 +5,7 @@
http://www.djangoproject.com/
:organization: Logilab
-:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
@@ -25,7 +25,7 @@
class CubicWebWsgiRequest(CubicWebRequestBase):
"""most of this code COMES FROM DJANO
"""
-
+
def __init__(self, environ, vreg, base_url=None):
self.environ = environ
self.path = environ['PATH_INFO']
@@ -42,7 +42,7 @@
self.form.update(files)
# prepare output headers
self.headers_out = {}
-
+
def __repr__(self):
# Since this is called as part of error handling, we need to be very
# robust against potentially malformed input.
@@ -52,14 +52,14 @@
(form, meta)
## cubicweb request interface ################################################
-
+
def base_url(self):
return self._base_url
def http_method(self):
"""returns 'POST', 'GET', 'HEAD', etc."""
return self.method
-
+
def relative_path(self, includeparams=True):
"""return the normalized path of the request (ie at least relative
to the application's root, but some other normalization may be needed
@@ -74,7 +74,7 @@
qs = self.environ.get('QUERY_STRING')
if qs:
return '%s?%s' % (path, qs)
-
+
return path
def get_header(self, header, default=None):
@@ -82,7 +82,7 @@
raise KeyError if the header is not set
"""
return self._headers.get(normalize_header(header), default)
-
+
def set_header(self, header, value, raw=True):
"""set an output HTTP header"""
assert raw, "don't know anything about non-raw headers for wsgi requests"
@@ -91,7 +91,7 @@
def add_header(self, header, value):
"""add an output HTTP header"""
self.headers_out[header] = value
-
+
def remove_header(self, header):
"""remove an output HTTP header"""
self.headers_out.pop(header, None)
@@ -101,9 +101,9 @@
mx date time value (GMT), else return None
"""
return None
-
+
## wsgi request helpers ###################################################
-
+
def application_uri(self):
"""Return the application's base URI (no PATH_INFO or QUERY_STRING)
@@ -123,7 +123,7 @@
url += ':' + environ['SERVER_PORT']
url += quote(environ.get('SCRIPT_NAME') or '/')
return url
-
+
def get_full_path(self):
return '%s%s' % (self.path, self.environ.get('QUERY_STRING', '') and ('?' + self.environ.get('QUERY_STRING', '')) or '')