backport stable branch into default
authorAdrien Di Mascio <Adrien.DiMascio@logilab.fr>
Thu, 23 Jul 2009 15:33:03 +0200
changeset 2458 4d114865098f
parent 2457 d0f31e119936 (current diff)
parent 2432 986718a355fa (diff)
child 2459 d088d0ff48a1
backport stable branch into default
__init__.py
common/uilib.py
debian/control
devtools/devctl.py
doc/book/en/admin/setup.rst
server/__init__.py
server/schemaserial.py
server/serverctl.py
web/data/cubicweb.edition.js
web/data/goa.js
web/test/unittest_viewselector.py
web/views/basecontrollers.py
web/views/cwproperties.py
web/views/editforms.py
--- a/.hgtags	Thu Jul 23 15:29:07 2009 +0200
+++ b/.hgtags	Thu Jul 23 15:33:03 2009 +0200
@@ -48,3 +48,5 @@
 1cf9e44e2f1f4415253b8892a0adfbd3b69e84fd cubicweb-version-3_3_3
 47b5236774a0cf3b1cfe75f6d4bd2ec989644ace cubicweb-version-3_3_3
 2ba27ce8ecd9828693ec53c517e1c8810cbbe33e cubicweb-debian-version-3_3_3-2
+d46363eac5d71bc1570d69337955154dfcd8fcc8 cubicweb-version-3.3.4
+7dc22caa7640bf70fcae55afb6d2326829dacced cubicweb-debian-version-3.3.4-1
--- a/__init__.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/__init__.py	Thu Jul 23 15:33:03 2009 +0200
@@ -300,3 +300,6 @@
     except AttributeError:
         return neg_role(obj.role)
 
+def underline_title(title, car='-'):
+    return title+'\n'+(car*len(title))
+
--- a/__pkginfo__.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/__pkginfo__.py	Thu Jul 23 15:33:03 2009 +0200
@@ -7,7 +7,7 @@
 distname = "cubicweb"
 modname = "cubicweb"
 
-numversion = (3, 3, 3)
+numversion = (3, 3, 4)
 version = '.'.join(str(num) for num in numversion)
 
 license = 'LGPL v2'
@@ -32,6 +32,13 @@
 ftp = 'ftp://ftp.logilab.org/pub/cubicweb'
 pyversions = ['2.4', '2.5']
 
+classifiers = [
+           'Environment :: Web Environment',
+           'Framework :: CubicWeb',
+           'Programming Language :: Python',
+           'Programming Language :: JavaScript',
+]
+
 
 import sys
 from os import listdir, environ
--- a/common/i18n.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/common/i18n.py	Thu Jul 23 15:33:03 2009 +0200
@@ -63,7 +63,7 @@
     """generate .mo files for a set of languages into the `destdir` i18n directory
     """
     from logilab.common.fileutils import ensure_fs_mode
-    print 'compiling %s catalogs...' % destdir
+    print '-> compiling %s catalogs...' % destdir
     errors = []
     for lang in langs:
         langdir = join(destdir, lang, 'LC_MESSAGES')
--- a/cwctl.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/cwctl.py	Thu Jul 23 15:33:03 2009 +0200
@@ -10,7 +10,7 @@
 
 from logilab.common.clcommands import register_commands, pop_arg
 
-from cubicweb import ConfigurationError, ExecutionError, BadCommandUsage
+from cubicweb import ConfigurationError, ExecutionError, BadCommandUsage, underline_title
 from cubicweb.cwconfig import CubicWebConfiguration as cwcfg, CONFIGURATIONS
 from cubicweb.toolsutils import Command, main_run,  rm, create_dir, confirm
 
@@ -286,20 +286,22 @@
             print ', '.join(cwcfg.available_cubes())
             return
         # create the registry directory for this application
+        print '\n'+underline_title('Creating the application %s' % appid)
         create_dir(config.apphome)
         # load site_cubicweb from the cubes dir (if any)
         config.load_site_cubicweb()
         # cubicweb-ctl configuration
-        print '** application\'s %s configuration' % configname
-        print '-' * 72
+        print '\n'+underline_title('Configuring the application (%s.conf)' % configname)
         config.input_config('main', self.config.config_level)
         # configuration'specific stuff
         print
         helper.bootstrap(cubes, self.config.config_level)
         # write down configuration
         config.save()
+        print '-> generated %s' % config.main_config_file()
         # handle i18n files structure
         # in the first cube given
+        print '-> preparing i18n catalogs'
         from cubicweb.common import i18n
         langs = [lang for lang, _ in i18n.available_catalogs(join(templdirs[0], 'i18n'))]
         errors = config.i18ncompile(langs)
@@ -317,12 +319,7 @@
             # this directory should be owned by the uid of the server process
             print 'set %s as owner of the data directory' % config['uid']
             chown(config.appdatahome, config['uid'])
-        print
-        print
-        print '*' * 72
-        print 'application %s (%s) created in %r' % (appid, configname,
-                                                     config.apphome)
-        print
+        print '\n-> creation done for %r.\n' % config.apphome
         helper.postcreate()
 
 
--- a/debian/changelog	Thu Jul 23 15:29:07 2009 +0200
+++ b/debian/changelog	Thu Jul 23 15:33:03 2009 +0200
@@ -1,3 +1,15 @@
+cubicweb (3.3.4-2) unstable; urgency=low
+
+  * fix conflicting test files
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr>  Tue, 21 Jul 2009 23:09:03 +0200
+
+cubicweb (3.3.4-1) unstable; urgency=low
+
+  * new upstream release
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr>  Tue, 21 Jul 2009 13:11:38 +0200
+
 cubicweb (3.3.3-2) unstable; urgency=low
 
   * re-release with "from __future__ import with_statement" commented out to
--- a/debian/cubicweb-dev.install.in	Thu Jul 23 15:29:07 2009 +0200
+++ b/debian/cubicweb-dev.install.in	Thu Jul 23 15:33:03 2009 +0200
@@ -1,2 +1,11 @@
 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/entities/test usr/lib/PY_VERSION/site-packages/cubicweb/entities/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/ext/test usr/lib/PY_VERSION/site-packages/cubicweb/ext/
+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/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/etwist/test usr/lib/PY_VERSION/site-packages/cubicweb/etwist/
+debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/goa/test usr/lib/PY_VERSION/site-packages/cubicweb/goa/
--- a/debian/rules	Thu Jul 23 15:29:07 2009 +0200
+++ b/debian/rules	Thu Jul 23 15:33:03 2009 +0200
@@ -47,12 +47,13 @@
 	dh_lintian
 
 	# Remove unittests directory (should be available in cubicweb-dev only)
-	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
+	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-twisted/usr/lib/${PY_VERSION}/site-packages/cubicweb/etwist/test
+	rm -rf debian/cubicweb-common/usr/lib/${PY_VERSION}/site-packages/cubicweb/ext/test
+	rm -rf debian/cubicweb-common/usr/lib/${PY_VERSION}/site-packages/cubicweb/common/test
+	rm -rf debian/cubicweb-common/usr/lib/${PY_VERSION}/site-packages/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/devctl.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/devtools/devctl.py	Thu Jul 23 15:33:03 2009 +0200
@@ -19,7 +19,7 @@
 from logilab.common.textutils import get_csv
 from logilab.common.clcommands import register_commands
 
-from cubicweb import CW_SOFTWARE_ROOT as BASEDIR, BadCommandUsage
+from cubicweb import CW_SOFTWARE_ROOT as BASEDIR, BadCommandUsage, underline_title
 from cubicweb.__pkginfo__ import version as cubicwebversion
 from cubicweb.toolsutils import Command, confirm, copy_skeleton
 from cubicweb.web.webconfig import WebConfiguration
@@ -261,7 +261,7 @@
         from cubicweb.common.i18n import extract_from_tal, execute
         tempdir = tempdir.mkdtemp()
         potfiles = [join(I18NDIR, 'entities.pot')]
-        print '******** extract schema messages'
+        print '-> extract schema messages.'
         schemapot = join(tempdir, 'schema.pot')
         potfiles.append(schemapot)
         # explicit close necessary else the file may not be yet flushed when
@@ -269,10 +269,10 @@
         schemapotstream = file(schemapot, 'w')
         generate_schema_pot(schemapotstream.write, cubedir=None)
         schemapotstream.close()
-        print '******** extract TAL messages'
+        print '-> extract TAL messages.'
         tali18nfile = join(tempdir, 'tali18n.py')
         extract_from_tal(find(join(BASEDIR, 'web'), ('.py', '.pt')), tali18nfile)
-        print '******** .pot files generation'
+        print '-> generate .pot files.'
         for id, files, lang in [('pycubicweb', get_module_files(BASEDIR) + list(globfind(join(BASEDIR, 'misc', 'migration'), '*.py')), None),
                                 ('schemadescr', globfind(join(BASEDIR, 'schemas'), '*.py'), None),
                                 ('yams', get_module_files(yams.__path__[0]), None),
@@ -287,11 +287,11 @@
             if exists(potfile):
                 potfiles.append(potfile)
             else:
-                print 'WARNING: %s file not generated' % potfile
-        print '******** merging .pot files'
+                print '-> WARNING: %s file was not generated' % potfile
+        print '-> merging %i .pot files' % len(potfiles)
         cubicwebpot = join(tempdir, 'cubicweb.pot')
         execute('msgcat %s > %s' % (' '.join(potfiles), cubicwebpot))
-        print '******** merging main pot file with existing translations'
+        print '-> merging main pot file with existing translations.'
         chdir(I18NDIR)
         toedit = []
         for lang in LANGS:
@@ -303,11 +303,10 @@
         # cleanup
         rm(tempdir)
         # instructions pour la suite
-        print '*' * 72
-        print 'you can now edit the following files:'
+        print '-> regenerated CubicWeb\'s .po catalogs.'
+        print '\nYou can now edit the following files:'
         print '* ' + '\n* '.join(toedit)
-        print
-        print "then you'll have to update cubes catalogs using the i18ncube command"
+        print 'when you are done, run "cubicweb-ctl i18ncube yourcube".'
 
 
 class UpdateTemplateCatalogCommand(Command):
@@ -331,19 +330,19 @@
     toedit = []
     for cubedir in cubes:
         if not isdir(cubedir):
-            print 'not a directory', cubedir
+            print '-> ignoring %s that is not a directory.' % cubedir
             continue
         try:
             toedit += update_cube_catalogs(cubedir)
         except Exception:
             import traceback
             traceback.print_exc()
-            print 'error while updating catalogs for', cubedir
+            print '-> Error while updating catalogs for cube', cubedir
     # instructions pour la suite
-    print '*' * 72
-    print 'you can now edit the following files:'
+    print '-> regenerated this cube\'s .po catalogs.'
+    print '\nYou can now edit the following files:'
     print '* ' + '\n* '.join(toedit)
-
+    print 'when you are done, run "cubicweb-ctl i18ninstance yourinstance".'
 
 def update_cube_catalogs(cubedir):
     import shutil
@@ -354,12 +353,11 @@
     toedit = []
     cube = basename(normpath(cubedir))
     tempdir = tempfile.mkdtemp()
-    print '*' * 72
-    print 'updating %s cube...' % cube
+    print underline_title('Updating i18n catalogs for cube %s' % cube)
     chdir(cubedir)
     potfiles = [join('i18n', scfile) for scfile in ('entities.pot',)
                 if exists(join('i18n', scfile))]
-    print '******** extract schema messages'
+    print '-> extract schema messages'
     schemapot = join(tempdir, 'schema.pot')
     potfiles.append(schemapot)
     # explicit close necessary else the file may not be yet flushed when
@@ -367,10 +365,10 @@
     schemapotstream = file(schemapot, 'w')
     generate_schema_pot(schemapotstream.write, cubedir)
     schemapotstream.close()
-    print '******** extract TAL messages'
+    print '-> extract TAL messages'
     tali18nfile = join(tempdir, 'tali18n.py')
     extract_from_tal(find('.', ('.py', '.pt'), blacklist=STD_BLACKLIST+('test',)), tali18nfile)
-    print '******** extract Javascript messages'
+    print '-> extract Javascript messages'
     jsfiles =  [jsfile for jsfile in find('.', '.js') if basename(jsfile).startswith('cub')]
     if jsfiles:
         tmppotfile = join(tempdir, 'js.pot')
@@ -379,7 +377,7 @@
         # no pot file created if there are no string to translate
         if exists(tmppotfile):
             potfiles.append(tmppotfile)
-    print '******** create cube specific catalog'
+    print '-> create cube-specific catalog'
     tmppotfile = join(tempdir, 'generated.pot')
     cubefiles = find('.', '.py', blacklist=STD_BLACKLIST+('test',))
     cubefiles.append(tali18nfile)
@@ -388,12 +386,12 @@
     if exists(tmppotfile): # doesn't exists of no translation string found
         potfiles.append(tmppotfile)
     potfile = join(tempdir, 'cube.pot')
-    print '******** merging .pot files'
+    print '-> merging %i .pot files:' % len(potfiles)
     execute('msgcat %s > %s' % (' '.join(potfiles), potfile))
-    print '******** merging main pot file with existing translations'
+    print '-> merging main pot file with existing translations:'
     chdir('i18n')
     for lang in LANGS:
-        print '****', lang
+        print '-> language', lang
         cubepo = '%s.po' % lang
         if not exists(cubepo):
             shutil.copy(potfile, cubepo)
--- a/doc/book/en/B000-development.en.txt	Thu Jul 23 15:29:07 2009 +0200
+++ b/doc/book/en/B000-development.en.txt	Thu Jul 23 15:33:03 2009 +0200
@@ -1,7 +1,5 @@
 .. -*- coding: utf-8 -*-
 
-.. _Part2:
-
 =====================
 Part II - Development
 =====================
--- a/doc/book/en/admin/setup.rst	Thu Jul 23 15:29:07 2009 +0200
+++ b/doc/book/en/admin/setup.rst	Thu Jul 23 15:33:03 2009 +0200
@@ -52,7 +52,7 @@
 3. run "apt-key add logilab-dists-key.asc"
 4. re-run apt-get update (manually or through the package manager, whichever you prefer)
 
-.. `Logilab's gnupg key` _http://ftp.logilab.org/dists/logilab-dists-key.asc
+.. _`Logilab's gnupg key`: http://ftp.logilab.org/dists/logilab-dists-key.asc
 
 Install from source
 ```````````````````
@@ -74,6 +74,9 @@
 repositories are set to 'stable' (using `hg up stable` for each one)
 if you do not intend to develop the framework itself.
 
+In both cases, make sure you have installed the dependencies (see appendixes for
+the list).
+
 Postgres installation
 `````````````````````
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/annexes/depends.rst	Thu Jul 23 15:33:03 2009 +0200
@@ -0,0 +1,48 @@
+.. -*- coding: utf-8 -*-
+
+.. _dependencies:
+
+Dependencies
+============
+
+When you run CubicWeb from source, either by downloading the tarball or
+cloning the mercurial forest, here is the list of tools and libraries you need
+to have installed in order for CubicWeb to work:
+
+* mxDateTime - http://www.egenix.com/products/python/mxBase/mxDateTime/ - http://pypi.python.org/pypi/egenix-mx-base
+
+* pyro - http://pyro.sourceforge.net/ - http://pypi.python.org/pypi/Pyro
+
+* yapps - http://theory.stanford.edu/~amitp/yapps/ -
+  http://pypi.python.org/pypi/Yapps2
+
+* pygraphviz - http://networkx.lanl.gov/pygraphviz/ -
+  http://pypi.python.org/pypi/pygraphviz
+
+* simplejson - http://code.google.com/p/simplejson/ -
+  http://pypi.python.org/pypi/simplejson
+
+* lxml - http://codespeak.net/lxml - http://pypi.python.org/pypi/lxml
+
+* twisted - http://twistedmatrix.com/ - http://pypi.python.org/pypi/Twisted
+
+* logilab-common - http://www.logilab.org/project/logilab-common -
+  http://pypi.python.org/pypi/logilab-common/ - included in the forest
+
+* logilab-constraint - http://www.logilab.org/project/logilab-constraint -
+  http://pypi.python.org/pypi/constraint/ - included in the forest
+
+* logilab-mtconverter - http://www.logilab.org/project/logilab-mtconverter -
+  http://pypi.python.org/pypi/logilab-mtconverter - included in the forest
+
+* rql - http://www.logilab.org/project/rql - http://pypi.python.org/pypi/rql -
+  included in the forest
+
+* yams - http://www.logilab.org/project/yams - http://pypi.python.org/pypi/yams
+  - included in the forest
+
+* indexer - http://www.logilab.org/project/indexer -
+  http://pypi.python.org/pypi/indexer - included in the forest
+
+Any help with the packaging of CubicWeb for more than Debian/Ubuntu (including
+eggs, buildouts, etc) will be greatly appreciated.
--- a/doc/book/en/annexes/index.rst	Thu Jul 23 15:29:07 2009 +0200
+++ b/doc/book/en/annexes/index.rst	Thu Jul 23 15:33:03 2009 +0200
@@ -16,6 +16,7 @@
    cubicweb-ctl
    rql/index
    mercurial
+   depends
 
 (X)HTML tricks to apply
 -----------------------
--- a/doc/book/en/development/datamodel/index.rst	Thu Jul 23 15:29:07 2009 +0200
+++ b/doc/book/en/development/datamodel/index.rst	Thu Jul 23 15:33:03 2009 +0200
@@ -9,6 +9,5 @@
    definition
    metadata
    baseschema
-
-..    define-workflows
-..    inheritance
+   define-workflows
+   inheritance
--- a/doc/book/en/development/datamodel/inheritance.rst	Thu Jul 23 15:29:07 2009 +0200
+++ b/doc/book/en/development/datamodel/inheritance.rst	Thu Jul 23 15:33:03 2009 +0200
@@ -1,1 +1,5 @@
-XXX WRITME
\ No newline at end of file
+
+Inheritance
+-----------
+
+XXX WRITME
--- a/etwist/twctl.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/etwist/twctl.py	Thu Jul 23 15:33:03 2009 +0200
@@ -8,6 +8,7 @@
 
 import sys
 
+from cubicweb import underline_title
 from cubicweb.toolsutils import CommandHandler
 from cubicweb.web.webctl import WebCreateHandler
 
@@ -20,7 +21,7 @@
 
     def bootstrap(self, cubes, inputlevel=0):
         """bootstrap this configuration"""
-        print '** twisted configuration'
+        print '\n'+underline_title('Configuring Twisted')
         mainpyfile = self.config.server_file()
         mainpy = open(mainpyfile, 'w')
         mainpy.write('''
@@ -28,7 +29,7 @@
 application = server.main(%r, %r)
 ''' % (self.config.appid, self.config.name))
         mainpy.close()
-        print 'application\'s twisted file %s generated' % mainpyfile
+        print '-> generated %s' % mainpyfile
         super(TWCreateHandler, self).bootstrap(cubes, inputlevel)
 
 
--- a/hercule.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/hercule.py	Thu Jul 23 15:33:03 2009 +0200
@@ -106,7 +106,7 @@
             password = getpass('password: ')
         if self.cnx is not None:
             self.cnx.close()
-        self.cnx = connect(user=user, password=password, host=host,
+        self.cnx = connect(login=user, password=password, host=host,
                            database=application)
         self.schema = self.cnx.get_schema()
         self.cursor = self.cnx.cursor()
--- a/misc/cwdesklets/rqlsensor/__init__.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/misc/cwdesklets/rqlsensor/__init__.py	Thu Jul 23 15:33:03 2009 +0200
@@ -65,7 +65,7 @@
             return self._v_cnx
         except AttributeError:
             appid, user, passwd = self._get_config("appid"), self._get_config("user"), self._get_config("passwd")
-            cnx = connect(database=appid, user=user, password=passwd)
+            cnx = connect(database=appid, login=user, password=passwd)
             self._v_cnx = cnx
             return cnx
 
--- a/server/__init__.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/server/__init__.py	Thu Jul 23 15:33:03 2009 +0200
@@ -45,7 +45,8 @@
     assert len(repo.sources) == 1, repo.sources
     schema = repo.schema
     sourcescfg = config.sources()
-    print 'creating necessary tables into the system source'
+    _title = '-> creating tables '
+    print _title,
     source = sourcescfg['system']
     driver = source['db-driver']
     sqlcnx = repo.system_source.get_connection()
@@ -56,7 +57,7 @@
         try:
             sqlexec(dropsql, execute)
         except Exception, ex:
-            print 'drop failed, skipped (%s)' % ex
+            print '-> drop failed, skipped (%s).' % ex
             sqlcnx.rollback()
     # schema entities and relations tables
     # can't skip entities table even if system source doesn't support them,
@@ -68,14 +69,14 @@
         schemasql = sqlschema(schema, driver)
         #skip_entities=[str(e) for e in schema.entities()
         #               if not repo.system_source.support_entity(str(e))])
-    sqlexec(schemasql, execute)
+    sqlexec(schemasql, execute, pbtitle=_title)
     # install additional driver specific sql files
     for fpath in glob(join(config.schemas_lib_dir(), '*.sql.%s' % driver)):
-        print 'install', fpath
+        print '-> installing', fpath
         sqlexec(open(fpath).read(), execute, False, delimiter=';;')
     for directory in config.cubes_path():
         for fpath in glob(join(directory, 'schema', '*.sql.%s' % driver)):
-            print 'install', fpath
+            print '-> installing', fpath
             sqlexec(open(fpath).read(), execute, False, delimiter=';;')
     sqlcursor.close()
     sqlcnx.commit()
@@ -90,7 +91,7 @@
             login, pwd = manager_userpasswd(msg=msg, confirm=True)
         else:
             login, pwd = unicode(source['db-user']), source['db-password']
-    print 'inserting default user and groups'
+    print '-> inserting default user and default groups.'
     needisfix = []
     for group in BASE_GROUPS:
         rset = session.execute('INSERT CWGroup X: X name %(name)s',
@@ -140,7 +141,7 @@
     config.bootstrap_schema = bootstrap_schema
     config.consider_user_state = True
     config.set_language = True
-    print 'application %s initialized' % config.appid
+    print '-> database for application %s initialized.' % config.appid
 
 
 def initialize_schema(config, schema, mhandler, event='create'):
--- a/server/schemaserial.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/server/schemaserial.py	Thu Jul 23 15:33:03 2009 +0200
@@ -277,12 +277,13 @@
     """synchronize schema and permissions in the database according to
     current schema
     """
-    print 'serializing the schema, this may take some time'
+    _title = '-> storing the schema in the database '
+    print _title,
     eschemas = schema.entities()
     aller = eschemas + schema.relations()
     if not verbose:
         pb_size = len(aller) + len(CONSTRAINTS) + len([x for x in eschemas if x.specializes()])
-        pb = ProgressBar(pb_size)
+        pb = ProgressBar(pb_size, title=_title)
     for cstrtype in CONSTRAINTS:
         rql = 'INSERT CWConstraintType X: X name "%s"' % cstrtype
         if verbose:
--- a/server/serverctl.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/server/serverctl.py	Thu Jul 23 15:33:03 2009 +0200
@@ -13,13 +13,12 @@
 from logilab.common.configuration import Configuration
 from logilab.common.clcommands import register_commands, cmd_run, pop_arg
 
-from cubicweb import AuthenticationError, ExecutionError, ConfigurationError
+from cubicweb import AuthenticationError, ExecutionError, ConfigurationError, underline_title
 from cubicweb.toolsutils import Command, CommandHandler, confirm
 from cubicweb.server import SOURCE_TYPES
 from cubicweb.server.utils import ask_source_config
 from cubicweb.server.serverconfig import USER_OPTIONS, ServerConfiguration
 
-
 # utility functions ###########################################################
 
 def source_cnx(source, dbname=None, special_privs=False, verbose=True):
@@ -32,7 +31,7 @@
     if dbname is None:
         dbname = source['db-name']
     driver = source['db-driver']
-    print '**** connecting to %s database %s@%s' % (driver, dbname, dbhost),
+    print '-> connecting to %s database %s@%s' % (driver, dbname, dbhost or 'localhost'),
     if not verbose or (not special_privs and source.get('db-user')):
         user = source['db-user']
         print 'as', user
@@ -48,7 +47,7 @@
             print special_privs
             print
         default_user = source.get('db-user', os.environ.get('USER', ''))
-        user = raw_input('user (%r by default): ' % default_user)
+        user = raw_input('Connect as user ? [%r]: ' % default_user)
         user = user or default_user
         if user == source.get('db-user') and source.get('db-password'):
             password = source['db-password']
@@ -108,7 +107,7 @@
         try:
             return in_memory_cnx(config, login, pwd)
         except AuthenticationError:
-            print 'wrong user/password'
+            print '-> Error: wrong user/password.'
             # reset cubes else we'll have an assertion error on next retry
             config._cubes = None
         login, pwd = manager_userpasswd()
@@ -124,14 +123,11 @@
         asking information necessary to build required configuration files
         """
         config = self.config
-        print 'application\'s repository configuration'
-        print '-' * 72
+        print underline_title('Configuring the repository')
         config.input_config('email', inputlevel)
         if config.pyro_enabled():
             config.input_config('pyro-server', inputlevel)
-        print
-        print 'repository sources configuration'
-        print '-' * 72
+        print '\n'+underline_title('Configuring the sources')
         sourcesfile = config.sources_file()
         sconfig = Configuration(options=SOURCE_TYPES['native'].options)
         sconfig.adapter = 'native'
@@ -142,19 +138,20 @@
             # source to use the cube, so add it.
             if cube in SOURCE_TYPES:
                 sourcescfg[cube] = ask_source_config(cube, inputlevel)
-        while raw_input('enter another source [y/N]: ').strip().lower() == 'y':
+        print
+        while confirm('Enter another source ?', default_is_yes=False):
             available = sorted(stype for stype in SOURCE_TYPES
                                if not stype in cubes)
             while True:
                 sourcetype = raw_input('source type (%s): ' % ', '.join(available))
                 if sourcetype in available:
                     break
-                print 'unknown source type, use one of the available type'
+                print '-> unknown source type, use one of the available types.'
             while True:
                 sourceuri = raw_input('source uri: ').strip()
                 if sourceuri != 'admin' and sourceuri not in sourcescfg:
                     break
-                print 'uri already used, choose another one'
+                print '-> uri already used, choose another one.'
             sourcescfg[sourceuri] = ask_source_config(sourcetype)
             sourcemodule = SOURCE_TYPES[sourcetype].module
             if not sourcemodule.startswith('cubicweb.'):
@@ -172,11 +169,12 @@
         config.write_bootstrap_cubes_file(cubes)
 
     def postcreate(self):
-        if confirm('do you want to create repository\'s system database?'):
+        if confirm('Do you want to run db-create to create the "system database" ?'):
             verbosity = (self.config.mode == 'installed') and 'y' or 'n'
             cmd_run('db-create', self.config.appid, '--verbose=%s' % verbosity)
         else:
-            print 'nevermind, you can do it later using the db-create command'
+            print ('-> nevermind, you can do it later with '
+                   '"cubicweb-ctl db-create %s".' % self.config.appid)
 
 
 class RepositoryDeleteHandler(CommandHandler):
@@ -189,18 +187,18 @@
         source = self.config.sources()['system']
         dbname = source['db-name']
         helper = get_adv_func_helper(source['db-driver'])
-        if confirm('delete database %s ?' % dbname):
+        if confirm('Delete database %s ?' % dbname):
             user = source['db-user'] or None
             cnx = _db_sys_cnx(source, 'DROP DATABASE', user=user)
             cursor = cnx.cursor()
             try:
                 cursor.execute('DROP DATABASE %s' % dbname)
-                print 'database %s dropped' % dbname
+                print '-> database %s dropped.' % dbname
                 # XXX should check we are not connected as user
                 if user and helper.users_support and \
-                       confirm('delete user %s ?' % user, default_is_yes=False):
+                       confirm('Delete user %s ?' % user, default_is_yes=False):
                     cursor.execute('DROP USER %s' % user)
-                    print 'user %s dropped' % user
+                    print '-> user %s dropped.' % user
                 cnx.commit()
             except:
                 cnx.rollback()
@@ -271,6 +269,7 @@
         driver = source['db-driver']
         helper = get_adv_func_helper(driver)
         if create_db:
+            print '\n'+underline_title('Creating the "system database"')
             # connect on the dbms system base to create our base
             dbcnx = _db_sys_cnx(source, 'CREATE DATABASE and / or USER', verbose=verbose)
             cursor = dbcnx.cursor()
@@ -278,12 +277,12 @@
                 if helper.users_support:
                     user = source['db-user']
                     if not helper.user_exists(cursor, user) and \
-                           confirm('create db user %s ?' % user, default_is_yes=False):
+                           confirm('Create db user %s ?' % user, default_is_yes=False):
                         helper.create_user(source['db-user'], source['db-password'])
-                        print 'user %s created' % user
+                        print '-> user %s created.' % user
                 dbname = source['db-name']
                 if dbname in helper.list_databases(cursor):
-                    if confirm('DB %s already exists -- do you want to drop it ?' % dbname):
+                    if confirm('Database %s already exists -- do you want to drop it ?' % dbname):
                         cursor.execute('DROP DATABASE %s' % dbname)
                     else:
                         return
@@ -294,7 +293,7 @@
                     helper.create_database(cursor, dbname,
                                            encoding=source['db-encoding'])
                 dbcnx.commit()
-                print 'database %s created' % source['db-name']
+                print '-> database %s created.' % source['db-name']
             except:
                 dbcnx.rollback()
                 raise
@@ -309,12 +308,13 @@
                 helper.create_language(cursor, extlang)
         cursor.close()
         cnx.commit()
-        print 'database for application %s created and necessary extensions installed' % appid
+        print '-> database for application %s created and necessary extensions installed.' % appid
         print
-        if confirm('do you want to initialize the system database?'):
+        if confirm('Do you want to run db-init to initialize the "system database" ?'):
             cmd_run('db-init', config.appid)
         else:
-            print 'nevermind, you can do it later using the db-init command'
+            print ('-> nevermind, you can do it later with '
+                   '"cubicweb-ctl db-init %s".' % self.config.appid)
 
 
 class InitApplicationCommand(Command):
@@ -339,6 +339,7 @@
         )
 
     def run(self, args):
+        print '\n'+underline_title('Initializing the "system database"')
         from cubicweb.server import init_repository
         appid = pop_arg(args, msg="No application specified !")
         config = ServerConfiguration.config_for(appid)
@@ -381,10 +382,10 @@
             cnx.rollback()
             import traceback
             traceback.print_exc()
-            print 'An error occured:', ex
+            print '-> an error occured:', ex
         else:
             cnx.commit()
-            print 'grants given to %s on application %s' % (appid, user)
+            print '-> rights granted to %s on application %s.' % (appid, user)
 
 class ResetAdminPasswordCommand(Command):
     """Reset the administrator password.
@@ -405,7 +406,7 @@
         try:
             adminlogin = sourcescfg['admin']['login']
         except KeyError:
-            print 'could not get cubicweb administrator login'
+            print '-> Error: could not get cubicweb administrator login.'
             sys.exit(1)
         cnx = source_cnx(sourcescfg['system'])
         cursor = cnx.cursor()
@@ -425,10 +426,10 @@
             cnx.rollback()
             import traceback
             traceback.print_exc()
-            print 'An error occured:', ex
+            print '-> an error occured:', ex
         else:
             cnx.commit()
-            print 'password reset, sources file regenerated'
+            print '-> password reset, sources file regenerated.'
 
 
 class StartRepositoryCommand(Command):
@@ -490,7 +491,7 @@
     rmcmd = 'ssh -t %s "rm -f /tmp/%s.dump"' % (host, appid)
     print rmcmd
     if os.system(rmcmd) and not confirm(
-        'an error occured while deleting remote dump. Continue anyway?'):
+        'An error occured while deleting remote dump. Continue anyway?'):
         raise ExecutionError('Error while deleting remote dump')
 
 def _local_dump(appid, output):
@@ -541,12 +542,12 @@
         try:
             softversion = config.cube_version(cube)
         except ConfigurationError:
-            print "no cube version information for %s, is the cube installed?" % cube
+            print "-> Error: no cube version information for %s, please check that the cube is installed." % cube
             continue
         try:
             applversion = vcconf[cube]
         except KeyError:
-            print "no cube version information for %s in version configuration" % cube
+            print "-> Error: no cube version information for %s in version configuration." % cube
             continue
         if softversion == applversion:
             continue
@@ -657,7 +658,7 @@
             _local_dump(srcappid, output)
         _local_restore(destappid, output, not self.config.no_drop)
         if self.config.keep_dump:
-            print 'you can get the dump file at', output
+            print '-> you can get the dump file at', output
         else:
             os.remove(output)
 
--- a/server/sqlutils.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/server/sqlutils.py	Thu Jul 23 15:33:03 2009 +0200
@@ -29,7 +29,7 @@
 SQL_PREFIX = 'cw_'
 
 
-def sqlexec(sqlstmts, cursor_or_execute, withpb=True, delimiter=';'):
+def sqlexec(sqlstmts, cursor_or_execute, withpb=True, pbtitle='', delimiter=';'):
     """execute sql statements ignoring DROP/ CREATE GROUP or USER statements
     error. If a cnx is given, commit at each statement
     """
@@ -39,7 +39,7 @@
         execute = cursor_or_execute
     sqlstmts = sqlstmts.split(delimiter)
     if withpb:
-        pb = ProgressBar(len(sqlstmts))
+        pb = ProgressBar(len(sqlstmts), title=pbtitle)
     for sql in sqlstmts:
         sql = sql.strip()
         if withpb:
--- a/toolsutils.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/toolsutils.py	Thu Jul 23 15:33:03 2009 +0200
@@ -7,6 +7,8 @@
 """
 __docformat__ = "restructuredtext en"
 
+# XXX move most of this in logilab.common (shellutils ?)
+
 import os, sys
 from os import listdir, makedirs, symlink, environ, chmod, walk, remove
 from os.path import exists, join, abspath, normpath
@@ -14,6 +16,7 @@
 from logilab.common.clcommands import Command as BaseCommand, \
      main_run as base_main_run
 from logilab.common.compat import any
+from logilab.common.shellutils import confirm
 
 from cubicweb import warning
 from cubicweb import ConfigurationError, ExecutionError
@@ -34,12 +37,12 @@
     """create a directory if it doesn't exist yet"""
     try:
         makedirs(directory)
-        print 'created directory', directory
+        print '-> created directory %s.' % directory
     except OSError, ex:
         import errno
         if ex.errno != errno.EEXIST:
             raise
-        print 'directory %s already exists' % directory
+        print '-> directory %s already exists, no need to create it.' % directory
 
 def create_symlink(source, target):
     """create a symbolic link"""
@@ -56,7 +59,7 @@
 def rm(whatever):
     import shutil
     shutil.rmtree(whatever)
-    print 'removed %s' % whatever
+    print '-> removed %s' % whatever
 
 def show_diffs(appl_file, ref_file, askconfirm=True):
     """interactivly replace the old file with the new file according to
@@ -133,24 +136,9 @@
     if log:
         log('set %s permissions to 0600', filepath)
     else:
-        print 'set %s permissions to 0600' % filepath
+        print '-> set %s permissions to 0600' % filepath
     chmod(filepath, 0600)
 
-def confirm(question, default_is_yes=True):
-    """ask for confirmation and return true on positive answer"""
-    if default_is_yes:
-        input_str = '%s [Y/n]: '
-    else:
-        input_str = '%s [y/N]: '
-    answer = raw_input(input_str % (question)).strip().lower()
-    if default_is_yes:
-        if answer in ('n', 'no'):
-            return False
-        return True
-    if answer in ('y', 'yes'):
-        return True
-    return False
-
 def read_config(config_file):
     """read the application configuration from a file and return it as a
     dictionnary
@@ -289,5 +277,5 @@
     password = optconfig.password
     if not password:
         password = getpass('password: ')
-    return connect(user=user, password=password, host=optconfig.host, database=appid)
+    return connect(login=user, password=password, host=optconfig.host, database=appid)
 
--- a/web/data/cubicweb.edition.js	Thu Jul 23 15:29:07 2009 +0200
+++ b/web/data/cubicweb.edition.js	Thu Jul 23 15:33:03 2009 +0200
@@ -512,7 +512,7 @@
           document.location.href = result[1];
         } else {
 	  if (result[0]) {
-            var d = asyncRemoteExec('reledit_form', eid, rtype, role, lzone);
+            var d = asyncRemoteExec('reledit_form', eid, rtype, role, default_value, lzone);
             d.addCallback(function (result) {
               jQuery('#'+divid+'-reledit').replaceWith(result);
             });
--- a/web/data/goa.js	Thu Jul 23 15:29:07 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-/*
- *  functions specific to ginco on google appengine
- *
- *  :organization: Logilab
- *  :copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
- *  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
- */
-
-/* overrides rql_for_eid function from htmlhelpers.hs */
-function rql_for_eid(eid) { return 'Any X WHERE X eid "' + eid + '"'; }
--- a/web/test/unittest_viewselector.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/web/test/unittest_viewselector.py	Thu Jul 23 15:33:03 2009 +0200
@@ -1,4 +1,4 @@
-# -*- coding: iso-8859-1 -*-
+# -*- coding: utf-8 -*-
 """XXX rename, split, reorganize this
 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
@@ -60,6 +60,9 @@
             print 'missing', [v for v in content.keys() if not v in expected]
             raise
 
+    def setUp(self):
+        super(VRegistryTC, self).setUp()
+        assert self.vreg['views']['propertiesform']
 
     def test_possible_views_none_rset(self):
         req = self.request()
@@ -123,6 +126,31 @@
                               ('xml', xmlrss.XMLView),
                               ])
 
+    def test_propertiesform_admin(self):
+        assert self.vreg['views']['propertiesform']
+        rset1, req1 = self.env.get_rset_and_req('CWUser X WHERE X login "admin"')
+        rset2, req2 = self.env.get_rset_and_req('CWUser X WHERE X login "anon"')
+        self.failUnless(self.vreg.select_object('views', 'propertiesform', req1, rset=None))
+        self.failUnless(self.vreg.select_object('views', 'propertiesform', req1, rset=rset1))
+        self.failUnless(self.vreg.select_object('views', 'propertiesform', req2, rset=rset2))
+
+    def test_propertiesform_anon(self):
+        self.login('anon')
+        rset1, req1 = self.env.get_rset_and_req('CWUser X WHERE X login "admin"')
+        rset2, req2 = self.env.get_rset_and_req('CWUser X WHERE X login "anon"')
+        self.assertRaises(NoSelectableObject, self.vreg.select_object, 'views', 'propertiesform', req1, rset=None)
+        self.assertRaises(NoSelectableObject, self.vreg.select_object, 'views', 'propertiesform', req1, rset=rset1)
+        self.assertRaises(NoSelectableObject, self.vreg.select_object, 'views', 'propertiesform', req1, rset=rset2)
+
+    def test_propertiesform_jdoe(self):
+        self.create_user('jdoe')
+        self.login('jdoe')
+        rset1, req1 = self.env.get_rset_and_req('CWUser X WHERE X login "admin"')
+        rset2, req2 = self.env.get_rset_and_req('CWUser X WHERE X login "jdoe"')
+        self.failUnless(self.vreg.select_object('views', 'propertiesform', req1, rset=None))
+        self.assertRaises(NoSelectableObject, self.vreg.select_object, 'views', 'propertiesform', req1, rset=rset1)
+        self.failUnless(self.vreg.select_object('views', 'propertiesform', req2, rset=rset2))
+
     def test_possible_views_multiple_different_types(self):
         rset, req = self.env.get_rset_and_req('Any X')
         self.assertListEqual(self.pviews(req, rset),
--- a/web/views/basecontrollers.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/web/views/basecontrollers.py	Thu Jul 23 15:33:03 2009 +0200
@@ -400,10 +400,11 @@
             return (success, args, None)
 
     @jsonize
-    def js_reledit_form(self, eid, rtype, role, lzone):
+    def js_reledit_form(self, eid, rtype, role, default, lzone):
+        """XXX we should get rid of this and use loadxhtml"""
         entity = self.req.eid_rset(eid).get_entity(0, 0)
         return entity.view('reledit', rtype=rtype, role=role,
-                           landing_zone=lzone)
+                           default=default, landing_zone=lzone)
 
     @jsonize
     def js_i18n(self, msgids):
--- a/web/views/cwproperties.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/web/views/cwproperties.py	Thu Jul 23 15:33:03 2009 +0200
@@ -228,10 +228,9 @@
 class CWPropertiesForm(SystemCWPropertiesForm):
     id = 'propertiesform'
     __select__ = (
-        # we don't want guests to be able to come here
-        match_user_groups('users', 'managers') &
-        (none_rset() | ((one_line_rset() & is_user_prefs()) &
-                        (one_line_rset() & match_user_groups('managers'))))
+        (none_rset() & match_user_groups('users','managers'))
+        | (one_line_rset() & match_user_groups('users') & is_user_prefs())
+        | (one_line_rset() & match_user_groups('managers') & implements('CWUser'))
         )
 
     title = _('preferences')
--- a/web/views/cwuser.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/web/views/cwuser.py	Thu Jul 23 15:33:03 2009 +0200
@@ -25,7 +25,7 @@
 
     def url(self):
         login = self.rset.get_entity(self.row or 0, self.col or 0).login
-        return self.build_url('cwuser/%s'%login, vid='epropertiesform')
+        return self.build_url('cwuser/%s'%login, vid='propertiesform')
 
 
 class FoafView(EntityView):
--- a/web/webctl.py	Thu Jul 23 15:29:07 2009 +0200
+++ b/web/webctl.py	Thu Jul 23 15:33:03 2009 +0200
@@ -8,6 +8,7 @@
 """
 __docformat__ = "restructuredtext en"
 
+from cubicweb import underline_title
 from cubicweb.toolsutils import CommandHandler, confirm
 
 
@@ -16,14 +17,12 @@
 
     def bootstrap(self, cubes, inputlevel=0):
         """bootstrap this configuration"""
-        print '** generic web configuration'
+        print '\n'+underline_title('Generic web configuration')
         config = self.config
         if config.repo_method == 'pyro':
-            print
-            print '** repository server configuration'
-            print '-' * 72
+            print '\n'+underline_title('Repository server configuration')
             config.input_config('pyro-client', inputlevel)
-        if confirm('allow anonymous access', False):
+        if confirm('Allow anonymous access ?', False):
             config.global_set_option('anonymous-user', 'anon')
             config.global_set_option('anonymous-password', 'anon')