# HG changeset patch # User Sylvain Thénault # Date 1266474553 -3600 # Node ID c4adfc2466f5e131e04072f133e2d269a92235eb # Parent e872097f228731e5a35203a39eaae912337debed# Parent f4254586e8670016664b09ebdc0c5222726f72d4 backport stable diff -r e872097f2287 -r c4adfc2466f5 cwconfig.py --- 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: diff -r e872097f2287 -r c4adfc2466f5 cwctl.py --- 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) diff -r e872097f2287 -r c4adfc2466f5 devtools/dataimport.py --- 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(): diff -r e872097f2287 -r c4adfc2466f5 misc/migration/postcreate.py --- 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(): diff -r e872097f2287 -r c4adfc2466f5 schema.py --- 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): diff -r e872097f2287 -r c4adfc2466f5 server/__init__.py --- 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 diff -r e872097f2287 -r c4adfc2466f5 test/data/rrqlexpr_on_attr.py --- 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'),), } diff -r e872097f2287 -r c4adfc2466f5 test/unittest_schema.py --- 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") diff -r e872097f2287 -r c4adfc2466f5 web/data/cubicweb.login.css --- 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; +} diff -r e872097f2287 -r c4adfc2466f5 web/facet.py --- 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): diff -r e872097f2287 -r c4adfc2466f5 web/uicfg.py --- 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': diff -r e872097f2287 -r c4adfc2466f5 web/views/basetemplates.py --- 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'
' % (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() diff -r e872097f2287 -r c4adfc2466f5 web/views/facets.py --- 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'
' % ( - divid, xml_escape(dumps([divid, vid, paginate, self.facetargs()])))) - w(u'
') - 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'
\n
\n') - finally: - rqlst.recover() + if self.bk_linkbox_template: + self.display_bookmark_link(rset) + w = self.w + w(u'
' % ( + divid, xml_escape(dumps([divid, vid, paginate, self.facetargs()])))) + w(u'
') + 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'
\n
\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 ###################################################################### diff -r e872097f2287 -r c4adfc2466f5 web/views/tableview.py --- 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, diff -r e872097f2287 -r c4adfc2466f5 web/views/tabs.py --- 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'