--- a/cwconfig.py Tue Feb 16 11:30:52 2010 +0100
+++ b/cwconfig.py Thu Feb 18 07:29:13 2010 +0100
@@ -328,7 +328,7 @@
cubes = set()
for directory in cls.cubes_search_path():
if not os.path.exists(directory):
- self.error('unexistant directory in cubes search path: %s'
+ cls.error('unexistant directory in cubes search path: %s'
% directory)
continue
for cube in os.listdir(directory):
@@ -347,7 +347,7 @@
path.append(directory)
except KeyError:
pass
- if not cls.CUBES_DIR in path:
+ if not cls.CUBES_DIR in path and exists(cls.CUBES_DIR):
path.append(cls.CUBES_DIR)
return path
@@ -474,7 +474,7 @@
from logilab.common.modutils import load_module_from_file
cls.cls_adjust_sys_path()
for ctlfile in ('web/webctl.py', 'etwist/twctl.py',
- 'server/serverctl.py',
+ 'server/serverctl.py',
'devtools/devctl.py', 'goa/goactl.py'):
if exists(join(CW_SOFTWARE_ROOT, ctlfile)):
try:
--- a/cwctl.py Tue Feb 16 11:30:52 2010 +0100
+++ b/cwctl.py Thu Feb 18 07:29:13 2010 +0100
@@ -297,14 +297,18 @@
# create the registry directory for this instance
print '\n'+underline_title('Creating the instance %s' % appid)
create_dir(config.apphome)
- # load site_cubicweb from the cubes dir (if any)
- config.load_site_cubicweb()
# cubicweb-ctl configuration
print '\n'+underline_title('Configuring the instance (%s.conf)' % configname)
config.input_config('main', self.config.config_level)
# configuration'specific stuff
print
helper.bootstrap(cubes, self.config.config_level)
+ # input for cubes specific options
+ for section in set(sect.lower() for sect, opt, optdict in config.all_options()
+ if optdict.get('inputlevel') <= self.config.config_level):
+ if section not in ('main', 'email', 'pyro'):
+ print '\n' + underline_title('%s options' % section)
+ config.input_config(section, self.config.config_level)
# write down configuration
config.save()
self._handle_win32(config, appid)
--- a/devtools/dataimport.py Tue Feb 16 11:30:52 2010 +0100
+++ b/devtools/dataimport.py Thu Feb 18 07:29:13 2010 +0100
@@ -134,7 +134,7 @@
try:
for func in funcs:
res[dest] = func(res[dest])
- if res[dest] is None or res[dest]==False:
+ if res[dest] is None:
raise AssertionError('undetermined value')
except AssertionError, err:
if optional in funcs:
@@ -220,7 +220,26 @@
return txt.strip()
def yesno(value):
- return value.lower()[0] in 'yo1'
+ """simple heuristic that returns boolean value
+
+ >>> yesno("Yes")
+ True
+ >>> yesno("oui")
+ True
+ >>> yesno("1")
+ True
+ >>> yesno("11")
+ True
+ >>> yesno("")
+ False
+ >>> yesno("Non")
+ False
+ >>> yesno("blablabla")
+ False
+ """
+ if value:
+ return value.lower()[0] in 'yo1'
+ return False
def isalpha(value):
if value.isalpha():
--- a/misc/migration/postcreate.py Tue Feb 16 11:30:52 2010 +0100
+++ b/misc/migration/postcreate.py Thu Feb 18 07:29:13 2010 +0100
@@ -5,7 +5,6 @@
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
"""
-
# insert versions
create_entity('CWProperty', pkey=u'system.version.cubicweb',
value=unicode(config.cubicweb_version()))
@@ -38,9 +37,8 @@
print 'you are using a manager account as anonymous user.'
print 'Hopefully this is not a production instance...'
elif anonlogin:
- rql('INSERT CWUser X: X login %(login)s, X upassword %(pwd)s,'
- 'X in_group G WHERE G name "guests"',
- {'login': unicode(anonlogin), 'pwd': anonpwd})
+ from cubicweb.server import create_user
+ create_user(session, unicode(anonlogin), anonpwd, 'guests')
# need this since we already have at least one user in the database (the default admin)
for user in rql('Any X WHERE X is CWUser').entities():
--- a/schema.py Tue Feb 16 11:30:52 2010 +0100
+++ b/schema.py Thu Feb 18 07:29:13 2010 +0100
@@ -254,7 +254,9 @@
return
# if 'owners' in allowed groups, check if the user actually owns this
# object, if so that's enough
- if 'owners' in groups and 'eid' in kwargs and session.user.owns(kwargs['eid']):
+ if 'owners' in groups and (
+ kwargs.get('creating')
+ or ('eid' in kwargs and session.user.owns(kwargs['eid']))):
return
# else if there is some rql expressions, check them
if any(rqlexpr.check(session, **kwargs)
@@ -787,20 +789,25 @@
session may actually be a request as well
"""
- if self.eid is not None:
+ creating = kwargs.get('creating')
+ if not creating and self.eid is not None:
key = (self.eid, tuple(sorted(kwargs.iteritems())))
try:
return session.local_perm_cache[key]
except KeyError:
pass
rql, has_perm_defs, keyarg = self.transform_has_permission()
+ if creating:
+ # when creating an entity, consider has_*_permission satisfied
+ if has_perm_defs:
+ return True
+ return False
if keyarg is None:
# on the server side, use unsafe_execute, but this is not available
# on the client side (session is actually a request)
execute = getattr(session, 'unsafe_execute', session.execute)
- # XXX what if 'u' in kwargs
+ kwargs.setdefault('u', session.user.eid)
cachekey = kwargs.keys()
- kwargs['u'] = session.user.eid
try:
rset = execute(rql, kwargs, cachekey, build_descr=True)
except NotImplementedError:
@@ -864,12 +871,15 @@
rql += ', U eid %(u)s'
return rql
- def check(self, session, eid=None):
+ def check(self, session, eid=None, creating=False, **kwargs):
if 'X' in self.rqlst.defined_vars:
if eid is None:
+ if creating:
+ return self._check(session, creating=True, **kwargs)
return False
- return self._check(session, x=eid)
- return self._check(session)
+ assert creating == False
+ return self._check(session, x=eid, **kwargs)
+ return self._check(session, **kwargs)
class RRQLExpression(RQLExpression):
--- a/server/__init__.py Tue Feb 16 11:30:52 2010 +0100
+++ b/server/__init__.py Thu Feb 18 07:29:13 2010 +0100
@@ -93,6 +93,14 @@
# database initialization ######################################################
+def create_user(session, login, pwd, *groups):
+ # monkey patch this method if you want to customize admin/anon creation
+ # (that maybe necessary if you change CWUser's schema)
+ session.create_entity('CWUser', login=login, upassword=pwd)
+ for group in groups:
+ session.execute('SET U in_group G WHERE G name %(group)s',
+ {'group': group})
+
def init_repository(config, interactive=True, drop=False, vreg=None):
"""initialise a repository database by creating tables add filling them
with the minimal set of entities (ie at least the schema, base groups and
@@ -161,9 +169,7 @@
for group in sorted(BASE_GROUPS):
session.execute('INSERT CWGroup X: X name %(name)s',
{'name': unicode(group)})
- session.execute('INSERT CWUser X: X login %(login)s, X upassword %(pwd)s',
- {'login': login, 'pwd': pwd})
- session.execute('SET U in_group G WHERE G name "managers"')
+ create_user(session, login, pwd, 'managers')
session.commit()
# reloging using the admin user
config._cubes = None # avoid assertion error
--- a/test/data/rrqlexpr_on_attr.py Tue Feb 16 11:30:52 2010 +0100
+++ b/test/data/rrqlexpr_on_attr.py Thu Feb 18 07:29:13 2010 +0100
@@ -20,6 +20,5 @@
class attr(RelationType):
__permissions__ = {
'read': ('managers', ),
- 'add': ('managers', RRQLExpression('S bla Y'),),
- 'delete': ('managers',),
+ 'update': ('managers', RRQLExpression('S bla Y'),),
}
--- a/test/unittest_schema.py Tue Feb 16 11:30:52 2010 +0100
+++ b/test/unittest_schema.py Thu Feb 18 07:29:13 2010 +0100
@@ -257,7 +257,7 @@
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)")
+ self._test('rrqlexpr_on_eetype.py', "can't use RRQLExpression on ToTo, use an ERQLExpression")
def test_erqlexpr_on_rtype(self):
self._test('erqlexpr_on_ertype.py', "can't use ERQLExpression on relation ToTo toto TuTu, use a RRQLExpression")
--- a/web/data/cubicweb.login.css Tue Feb 16 11:30:52 2010 +0100
+++ b/web/data/cubicweb.login.css Thu Feb 18 07:29:13 2010 +0100
@@ -1,7 +1,7 @@
/* styles for the login popup and login form
*
* :organization: Logilab
- * :copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+ * :copyright: 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
* :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
*/
@@ -11,8 +11,11 @@
right: 0px;
width: 26em;
padding: 0px 1px 1px;
+ background: #E4EAD8;
+}
+
+div#popupLoginBox label{
font-weight: bold;
- background: #E4EAD8;
}
div#popupLoginBox div#loginContent {
@@ -72,7 +75,7 @@
}
#loginContent input.data {
- width:12em;
+ width: 12em;
}
.loginButton {
@@ -81,3 +84,7 @@
margin: 2px 0px 0px;
background: #f0eff0 url("gradient-grey-up.png") left top repeat-x;
}
+
+#loginContent .formButtonBar {
+ float: right;
+}
--- a/web/facet.py Tue Feb 16 11:30:52 2010 +0100
+++ b/web/facet.py Thu Feb 18 07:29:13 2010 +0100
@@ -268,25 +268,16 @@
needs_update = False
start_unfolded = True
- def __init__(self, req, rset=None, rqlst=None, filtered_variable=None,
+ def __init__(self, req, rqlst=None, filtered_variable=None,
**kwargs):
- super(AbstractFacet, self).__init__(req, rset=rset, **kwargs)
- assert rset is not None or rqlst is not None
+ super(AbstractFacet, self).__init__(req, **kwargs)
+ assert rqlst is not None
assert filtered_variable
- # facet retreived using `object_by_id` from an ajax call
- if rset is None:
- self.init_from_form(rqlst=rqlst)
- # facet retreived from `select` using the result set to filter
- else:
- self.init_from_rset()
+ # take care: facet may be retreived using `object_by_id` from an ajax call
+ # or from `select` using the result set to filter
+ self.rqlst = rqlst
self.filtered_variable = filtered_variable
- def init_from_rset(self):
- self.rqlst = self.cw_rset.syntax_tree().children[0]
-
- def init_from_form(self, rqlst):
- self.rqlst = rqlst
-
@property
def operator(self):
# OR between selected values by default
@@ -521,6 +512,9 @@
def get_widget(self):
"""return the widget instance to use to display this facet"""
values = set(value for _, value in self.vocabulary() if value is not None)
+ # Rset with entities (the facet is selected) but without values
+ if len(values) == 0:
+ return None
return self.wdgclass(self, min(values), max(values))
def infvalue(self):
--- a/web/uicfg.py Tue Feb 16 11:30:52 2010 +0100
+++ b/web/uicfg.py Thu Feb 18 07:29:13 2010 +0100
@@ -379,7 +379,8 @@
continue
rdef = rschema.role_rdef(eschema, tschema, role)
if rschema.final:
- if not rdef.has_perm(cw, permission, eid=eid):
+ if not rdef.has_perm(cw, permission, eid=eid,
+ creating=eid is None):
continue
elif strict or not rdef.has_local_role(relpermission):
if role == 'subject':
--- a/web/views/basetemplates.py Tue Feb 16 11:30:52 2010 +0100
+++ b/web/views/basetemplates.py Thu Feb 18 07:29:13 2010 +0100
@@ -9,6 +9,7 @@
__docformat__ = "restructuredtext en"
from logilab.mtconverter import xml_escape
+from logilab.common.deprecation import class_renamed
from cubicweb.appobject import objectify_selector
from cubicweb.selectors import match_kwargs
@@ -398,7 +399,7 @@
if state[0] == 'normal':
return
_ = self._cw._
- value = self.view('oneline', self._cw.eid_rset(state[1][1]))
+ value = self._cw.view('oneline', self._cw.eid_rset(state[1][1]))
msg = ' '.join((_("searching for"),
display_name(self._cw, state[1][3]),
_("to associate with"), value,
@@ -465,12 +466,13 @@
class LogForm(forms.FieldsForm):
__regid__ = 'logform'
domid = 'loginForm'
+ needs_css = ('cubicweb.login.css',)
# XXX have to recall fields name since python is mangling __login/__password
__login = ff.StringField('__login', widget=fw.TextInput({'class': 'data'}))
__password = ff.StringField('__password', label=_('password'),
widget=fw.PasswordSingleInput({'class': 'data'}))
form_buttons = [fw.SubmitButton(label=_('log in'),
- attrs={'class': 'loginButton right'})]
+ attrs={'class': 'loginButton'})]
@property
def action(self):
@@ -484,7 +486,6 @@
title = 'log in'
def call(self, id, klass, title=True, showmessage=True):
- self._cw.add_css('cubicweb.login.css')
self.w(u'<div id="%s" class="%s">' % (id, klass))
if title:
stitle = self._cw.property_value('ui.site-title')
@@ -512,6 +513,8 @@
self.w(form.render(table_class='', display_progress_div=False))
cw.html_headers.add_onload('jQuery("#__login:visible").focus()')
+LogFormTemplate = class_renamed('LogFormTemplate', LogFormView)
+
def login_form_url(req):
if req.https:
return req.url()
--- a/web/views/facets.py Tue Feb 16 11:30:52 2010 +0100
+++ b/web/views/facets.py Thu Feb 18 07:29:13 2010 +0100
@@ -69,37 +69,38 @@
rset, vid, divid, paginate = self._get_context(view)
if rset.rowcount < 2: # XXX done by selectors, though maybe necessary when rset has been hijacked
return
+ rqlst = self.cw_rset.syntax_tree()
+ # union not yet supported
+ if len(rqlst.children) != 1:
+ return ()
+ rqlst = rqlst.copy()
+ req.vreg.rqlhelper.annotate(rqlst)
+ mainvar, baserql = prepare_facets_rqlst(rqlst, rset.args)
+ widgets = []
+ for facet in self.get_facets(rset, rqlst.children[0], mainvar):
+ if facet.cw_propval('visible'):
+ wdg = facet.get_widget()
+ if wdg is not None:
+ widgets.append(wdg)
+ if not widgets:
+ return
if vid is None:
vid = req.form.get('vid')
- rqlst = rset.syntax_tree()
- rqlst.save_state()
- try:
- mainvar, baserql = prepare_facets_rqlst(rqlst, rset.args)
- widgets = []
- for facet in self.get_facets(rset, mainvar):
- if facet.cw_propval('visible'):
- wdg = facet.get_widget()
- if wdg is not None:
- widgets.append(wdg)
- if not widgets:
- return
- if self.bk_linkbox_template:
- self.display_bookmark_link(rset)
- w = self.w
- w(u'<form method="post" id="%sForm" cubicweb:facetargs="%s" action="">' % (
- divid, xml_escape(dumps([divid, vid, paginate, self.facetargs()]))))
- w(u'<fieldset>')
- hiddens = {'facets': ','.join(wdg.facet.__regid__ for wdg in widgets),
- 'baserql': baserql}
- for param in ('subvid', 'vtitle'):
- if param in req.form:
- hiddens[param] = req.form[param]
- filter_hiddens(w, **hiddens)
- for wdg in widgets:
- wdg.render(w=self.w)
- w(u'</fieldset>\n</form>\n')
- finally:
- rqlst.recover()
+ if self.bk_linkbox_template:
+ self.display_bookmark_link(rset)
+ w = self.w
+ w(u'<form method="post" id="%sForm" cubicweb:facetargs="%s" action="">' % (
+ divid, xml_escape(dumps([divid, vid, paginate, self.facetargs()]))))
+ w(u'<fieldset>')
+ hiddens = {'facets': ','.join(wdg.facet.__regid__ for wdg in widgets),
+ 'baserql': baserql}
+ for param in ('subvid', 'vtitle'):
+ if param in req.form:
+ hiddens[param] = req.form[param]
+ filter_hiddens(w, **hiddens)
+ for wdg in widgets:
+ wdg.render(w=self.w)
+ w(u'</fieldset>\n</form>\n')
def display_bookmark_link(self, rset):
eschema = self._cw.vreg.schema.eschema('Bookmark')
@@ -115,10 +116,10 @@
self._cw._('bookmark this search'))
self.w(self.bk_linkbox_template % bk_link)
- def get_facets(self, rset, mainvar):
- return self._cw.vreg['facets'].poss_visible_objects(self._cw, rset=rset,
- context='facetbox',
- filtered_variable=mainvar)
+ def get_facets(self, rset, rqlst, mainvar):
+ return self._cw.vreg['facets'].poss_visible_objects(
+ self._cw, rset=rset, rqlst=rqlst,
+ context='facetbox', filtered_variable=mainvar)
# facets ######################################################################
--- a/web/views/tableview.py Tue Feb 16 11:30:52 2010 +0100
+++ b/web/views/tableview.py Thu Feb 18 07:29:13 2010 +0100
@@ -33,13 +33,13 @@
# union not yet supported
if len(rqlst.children) != 1:
return ()
- rqlst.save_state()
+ rqlst = rqlst.copy()
+ self._cw.vreg.rqlhelper.annotate(rqlst)
mainvar, baserql = prepare_facets_rqlst(rqlst, self.cw_rset.args)
wdgs = [facet.get_widget() for facet in self._cw.vreg['facets'].poss_visible_objects(
- self._cw, rset=self.cw_rset, context='tablefilter',
+ self._cw, rset=self.cw_rset, rqlst=rqlst.children[0], context='tablefilter',
filtered_variable=mainvar)]
wdgs = [wdg for wdg in wdgs if wdg is not None]
- rqlst.recover()
if wdgs:
self._generate_form(divid, baserql, wdgs, hidden,
vidargs={'displaycols': displaycols,
--- a/web/views/tabs.py Tue Feb 16 11:30:52 2010 +0100
+++ b/web/views/tabs.py Thu Feb 18 07:29:13 2010 +0100
@@ -8,6 +8,7 @@
__docformat__ = "restructuredtext en"
+from logilab.common.deprecation import class_renamed
from logilab.mtconverter import xml_escape
from cubicweb import NoSelectableObject, role
@@ -187,11 +188,11 @@
def cell_call(self, row, col):
entity = self.cw_rset.complete_entity(row, col)
+ self.render_entity_toolbox(entity)
self.render_entity_title(entity)
- # XXX uncomment this in 3.6
- #self.render_entity_toolbox(entity)
self.render_tabs(self.tabs, self.default_tab, entity)
-TabedPrimaryView = TabbedPrimaryView # XXX deprecate that typo!
+
+TabedPrimaryView = class_renamed('TabedPrimaryView', TabbedPrimaryView)
class PrimaryTab(primary.PrimaryView):
__regid__ = 'main_tab'