--- a/cwconfig.py Thu Nov 03 11:18:37 2011 +0100
+++ b/cwconfig.py Thu Nov 03 15:28:30 2011 +0100
@@ -22,6 +22,9 @@
Resource mode
-------------
+Standard resource mode
+```````````````````````````
+
A resource *mode* is a predefined set of settings for various resources
directories, such as cubes, instances, etc. to ease development with the
framework. There are two running modes with *CubicWeb*:
@@ -30,7 +33,7 @@
usually requiring root access):
- instances are stored in :file:`<INSTALL_PREFIX>/etc/cubicweb.d`
- - temporary files (such as pid file) in :file:`/var/run/cubicweb`
+ - temporary files (such as pid file) in :file:`<INSTALL_PREFIX>/var/run/cubicweb`
where `<INSTALL_PREFIX>` is the detected installation prefix ('/usr/local' for
instance).
@@ -42,6 +45,25 @@
+
+.. _CubicwebWithinVirtualEnv:
+
+Within virtual environment
+```````````````````````````
+
+If you are not administrator of you machine or if you need to play with some
+specific version of |cubicweb| you can use `virtualenv`_ a tool to create
+isolated Python environments. Since version 3.9 |cubicweb| is **`virtualenv`
+friendly** and won't write any file outside the virtualenv directory.
+
+- instances are stored in :file:`<VIRTUAL_ENV>/etc/cubicweb.d`
+- temporary files (such as pid file) in :file:`<VIRTUAL_ENV>/var/run/cubicweb`
+
+.. _`virtualenv`: http://pypi.python.org/pypi/virtualenv
+
+Custom resource location
+````````````````````````````````
+
Notice that each resource path may be explicitly set using an environment
variable if the default doesn't suit your needs. Here are the default resource
directories that are affected according to mode:
@@ -49,8 +71,8 @@
* **system**: ::
CW_INSTANCES_DIR = <INSTALL_PREFIX>/etc/cubicweb.d/
- CW_INSTANCES_DATA_DIR = /var/lib/cubicweb/instances/
- CW_RUNTIME_DIR = /var/run/cubicweb/
+ CW_INSTANCES_DATA_DIR = <INSTALL_PREFIX>/var/lib/cubicweb/instances/
+ CW_RUNTIME_DIR = <INSTALL_PREFIX>/var/run/cubicweb/
* **user**: ::
@@ -60,10 +82,13 @@
Cubes search path is also affected, see the :ref:`Cube` section.
-By default, the mode automatically set to `user` if a :file:`.hg` directory is found
-in the cubicweb package, else it's set to `system`. You can force this by setting
-the :envvar:`CW_MODE` environment variable to either `user` or `system` so you can
-easily:
+Setting Cubicweb Mode
+`````````````````````
+
+By default, the mode is set to 'system' for standard installation. The mode is
+set to 'user' if `cubicweb is used from a mercurial repository`_. You can force
+this by setting the :envvar:`CW_MODE` environment variable to either 'user' or
+'system' so you can easily:
* use system wide installation but user specific instances and all, without root
privileges on the system (`export CW_MODE=user`)
@@ -74,7 +99,15 @@
If you've a doubt about the mode you're currently running, check the first line
outputed by the :command:`cubicweb-ctl list` command.
-Also, if cubicweb is a mercurial checkout located in `<CW_SOFTWARE_ROOT>`:
+.. _`cubicweb is used from a mercurial repository`: CubicwebDevelopmentMod_
+
+.. _CubicwebDevelopmentMod:
+
+Development Mode
+`````````````````````
+If :file:`.hg` directory is found into the cubicweb package, there are specific resource rules.
+
+`<CW_SOFTWARE_ROOT>` is the mercurial checkout of cubicweb:
* main cubes directory is `<CW_SOFTWARE_ROOT>/../cubes`. You can specify
another one with :envvar:`CW_INSTANCES_DIR` environment variable or simply
--- a/rset.py Thu Nov 03 11:18:37 2011 +0100
+++ b/rset.py Thu Nov 03 15:28:30 2011 +0100
@@ -351,7 +351,8 @@
if offset <= entity.cw_row < stop:
entity.cw_row = entity.cw_row - offset
else:
- self.req.drop_entity_cache(entity.eid)
+ entity.cw_rset = entity.as_rset()
+ entity.cw_row = entity.cw_col = 0
else:
rset = self.copy(rows, descr)
if not offset:
--- a/server/migractions.py Thu Nov 03 11:18:37 2011 +0100
+++ b/server/migractions.py Thu Nov 03 15:28:30 2011 +0100
@@ -392,7 +392,7 @@
if cube is None:
directory = osp.join(CW_SOFTWARE_ROOT, 'schemas')
else:
- directory = self.config.cube_dir(cube)
+ directory = osp.join(self.config.cube_dir(cube), 'schema')
sql_scripts = glob(osp.join(directory, '*.%s.sql' % driver))
for fpath in sql_scripts:
print '-> installing', fpath
--- a/test/unittest_rset.py Thu Nov 03 11:18:37 2011 +0100
+++ b/test/unittest_rset.py Thu Nov 03 15:28:30 2011 +0100
@@ -107,7 +107,7 @@
self.compare_urls(req.build_url('view', _restpath=''), baseurl)
- def test_resultset_build(self):
+ def test_build(self):
"""test basic build of a ResultSet"""
rs = ResultSet([1,2,3], 'CWGroup X', description=['CWGroup', 'CWGroup', 'CWGroup'])
self.assertEqual(rs.rowcount, 3)
@@ -115,7 +115,7 @@
self.assertEqual(rs.description, ['CWGroup', 'CWGroup', 'CWGroup'])
- def test_resultset_limit(self):
+ def test_limit(self):
rs = ResultSet([[12000, 'adim'], [13000, 'syt'], [14000, 'nico']],
'Any U,L where U is CWUser, U login L',
description=[['CWUser', 'String']] * 3)
@@ -128,8 +128,30 @@
self.assertEqual(rs.limit(2, offset=2).rows, [[14000, 'nico']])
self.assertEqual(rs.limit(2, offset=3).rows, [])
+ def test_limit_2(self):
+ req = self.request()
+ # drop user from cache for the sake of this test
+ req.drop_entity_cache(req.user.eid)
+ rs = req.execute('Any E,U WHERE E is CWEType, E created_by U')
+ # get entity on row 9. This will fill its created_by relation cache,
+ # with cwuser on row 9 as well
+ e1 = rs.get_entity(9, 0)
+ # get entity on row 10. This will fill its created_by relation cache,
+ # with cwuser built on row 9
+ e2 = rs.get_entity(10, 0)
+ # limit result set from row 10
+ rs.limit(1, 10, inplace=True)
+ # get back eid
+ e = rs.get_entity(0, 0)
+ self.assertTrue(e2 is e)
+ # rs.limit has properly removed cwuser for request cache, but it's
+ # still referenced by e/e2 relation cache
+ u = e.created_by[0]
+ # now ensure this doesn't trigger IndexError because cwuser.cw_row is 9
+ # while now rset has only one row
+ u.cw_rset[u.cw_row]
- def test_resultset_filter(self):
+ def test_filter(self):
rs = ResultSet([[12000, 'adim'], [13000, 'syt'], [14000, 'nico']],
'Any U,L where U is CWUser, U login L',
description=[['CWUser', 'String']] * 3)
@@ -142,7 +164,7 @@
self.assertEqual(len(rs2), 2)
self.assertEqual([login for _, login in rs2], ['adim', 'syt'])
- def test_resultset_transform(self):
+ def test_transform(self):
rs = ResultSet([[12, 'adim'], [13, 'syt'], [14, 'nico']],
'Any U,L where U is CWUser, U login L',
description=[['CWUser', 'String']] * 3)
@@ -154,7 +176,7 @@
self.assertEqual(len(rs2), 3)
self.assertEqual(list(rs2), [['adim'],['syt'],['nico']])
- def test_resultset_sort(self):
+ def test_sort(self):
rs = ResultSet([[12000, 'adim'], [13000, 'syt'], [14000, 'nico']],
'Any U,L where U is CWUser, U login L',
description=[['CWUser', 'String']] * 3)
@@ -179,7 +201,7 @@
# make sure rs is unchanged
self.assertEqual([login for _, login in rs], ['adim', 'syt', 'nico'])
- def test_resultset_split(self):
+ def test_split(self):
rs = ResultSet([[12000, 'adim', u'Adim chez les pinguins'],
[12000, 'adim', u'Jardiner facile'],
[13000, 'syt', u'Le carrelage en 42 leçons'],
--- a/web/data/cubicweb.fckcwconfig-full.js Thu Nov 03 11:18:37 2011 +0100
+++ b/web/data/cubicweb.fckcwconfig-full.js Thu Nov 03 15:28:30 2011 +0100
@@ -29,6 +29,9 @@
FCKConfig.ContextMenu = ['Generic','Link','Anchor','Image','BulletedList','NumberedList','Table'] ;
FCKConfig.LinkUpload = false ;
+FCKConfig.LinkBrowser = false ;
FCKConfig.ImageUpload = false ;
+FCKConfig.ImageBrowser = false ;
FCKConfig.FlashUpload = false ;
+FCKConfig.FlashBrowser = false ;
--- a/web/data/cubicweb.fckcwconfig.js Thu Nov 03 11:18:37 2011 +0100
+++ b/web/data/cubicweb.fckcwconfig.js Thu Nov 03 15:28:30 2011 +0100
@@ -11,5 +11,8 @@
FCKConfig.ContextMenu = ['Generic','Link','Anchor','Image','BulletedList','NumberedList','Table'] ;
FCKConfig.LinkUpload = false ;
+FCKConfig.LinkBrowser = false ;
FCKConfig.ImageUpload = false ;
+FCKConfig.ImageBrowser = false ;
FCKConfig.FlashUpload = false ;
+FCKConfig.FlashBrowser = false ;
--- a/web/views/basecomponents.py Thu Nov 03 11:18:37 2011 +0100
+++ b/web/views/basecomponents.py Thu Nov 03 15:28:30 2011 +0100
@@ -50,25 +50,22 @@
visible = False
def call(self, view=None):
+ req = self._cw
if hasattr(view, 'filter_box_context_info'):
rset = view.filter_box_context_info()[0]
else:
rset = self.cw_rset
# display multilines query as one line
- rql = rset is not None and rset.printable_rql(encoded=False) or self._cw.form.get('rql', '')
+ rql = rset is not None and rset.printable_rql(encoded=False) or req.form.get('rql', '')
rql = rql.replace(u"\n", u" ")
- req = self._cw
- self.w(u'''<div id="rqlinput" class="%s">
- <form action="%s">
-<fieldset>
+ self.w(u'''<div id="rqlinput" class="%s"><form action="%s"><fieldset>
<input type="text" id="rql" name="rql" value="%s" title="%s" tabindex="%s" accesskey="q" class="searchField" />
-</fieldset>
''' % (not self.cw_propval('visible') and 'hidden' or '',
- self._cw.build_url('view'), xml_escape(rql), req._('full text or RQL query'), req.next_tabindex()))
- if self._cw.search_state[0] != 'normal':
+ req.build_url('view'), xml_escape(rql), req._('full text or RQL query'), req.next_tabindex()))
+ if req.search_state[0] != 'normal':
self.w(u'<input type="hidden" name="__mode" value="%s"/>'
% ':'.join(req.search_state[1]))
- self.w(u'</form></div>')
+ self.w(u'</fieldset></form></div>')