def test_invalid_calls(self): """checks invalid calls raise a ValueError""" # mixing named and positional arguments should fail with self.assertRaises(ValueError) as cm: match_form_params('list', x='1', y='2') self.assertEqual(str(cm.exception), "match_form_params() can't be called with both " "positional and named arguments") # using a dict as first and unique argument should fail with self.assertRaises(ValueError) as cm: match_form_params({'x': 1}) self.assertEqual(str(cm.exception), "match_form_params() positional arguments must be strings")
def test_keyonly_match(self): """test standard usage: ``match_form_params('param1', 'param2')`` ``param1`` and ``param2`` must be specified in request's form. """ web_request = self.admin_access.web_request vid_selector = match_form_params('vid') vid_subvid_selector = match_form_params('vid', 'subvid') # no parameter => KO,KO with web_request() as req: self.assertEqual(vid_selector(None, req), 0) self.assertEqual(vid_subvid_selector(None, req), 0) # one expected parameter found => OK,KO with web_request(vid='foo') as req: self.assertEqual(vid_selector(None, req), 1) self.assertEqual(vid_subvid_selector(None, req), 0) # all expected parameters found => OK,OK with web_request(vid='foo', subvid='bar') as req: self.assertEqual(vid_selector(None, req), 1) self.assertEqual(vid_subvid_selector(None, req), 2)
class BreadCrumbLinkToVComponent(BreadCrumbEntityVComponent): __select__ = basecomponents.HeaderComponent.__select__ & match_form_params( '__linkto') def render(self, w, **kwargs): eid = self._cw.list_form_param('__linkto')[0].split(':')[1] entity = self._cw.entity_from_eid(eid) ecmp = self._cw.vreg[self.__registry__].select(self.__regid__, self._cw, entity=entity, **kwargs) ecmp.render(w, **kwargs)
class AddRelationView(component.EditRelationMixIn, View): """base class for view which let add entities linked by a given relation subclasses should define at least id, rtype and target class attributes. """ __registry__ = 'views' __regid__ = 'xaddrelation' __select__ = (match_form_params('rtype', 'target') | match_kwargs('rtype', 'target')) cw_property_defs = {} # don't want to inherit this from Box expected_kwargs = form_params = ('rtype', 'target') def cell_call(self, row, col, rtype=None, target=None, etype=None): self.rtype = rtype or self._cw.form['rtype'] self.target = target or self._cw.form['target'] self.etype = etype or self._cw.form.get('etype') entity = self.cw_rset.get_entity(row, col) rschema = self._cw.vreg.schema.rschema(self.rtype) if not self.etype: if self.target == 'object': etypes = rschema.objects(entity.e_schema) else: etypes = rschema.subjects(entity.e_schema) if len(etypes) == 1: self.etype = etypes[0] self.w(u'<div id="%s">' % self.domid) self.w( u'<h1>%s</h1>' % self._cw._('relation %(relname)s of %(ent)s') % { 'relname': rschema.display_name(self._cw, role(self)), 'ent': entity.view('incontext') }) self.w(u'<ul class="list-unstyled">') for boxitem in self.unrelated_boxitems(entity): self.w('<li>%s</li>' % boxitem) self.w(u'</ul></div>') def unrelated_entities(self, entity): """returns the list of unrelated entities if etype is not defined on the Box's class, the default behaviour is to use the entity's appropraite vocabulary function """ # use entity.unrelated if we've been asked for a particular etype if getattr(self, 'etype', None): rset = entity.unrelated(self.rtype, self.etype, role(self), ordermethod='fetch_order') self.paginate(self._cw, rset=rset, w=self.w) return rset.entities() super(AddRelationView, self).unrelated_entities(self)
class MailBugReportController(Controller): __regid__ = 'reportbug' __select__ = match_form_params('description') def publish(self, rset=None): req = self._cw desc = req.form['description'] # The description is generated and signed by cubicweb itself, check # description's signature so we don't want to send spam here sign = req.form.get('__signature', '') if not (sign and req.vreg.config.check_text_sign(desc, sign)): raise Forbidden('Invalid content') self.sendmail(req.vreg.config['submit-mail'], req._('%s error report') % req.vreg.config.appid, desc) raise Redirect(req.build_url(__message=req._('bug report sent')))
def test_keyvalue_match_two_parameters(self): """test dict usage: ``match_form_params(param1=value1, param2=value2)`` ``param1`` and ``param2`` must be specified in the request's form and their respective value must be ``value1`` and ``value2``. """ web_request = self.admin_access.web_request vid_subvid_selector = match_form_params(vid='list', subvid='tsearch') # missing one expected parameter => KO with web_request(vid='list') as req: self.assertEqual(vid_subvid_selector(None, req), 0) # expected parameters found but values are incorrect => KO with web_request(vid='list', subvid='foo') as req: self.assertEqual(vid_subvid_selector(None, req), 0) # expected parameters found and values are correct => OK with web_request(vid='list', subvid='tsearch') as req: self.assertEqual(vid_subvid_selector(None, req), 2)
class ChangeStateFormView(form.FormViewMixIn, EntityView): __regid__ = 'statuschange' title = _('status change') __select__ = (one_line_rset() & match_form_params('treid') & adaptable('IWorkflowable')) def cell_call(self, row, col): entity = self.cw_rset.get_entity(row, col) transition = self._cw.entity_from_eid(self._cw.form['treid']) form = self.get_form(entity, transition) self.w(u'<h4>%s %s</h4>\n' % (self._cw._(transition.name), entity.view('oneline'))) msg = self._cw._('status will change from %(st1)s to %(st2)s') % { 'st1': entity.cw_adapt_to('IWorkflowable').printable_state, 'st2': self._cw._(transition.destination(entity).name) } self.w(u'<p>%s</p>\n' % msg) form.render(w=self.w) def redirectpath(self, entity): return entity.rest_path() def get_form(self, entity, transition, **kwargs): # XXX used to specify both rset/row/col and entity in case implements # selector (and not is_instance) is used on custom form form = self._cw.vreg['forms'].select( 'changestate', self._cw, entity=entity, transition=transition, redirect_path=self.redirectpath(entity), **kwargs) trinfo = self._cw.vreg['etypes'].etype_class('TrInfo')(self._cw) trinfo.eid = next(self._cw.varmaker) subform = self._cw.vreg['forms'].select('edition', self._cw, entity=trinfo, mainform=False) subform.field_by_name('wf_info_for', 'subject').value = entity.eid trfield = subform.field_by_name('by_transition', 'subject') trfield.widget = fwdgs.HiddenInput() trfield.value = transition.eid form.add_subform(subform) return form
def test_keyvalue_multiple_match(self): """test dict usage with multiple values i.e. as in ``match_form_params(param1=('value1', 'value2'))`` ``param1`` must be specified in the request's form and its value must be either ``value1`` or ``value2``. """ web_request = self.admin_access.web_request vid_subvid_selector = match_form_params(vid='list', subvid=('tsearch', 'listitem')) # expected parameters found and values correct => OK with web_request(vid='list', subvid='tsearch') as req: self.assertEqual(vid_subvid_selector(None, req), 2) with web_request(vid='list', subvid='listitem') as req: self.assertEqual(vid_subvid_selector(None, req), 2) # expected parameters found but values are incorrect => OK with web_request(vid='list', subvid='foo') as req: self.assertEqual(vid_subvid_selector(None, req), 0)
def test_keyvalue_match_one_parameter(self): """test dict usage: ``match_form_params(param1=value1)`` ``param1`` must be specified in the request's form and its value must be ``value1``. """ web_request = self.admin_access.web_request # test both positional and named parameters vid_selector = match_form_params(vid='foo') # no parameter => should fail with web_request() as req: self.assertEqual(vid_selector(None, req), 0) # expected parameter found with expected value => OK with web_request(vid='foo', subvid='bar') as req: self.assertEqual(vid_selector(None, req), 1) # expected parameter found but value is incorrect => KO with web_request(vid='bar') as req: self.assertEqual(vid_selector(None, req), 0)
class UndoController(Controller): __regid__ = 'undo' __select__ = authenticated_user() & match_form_params('txuuid') def publish(self, rset=None): txuuid = self._cw.form['txuuid'] try: self._cw.cnx.undo_transaction(txuuid) except UndoTransactionException as exc: errors = exc.errors #This will cause a rollback in main_publish raise ValidationError(None, {None: '\n'.join(errors)}) else: self.redirect() # Will raise Redirect def redirect(self, msg=None): req = self._cw msg = msg or req._("transaction undone") self._redirect({'_cwmsgid': req.set_redirect_message(msg)})
class InlineHelpImageView(StartupView): __regid__ = 'wdocimages' __select__ = match_form_params('fid') binary = True templatable = False content_type = 'image/png' def call(self): fid = self._cw.form['fid'] for lang in chain((self._cw.lang, self._cw.vreg.property_value('ui.language')), self._cw.vreg.config.available_languages()): rid = join('images', '%s_%s.png' % (fid, lang)) resourcedir = self._cw.vreg.config.locate_doc_file(rid) if resourcedir: break else: raise NotFound with io.open(join(resourcedir, rid)) as f: self.w(f.read())
class UnrelatedDivs(EntityView): __regid__ = 'unrelateddivs' __select__ = match_form_params('relation') def cell_call(self, row, col): entity = self.cw_rset.get_entity(row, col) relname, role = self._cw.form.get('relation').rsplit('_', 1) rschema = self._cw.vreg.schema.rschema(relname) hidden = 'hidden' in self._cw.form is_cell = 'is_cell' in self._cw.form self.w( self.build_unrelated_select_div(entity, rschema, role, is_cell=is_cell, hidden=hidden)) def build_unrelated_select_div(self, entity, rschema, role, is_cell=False, hidden=True): options = [] divid = 'div%s_%s_%s' % (rschema.type, role, entity.eid) selectid = 'select%s_%s_%s' % (rschema.type, role, entity.eid) if rschema.symmetric or role == 'subject': targettypes = rschema.objects(entity.e_schema) etypes = '/'.join( sorted(etype.display_name(self._cw) for etype in targettypes)) else: targettypes = rschema.subjects(entity.e_schema) etypes = '/'.join( sorted(etype.display_name(self._cw) for etype in targettypes)) etypes = uilib.cut( etypes, self._cw.property_value('navigation.short-line-size')) options.append('<option>%s %s</option>' % (self._cw._('select a'), etypes)) options += self._get_select_options(entity, rschema, role) options += self._get_search_options(entity, rschema, role, targettypes) relname, role = self._cw.form.get('relation').rsplit('_', 1) return u"""\ <div class="%s" id="%s"> <select id="%s" onchange="javascript: addPendingInsert(this.options[this.selectedIndex], %s, %s, '%s');"> %s </select> </div> """ % (hidden and 'hidden' or '', divid, selectid, xml_escape(json_dumps(entity.eid)), is_cell and 'true' or 'null', relname, '\n'.join(options)) def _get_select_options(self, entity, rschema, role): """add options to search among all entities of each possible type""" options = [] pending_inserts = get_pending_inserts(self._cw, entity.eid) rtype = rschema.type form = self._cw.vreg['forms'].select('edition', self._cw, entity=entity) field = form.field_by_name(rschema, role, entity.e_schema) limit = self._cw.property_value('navigation.combobox-limit') # NOTE: expect 'limit' arg on choices method of relation field for eview, reid in field.vocabulary(form, limit=limit): if reid is None: if eview: # skip blank value options.append( '<option class="separator">-- %s --</option>' % xml_escape(eview)) elif reid != ff.INTERNAL_FIELD_VALUE: optionid = relation_id(entity.eid, rtype, role, reid) if optionid not in pending_inserts: # prefix option's id with letters to make valid XHTML wise options.append('<option id="id%s" value="%s">%s</option>' % (optionid, reid, xml_escape(eview))) return options def _get_search_options(self, entity, rschema, role, targettypes): """add options to search among all entities of each possible type""" options = [] _ = self._cw._ for eschema in targettypes: mode = '%s:%s:%s:%s' % (role, entity.eid, rschema.type, eschema) url = self._cw.build_url(entity.rest_path(), vid='search-associate', __mode=mode) options.append((eschema.display_name(self._cw), '<option value="%s">%s %s</option>' % (xml_escape(url), _('Search for'), eschema.display_name(self._cw)))) return [o for l, o in sorted(options)]
class InlineHelpView(StartupView): __select__ = match_form_params('fid') __regid__ = 'wdoc' title = _('site documentation') def call(self): fid = self._cw.form['fid'] vreg = self._cw.vreg for lang in chain((self._cw.lang, vreg.property_value('ui.language')), vreg.config.available_languages()): rid = '%s_%s.rst' % (fid, lang) resourcedir = vreg.config.locate_doc_file(rid) if resourcedir: break else: raise NotFound self.tocindex = build_toc(vreg.config) try: node, parent = self.tocindex[fid] except KeyError: node, parent = None, None else: self.navigation_links(node, parent) self.w(u'<div class="hr"></div>') self.w(u'<h1>%s</h1>' % (title_for_lang(node, self._cw.lang))) with io.open(join(resourcedir, rid)) as f: self.w(rest_publish(self, f.read())) if node is not None: self.subsections_links(node) self.w(u'<div class="hr"></div>') self.navigation_links(node, parent) def navigation_links(self, node, parent): if parent is None: return brothers = subsections(parent) self.w(u'<div class="docnav">\n') previousidx = brothers.index(node) - 1 if previousidx >= 0: self.navsection(brothers[previousidx], 'prev') self.navsection(parent, 'up') nextidx = brothers.index(node) + 1 if nextidx < len(brothers): 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) self.w(u'%s : ' % self._cw._(msgid)) self.w(u'<a href="%s">%s</a>' % ( self._cw.build_url('doc/' + node.attrib['resource']), title_for_lang(node, self._cw.lang))) self.w(u'</span>\n') def subsections_links(self, node, first=True): sub = subsections(node) if not sub: return if first: self.w(u'<div class="hr"></div>') self.w(u'<ul class="docsum">') for child in sub: self.w(u'<li><a href="%s">%s</a>' % ( self._cw.build_url('doc/' + child.attrib['resource']), title_for_lang(child, self._cw.lang))) self.subsections_links(child, False) self.w(u'</li>') self.w(u'</ul>\n')