def test_individual_admins_post_errors(self): with self.request_context_with_admin("/", method="POST"): flask.request.form = MultiDict([]) response = self.manager.admin_individual_admin_settings_controller.process_post() eq_(response.uri, INCOMPLETE_CONFIGURATION.uri) with self.request_context_with_admin("/", method="POST"): flask.request.form = MultiDict([ ("email", "*****@*****.**"), ("roles", json.dumps([{ "role": AdminRole.LIBRARIAN, "library": "notalibrary" }])), ]) response = self.manager.admin_individual_admin_settings_controller.process_post() eq_(response.uri, LIBRARY_NOT_FOUND.uri) library = self._library() with self.request_context_with_admin("/", method="POST"): flask.request.form = MultiDict([ ("email", "*****@*****.**"), ("roles", json.dumps([{ "role": "notarole", "library": library.short_name }])), ]) response = self.manager.admin_individual_admin_settings_controller.process_post() eq_(response.uri, UNKNOWN_ROLE.uri) with self.request_context_with_admin("/", method="POST"): flask.request.form = MultiDict([ ("email", "wrong!"), ("password", "pass"), ("roles", json.dumps([{ "role": AdminRole.LIBRARY_MANAGER, "library": self._default_library.short_name }])), ]) response = self.manager.admin_individual_admin_settings_controller.process_post() eq_(response.uri, INVALID_EMAIL.uri) assert "wrong!" in response.detail
def test_is_valid_issue_form(self): """Assert that we get the form parameters we want.""" incomplete_form = MultiDict([('problem_category', 'unknown_bug')]) self.assertFalse(helpers.is_valid_issue_form(incomplete_form)) valid_form = MultiDict([ ('browser', 'Firefox 61.0'), ('description', 'streamlining the form.'), ('details', ''), ('os', 'Mac OS X 10.13'), ('problem_category', 'unknown_bug'), ('submit_type', 'github-auth-report'), ('url', 'http://2479.example.com'), ('username', ''), ]) self.assertTrue(helpers.is_valid_issue_form(valid_form)) # The value for submit-Type can be only: # - github-auth-report # - github-proxy-report wrong_value_form = MultiDict([ ('browser', 'Firefox 61.0'), ('description', 'streamlining the form.'), ('details', ''), ('os', 'Mac OS X 10.13'), ('problem_category', 'unknown_bug'), ('submit_type', 'wrong-value'), ('url', 'http://2479.example.com'), ('username', ''), ]) self.assertFalse(helpers.is_valid_issue_form(wrong_value_form))
def test_is_valid_issue_form(self): """Assert that we get the form parameters we want.""" cookie = 'exp=form-v1; Path=/' with webcompat.app.test_request_context( environ_base={'HTTP_COOKIE': cookie}): webcompat.app.preprocess_request() incomplete_form = MultiDict([('problem_category', 'unknown_bug')]) self.assertFalse(helpers.is_valid_issue_form(incomplete_form)) valid_form = MultiDict([ ('browser', 'Firefox 61.0'), ('description', 'streamlining the form.'), ('details', ''), ('os', 'Mac OS X 10.13'), ('problem_category', 'unknown_bug'), ('submit_type', 'github-auth-report'), ('url', 'http://2479.example.com'), ('username', ''), ]) self.assertTrue(helpers.is_valid_issue_form(valid_form)) # The value for submit-Type can be only: # - github-auth-report # - github-proxy-report wrong_value_form = MultiDict([ ('browser', 'Firefox 61.0'), ('description', 'streamlining the form.'), ('details', ''), ('os', 'Mac OS X 10.13'), ('problem_category', 'unknown_bug'), ('submit_type', 'wrong-value'), ('url', 'http://2479.example.com'), ('username', ''), ]) self.assertFalse(helpers.is_valid_issue_form(wrong_value_form))
def GetValidFilters (args): filters = MultiDict() for arg, val in args.iteritems(True): if arg in ValidFilters: filters.add(arg, val) return filters
def _prep_input(self, method, data, content_type): """Return encoded and packed POST data.""" if data is None or method != 'POST': prepped = { 'input_stream': None, 'content_length': None, 'content_type': None, } if method == 'GET' and data: qs = MultiDict() for key, value in to_pairs(data): qs.setlistdefault(key).append(value) prepped['query_string'] = url_encode(qs) return prepped else: if content_type == 'multipart/form-data': data = [(k, _wrap_file(*v)) if isinstance(v, tuple) else (k,v) for k,v in data] boundary, payload = encode_multipart(MultiDict(to_pairs(data))) content_type = 'multipart/form-data; boundary=' + boundary else: payload = url_encode(MultiDict(to_pairs(data))) content_type = 'application/x-www-form-urlencoded' return { 'input_stream': StringIO(payload), 'content_length': len(payload), 'content_type': content_type }
def test_date_range_supports_variable_precision(self): """Date range in advanced search should support variable precision.""" data = MultiDict({ 'terms-0-operator': 'AND', 'terms-0-field': 'title', 'terms-0-term': 'foo', 'date-filter_by': 'date_range', 'date-to_date': '2012-02-05' }) form = AdvancedSearchForm(data) self.assertTrue(form.validate()) data = MultiDict({ 'terms-0-operator': 'AND', 'terms-0-field': 'title', 'terms-0-term': 'foo', 'date-filter_by': 'date_range', 'date-to_date': '2012-02' }) form = AdvancedSearchForm(data) self.assertTrue(form.validate()) data = MultiDict({ 'terms-0-operator': 'AND', 'terms-0-field': 'title', 'terms-0-term': 'foo', 'date-filter_by': 'date_range', 'date-to_date': '2013', 'date-from_date': '2012-03' }) form = AdvancedSearchForm(data) self.assertTrue(form.validate())
def test_bad_parameters(self) -> None: """Test parameters with bad values.""" request_data = MultiDict({ 'id': 'foo', # invalid 'function': 'prev', # valid 'context': 'cs.AI' # valid }) with self.assertRaises(BadRequest): prevnext.get_prevnext(request_data) request_data = MultiDict({ 'id': 'cs/0001001', # valid 'function': 'bar', # invalid 'context': 'cs' # valid }) with self.assertRaises(BadRequest): prevnext.get_prevnext(request_data) request_data = MultiDict({ 'id': 'cs/0001001', # valid 'function': 'next', # valid 'context': 'baz' # invalid }) with self.assertRaises(BadRequest): prevnext.get_prevnext(request_data)
def GetValidFilters(args): filters = MultiDict() for arg, val in args.iteritems(True): if arg in ValidFilters: filters.add(arg, val) return filters
def current_url(self, **kwargs): curl = current_url(self.grid.manager, strip_querystring=True, strip_host=True) href = Href(curl, sort=True) req_args = MultiDict(self.grid.manager.request_args()) # kwargs will be modified with new keys if there is a prefix, so copy the original set # of keys first. Otherwise, the loop may pick up new keys and apply the prefix again key_list = list(kwargs.keys()) for key in key_list: # arg keys may need to be prefixed if self.grid.qs_prefix: prefixed_key = self.grid.qs_prefix + key kwargs[prefixed_key] = kwargs[key] del kwargs[key] key = prefixed_key # multidicts extend, not replace, so we need to get rid of the # keys first try: del req_args[key] except KeyError: pass # convert to md first so that if we have lists in the kwargs, they # are converted appropriately req_args.update(MultiDict(kwargs)) return href(req_args)
def test_good_parameters(self, mock_url_for, mock_get_sequential_id) -> None: # type: ignore """Test parameters with good values.""" request_data = MultiDict({ 'id': '1801.00001', 'function': 'next', 'context': 'all' }) mock_get_sequential_id.return_value = '1801.00002' _, status, headers = prevnext.get_prevnext(request_data) self.assertEqual(status, 301) request_data = MultiDict({ 'id': '1801.00002', 'function': 'prev', 'context': 'cs.AI' }) mock_get_sequential_id.return_value = '1801.00001' _, status, headers = prevnext.get_prevnext(request_data) self.assertEqual(status, 301) request_data = MultiDict({ 'id': '1701.00002', 'function': 'next', 'context': 'physics.gen-ph' }) mock_get_sequential_id.return_value = None with self.assertRaises(BadRequest): prevnext.get_prevnext(request_data) mock_get_sequential_id.return_value = '' with self.assertRaises(BadRequest): prevnext.get_prevnext(request_data)
def test_validate_language_code(self): all_valid = ["eng", "spa", "ita"] all_invalid = ["abc", "def", "ghi"] mixed = ["eng", "abc", "spa"] form = MultiDict([("large_collections", all_valid)]) response = Validator().validate_language_code( Configuration.LIBRARY_SETTINGS, {"form": form}) eq_(response, None) form = MultiDict([("large_collections", all_invalid)]) response = Validator().validate_language_code( Configuration.LIBRARY_SETTINGS, {"form": form}) eq_(response.detail, '"abc" is not a valid language code.') eq_(response.status_code, 400) form = MultiDict([("large_collections", mixed)]) response = Validator().validate_language_code( Configuration.LIBRARY_SETTINGS, {"form": form}) eq_(response.detail, '"abc" is not a valid language code.') eq_(response.status_code, 400) form = MultiDict([("large_collections", all_valid), ("small_collections", all_valid), ("tiny_collections", mixed)]) response = Validator().validate_language_code( Configuration.LIBRARY_SETTINGS, {"form": form}) eq_(response.detail, '"abc" is not a valid language code.') eq_(response.status_code, 400)
def request_withdrawal(method: str, params: MultiDict, session: Session, submission_id: int, **kwargs) -> Response: """Request withdrawal of a paper.""" submitter, client = user_and_client_from_session(session) logger.debug(f'method: {method}, submission: {submission_id}. {params}') # Will raise NotFound if there is no such submission. submission, _ = load_submission(submission_id) # The submission must be announced for this to be a withdrawal request. if not submission.is_announced: alerts.flash_failure( Markup( "Submission must first be announced. See " "<a href='https://arxiv.org/help/withdraw'>the arXiv help pages" "</a> for details.")) loc = url_for('ui.create_submission') return {}, status.SEE_OTHER, {'Location': loc} # The form should be prepopulated based on the current state of the # submission. if method == 'GET': params = MultiDict({}) params.setdefault("confirmed", False) form = WithdrawalForm(params) response_data = { 'submission_id': submission_id, 'submission': submission, 'form': form, } if method == 'POST': # We require the user to confirm that they wish to proceed. if not form.validate(): raise BadRequest(response_data) cmd = RequestWithdrawal(reason=form.withdrawal_reason.data, creator=submitter, client=client) if not validate_command(form, cmd, submission, 'withdrawal_reason'): raise BadRequest(response_data) if not form.confirmed.data: response_data['require_confirmation'] = True return response_data, status.OK, {} response_data['require_confirmation'] = True try: # Save the events created during form validation. submission, _ = save(cmd, submission_id=submission_id) except SaveError as e: raise InternalServerError(response_data) from e # Success! Send user back to the submission page. alerts.flash_success("Withdrawal request submitted.") status_url = url_for('ui.create_submission') return {}, status.SEE_OTHER, {'Location': status_url} logger.debug('Nothing to do, return 200') return response_data, status.OK, {}
def test_date_range_must_be_specified(self): """If the user selects date range, they must indicate start or end.""" data = MultiDict({ 'terms-0-operator': 'AND', 'terms-0-field': 'title', 'terms-0-term': 'foo', 'date-filter_by': 'date_range', }) form = AdvancedSearchForm(data) self.assertFalse(form.validate()) self.assertEqual(len(form.errors), 1) data = MultiDict({ 'terms-0-operator': 'AND', 'terms-0-field': 'title', 'terms-0-term': 'foo', 'date-filter_by': 'date_range', 'date-from_date': '2012-02-05' }) form = AdvancedSearchForm(data) self.assertTrue(form.validate()) data = MultiDict({ 'terms-0-operator': 'AND', 'terms-0-field': 'title', 'terms-0-term': 'foo', 'date-filter_by': 'date_range', 'date-to_date': '2012-02-05' }) form = AdvancedSearchForm(data) self.assertTrue(form.validate())
def send_email(datafile): env = Environment(loader=PackageLoader('sendemail', 'templates')) template = env.get_template('email.html') with open(datafile, 'r') as f: wholefile = f.read() wholefile = json.loads(wholefile) files = MultiDict() # this 'i' business is jank to work around a Multidict bug in Requests: # https://github.com/kennethreitz/requests/issues/1155 i = 1 context = list() for graph in wholefile: points = list() if graph['type'] == 'table': for row in graph['data']: points.append((row[0], row[1])) currentgraph = { 'type': 'table', 'title': graph['name'].title(), 'additional': graph['additional'].title(), 'col1': graph['columns'][0], 'col2': graph['columns'][1], 'points': points, } elif graph['type'] == 'timeseries' or (graph['type'] == 'bar' and graph['data']): imagename = graph['uniquename'] + '.png' files.add('inline[%s]' % str(i), open(os.path.join(IMAGEDIR, imagename))) i += 1 currentgraph = { 'type': 'imagegraph', 'title': graph['name'].title(), 'additional': graph.get('additional', '').title(), 'cid': imagename, 'alt': '%s graph' % graph['name'], } context.append(currentgraph) return requests.post( POST_URL, auth=('api', MAILGUN_KEY), files=files, data={ "from": MAILGUN_FROM, "to": MAILGUN_TO, "subject": "Daily Status Report", "text": "Daily snapshot of the Refugees United dashboard.", "html": template.render(context=context), })
def test_urlencoded_parser(): parser = urlencoded_parser() stream = io.BytesIO(b'foo=1&bar=2') assert parser(stream) == MultiDict({"foo": "1", "bar": "2"}) parser = urlencoded_parser() stream = io.BytesIO(b'foo=1&foo=2') assert parser(stream) == MultiDict([("foo", "1"), ("foo", "2")])
def test_request_missing_parameter(self): """Request for a new compilation with missing parameter.""" with self.assertRaises(BadRequest): controllers.compile(MultiDict({'checksum': 'as12345'}), 'footoken', mock.MagicMock()) with self.assertRaises(BadRequest): controllers.compile(MultiDict({'source_id': '1234'}), 'footoken', mock.MagicMock())
def instrument_processor(form, field, submit=False, fields=None): form.embargo_date.flags.hidden = True form.embargo_date.flags.disabled = True form.license.flags.hidden = True form.license.flags.disabled = True form.access_conditions.flags.hidden = True form.access_conditions.flags.disabled = True form.access_groups.flags.hidden = True form.access_groups.flags.disabled = True form.access_right.flags.hidden = True form.access_right.flags.disabled = True if field.data != '-1': selected = getInstrument(field.data) instrument = json.loads(selected) accessRight = str(instrument['accessRight']) license = str(instrument['license']) embargoDate = str(instrument['embargoDate']) conditions = str(instrument['conditions']) groups = getUsergroupByIdInstrument(field.data) groups_json = json.loads(groups) d = MultiDict() for group in groups_json: info = { u'identifier': unicode(str(group['idGroup'])), u'title': group['name'], } d.add(unicode('access_groups'), info) #current_app.logger.debug(d) form.access_groups.process(d) #MultiDict([(unicode('access_groups'),info)]) form.license.data = license form.access_conditions.data = conditions if embargoDate is not None and str(embargoDate) != 'None': form.embargo_date.data = datetime.fromtimestamp( float(embargoDate) / 1000.0).strftime('%Y-%m-%d') if accessRight == 'embargoed': form.embargo_date.flags.hidden = False form.embargo_date.flags.disabled = False if accessRight == 'restricted': form.access_conditions.flags.hidden = False form.access_conditions.flags.disabled = False form.access_groups.flags.hidden = False form.access_groups.flags.disabled = False if accessRight in ['open', 'embargoed']: form.license.flags.hidden = False form.license.flags.disabled = False form.access_right.data = unicode(accessRight) else: form.access_right.data = 'open' form.access_conditions.data = '' form.license.flags.hidden = False form.license.flags.disabled = False form.access_right.flags.hidden = False form.access_right.flags.disabled = False
def test_source(self): req = Mock(['args', 'headers', 'values']) req.args = {'foo': 'bar'} req.headers = {'baz': 'bat'} arg = Argument('foo', location=['args']) self.assertEquals(arg.source(req), MultiDict(req.args)) arg = Argument('foo', location=['headers']) self.assertEquals(arg.source(req), MultiDict(req.headers))
def as_multidict(data=None): if data is None: return None resp = MultiDict() for key, val in data.items(): if not isinstance(val, list): val = [val] resp.setlist(key, val) return resp
def handle(controller: Callable, template: str, title: str, submission_id: Optional[int] = None, get_params: bool = False, **kwargs) -> Response: """ Generalized request handling pattern. Parameters ---------- controller : callable A controller function with the signature ``(method: str, params: MultiDict, session: Session, submission_id: int, token: str) -> Tuple[dict, int, dict]`` template : str HTML template to use in the response. title : str Page title, if not provided by controller. submission_id : int or None get_params : bool If True, GET parameters will be passed to the controller on GET requests. Default is False. kwargs : kwargs Passed as ``**kwargs`` to the controller. Returns ------- :class:`.Response` """ logger.debug('Handle call to controller %s with template %s, title %s,' ' and ID %s', controller, template, title, submission_id) if request.method == 'GET' and get_params: request_data = MultiDict(request.args.items(multi=True)) else: request_data = MultiDict(request.form.items(multi=True)) context = {'pagetitle': title} try: data, code, headers = controller(request.method, request_data, request.session, submission_id, **kwargs) except (BadRequest, InternalServerError) as e: logger.debug('Caught %s from controller', e) context.update(e.description) context.update({'error': e}) message = Markup(f'Something unexpected went wrong. {SUPPORT}') add_immediate_alert(context, alerts.FAILURE, message) return make_response(render_template(template, **context), e.code) except Unavailable as e: raise InternalServerError('Could not connect to database') from e context.update(data) if code < 300: return make_response(render_template(template, **context), code) if 'Location' in headers: return redirect(headers['Location'], code=code) return Response(response=context, status=code, headers=headers)
def test_collections_post_edit_mirror_integration(self): # The collection exists. collection = self._collection( name="Collection 1", protocol=ExternalIntegration.RB_DIGITAL ) # There is a storage integration not associated with the collection. storage = self._external_integration( protocol=ExternalIntegration.S3, goal=ExternalIntegration.STORAGE_GOAL ) # It's possible to associate the storage integration with the # collection for either a books or covers mirror. base_request = self._base_collections_post_request(collection) with self.request_context_with_admin("/", method="POST"): request = MultiDict( base_request + [("books_mirror_integration_id", storage.id)] ) flask.request.form = request response = self.manager.admin_collection_settings_controller.process_collections() eq_(response.status_code, 200) # There is an external integration link to associate the collection's # external integration with the storage integration for a books mirror. external_integration_link = get_one( self._db, ExternalIntegrationLink, external_integration_id=collection.external_integration.id ) eq_(storage.id, external_integration_link.other_integration_id) # It's possible to unset the mirror integration. controller = self.manager.admin_collection_settings_controller with self.request_context_with_admin("/", method="POST"): request = MultiDict( base_request + [("books_mirror_integration_id", str(controller.NO_MIRROR_INTEGRATION))] ) flask.request.form = request response = controller.process_collections() eq_(response.status_code, 200) external_integration_link = get_one( self._db, ExternalIntegrationLink, external_integration_id=collection.external_integration.id ) eq_(None, external_integration_link) # Providing a nonexistent integration ID gives an error. with self.request_context_with_admin("/", method="POST"): request = MultiDict( base_request + [("books_mirror_integration_id", -200)] ) flask.request.form = request response = self.manager.admin_collection_settings_controller.process_collections() eq_(response, MISSING_SERVICE)
def send_email(datafile): env = Environment(loader=PackageLoader('sendemail', 'templates')) template = env.get_template('email.html') with open(datafile, 'r') as f: wholefile = f.read() wholefile = json.loads(wholefile) files = MultiDict() # this 'i' business is jank to work around a Multidict bug in Requests: # https://github.com/kennethreitz/requests/issues/1155 i = 1 context = list() for graph in wholefile: points = list() if graph['type'] == 'table': for row in graph['data']: points.append((row[0], row[1])) currentgraph = { 'type' : 'table', 'title' : graph['name'].title(), 'additional' : graph['additional'].title(), 'col1' : graph['columns'][0], 'col2' : graph['columns'][1], 'points' : points, } elif graph['type'] == 'timeseries' or (graph['type'] == 'bar' and graph['data']): imagename = graph['uniquename'] + '.png' files.add('inline[%s]' % str(i), open(os.path.join(IMAGEDIR, imagename))) i += 1 currentgraph = { 'type' : 'imagegraph', 'title' : graph['name'].title(), 'additional' : graph.get('additional', '').title(), 'cid' : imagename, 'alt' : '%s graph' % graph['name'], } context.append(currentgraph) return requests.post( POST_URL, auth=('api', MAILGUN_KEY), files=files, data={"from": MAILGUN_FROM, "to": MAILGUN_TO, "subject": SUBJECT, "text": "Analytics by email.", "html": template.render(context=context), })
def process(self, formdata, data=_unset_value): """ Preprocess formdata in case we are passed a JSON data structure. """ if formdata and self.name in formdata: formdata = formdata[self.name] formdata = MultiDict( dict([("%s%s%s" % (self.name, self.separator, k), v) for k, v in formdata.items()])) super(FormField, self).process(formdata, data=data)
def json2multidict(jsonstr): jsondata = json.loads(jsonstr) m = MultiDict() for k,v in jsondata.items(): if v is not None: if isinstance(v, unicode): v = v.encode('utf-8') if isinstance(v, (str, int, float,)): m[k] = v else: m.setlist(k,v) return m
def process(self, formdata, data=unset_value): """Preprocess formdata in case we are passed a JSON data structure.""" if formdata and self.name in formdata: if not isinstance(formdata[self.name], dict): raise ValueError("Got unexpected value type") formdata = formdata[self.name] formdata = MultiDict( dict([("%s%s%s" % (self.name, self.separator, k), v) for k, v in formdata.items()])) super(FormField, self).process(formdata, data=data)
def instrument_processor(form, field, submit=False, fields=None): form.embargo_date.flags.hidden = True form.embargo_date.flags.disabled = True form.license.flags.hidden = True form.license.flags.disabled = True form.access_conditions.flags.hidden = True form.access_conditions.flags.disabled = True form.access_groups.flags.hidden = True form.access_groups.flags.disabled = True form.access_right.flags.hidden = True form.access_right.flags.disabled = True if field.data != "-1": selected = getInstrument(field.data) instrument = json.loads(selected) accessRight = str(instrument["accessRight"]) license = str(instrument["license"]) embargoDate = str(instrument["embargoDate"]) conditions = str(instrument["conditions"]) groups = getUsergroupByIdInstrument(field.data) groups_json = json.loads(groups) d = MultiDict() for group in groups_json: info = {u"identifier": unicode(str(group["idGroup"])), u"title": group["name"]} d.add(unicode("access_groups"), info) # current_app.logger.debug(d) form.access_groups.process(d) # MultiDict([(unicode('access_groups'),info)]) form.license.data = license form.access_conditions.data = conditions if embargoDate is not None and str(embargoDate) != "None": form.embargo_date.data = datetime.fromtimestamp(float(embargoDate) / 1000.0).strftime("%Y-%m-%d") if accessRight == "embargoed": form.embargo_date.flags.hidden = False form.embargo_date.flags.disabled = False if accessRight == "restricted": form.access_conditions.flags.hidden = False form.access_conditions.flags.disabled = False form.access_groups.flags.hidden = False form.access_groups.flags.disabled = False if accessRight in ["open", "embargoed"]: form.license.flags.hidden = False form.license.flags.disabled = False form.access_right.data = unicode(accessRight) else: form.access_right.data = "open" form.access_conditions.data = "" form.license.flags.hidden = False form.license.flags.disabled = False form.access_right.flags.hidden = False form.access_right.flags.disabled = False
def test_post_upload(self, mock_load, mock_save, mock_filemanager): """POST request for submission with an existing upload package.""" submission_id = 2 mock_submission = mock.MagicMock( submission_id=submission_id, source_content=SubmissionContent( identifier='5433', checksum='a1s2d3f4', uncompressed_size=593920, compressed_size=1000, source_format=SubmissionContent.Format.TEX), is_finalized=False, is_announced=False, arxiv_id=None, version=1) mock_load.return_value = (mock_submission, []) mock_save.return_value = (mock_submission, []) mock_fm = mock.MagicMock() mock_fm.add_file.return_value = Upload( identifier=25, checksum='a1s2d3f4', size=593920, started=datetime.now(), completed=datetime.now(), created=datetime.now(), modified=datetime.now(), status=Upload.Status.READY, lifecycle=Upload.LifecycleStates.ACTIVE, locked=False, files=[ FileStatus(path='', name='thebestfile.pdf', file_type='PDF', modified=datetime.now(), size=20505, ancillary=False, errors=[]) ], errors=[]) mock_filemanager.current_session.return_value = mock_fm params = MultiDict({}) mock_file = mock.MagicMock() files = MultiDict({'file': mock_file}) _, code, _ = upload.upload_files('POST', params, self.session, submission_id, files=files, token='footoken') self.assertEqual(code, status.SEE_OTHER, 'Returns 303') self.assertEqual(mock_fm.add_file.call_count, 1, 'Calls the file management service') self.assertTrue(mock_filemanager.add_file.called_with(mock_file))
def process(self, formdata, data=unset_value): """Preprocess formdata in case we are passed a JSON data structure.""" if formdata and self.name in formdata: if not isinstance(formdata[self.name], dict): raise ValueError("Got unexpected value type") formdata = formdata[self.name] formdata = MultiDict(dict([ ("%s%s%s" % (self.name, self.separator, k), v) for k, v in formdata.items() ])) super(FormField, self).process(formdata, data=data)
def test_get_upload(self, mock_load, mock_filemanager): """GET request for submission with an existing upload package.""" submission_id = 2 mock_load.return_value = (mock.MagicMock( submission_id=submission_id, source_content=SubmissionContent( identifier='5433', checksum='a1s2d3f4', uncompressed_size=593920, compressed_size=1000, source_format=SubmissionContent.Format.TEX), is_finalized=False, is_announced=False, arxiv_id=None, version=1), []) mock_filemanager.get_upload_status.return_value = (Upload( identifier=25, checksum='a1s2d3f4', size=593920, started=datetime.now(), completed=datetime.now(), created=datetime.now(), modified=datetime.now(), status=Upload.Status.READY, lifecycle=Upload.LifecycleStates.ACTIVE, locked=False, files=[ FileStatus(path='', name='thebestfile.pdf', file_type='PDF', modified=datetime.now(), size=20505, ancillary=False, errors=[]) ], errors=[])) params = MultiDict({}) files = MultiDict({}) data, code, _ = upload.upload_files('GET', params, self.session, submission_id, files=files, token='footoken') self.assertEqual(code, status.OK, 'Returns 200 OK') self.assertEqual(mock_filemanager.get_upload_status.call_count, 1, 'Calls the file management service') self.assertIn('status', data, 'Upload status is in response') self.assertIn('submission', data, 'Submission is in response') self.assertIn('submission_id', data, 'ID is in response')
def test_analytics_services_post_create(self): library, ignore = create( self._db, Library, name="Library", short_name="L", ) with self.request_context_with_admin("/", method="POST"): flask.request.form = MultiDict([ ("name", "Google analytics name"), ("protocol", GoogleAnalyticsProvider.__module__), (ExternalIntegration.URL, "http://test"), ("libraries", json.dumps([{ "short_name": "L", "tracking_id": "trackingid" }])), ]) response = self.manager.admin_analytics_services_controller.process_analytics_services( ) eq_(response.status_code, 201) service = get_one(self._db, ExternalIntegration, goal=ExternalIntegration.ANALYTICS_GOAL) eq_(service.id, int(response.response[0])) eq_(GoogleAnalyticsProvider.__module__, service.protocol) eq_("http://test", service.url) eq_([library], service.libraries) eq_( "trackingid", ConfigurationSetting.for_library_and_externalintegration( self._db, GoogleAnalyticsProvider.TRACKING_ID, library, service).value) # Creating a local analytics service doesn't require a URL. with self.request_context_with_admin("/", method="POST"): flask.request.form = MultiDict([ ("name", "local analytics name"), ("protocol", LocalAnalyticsProvider.__module__), ("libraries", json.dumps([{ "short_name": "L", "tracking_id": "trackingid" }])), ]) response = self.manager.admin_analytics_services_controller.process_analytics_services( ) eq_(response.status_code, 201)
def classification(method: str, params: MultiDict, session: Session, submission_id: int, **kwargs) -> Response: """Handle primary classification requests.""" submitter, client = user_and_client_from_session(session) submission, submission_events = load_submission(submission_id) if method == 'GET': # Prepopulate the form based on the state of the submission. if submission.primary_classification \ and submission.primary_classification.category: params['category'] = submission.primary_classification.category # Use the user's default category as the default for the form. params.setdefault('category', session.user.profile.default_category) params['operation'] = PrimaryClassificationForm.ADD form = PrimaryClassificationForm(params) form.filter_choices(submission, session) response_data = { 'submission_id': submission_id, 'submission': submission, 'submitter': submitter, 'client': client, 'form': form } if method == 'POST': if not form.validate(): raise BadRequest(response_data) command = SetPrimaryClassification(category=form.category.data, creator=submitter, client=client) if not validate_command(form, command, submission, 'category'): raise BadRequest(response_data) try: submission, _ = save(command, submission_id=submission_id) response_data['submission'] = submission except SaveError as e: logger.error('Could not save command: %s', e) raise InternalServerError(response_data) from e if params.get('action') in ['previous', 'save_exit', 'next']: return response_data, status.SEE_OTHER, {} return response_data, status.OK, {}
def test_search_links_with_fields_filtering(inspire_app): expected_links_test = { "self": "http://localhost:5000/api/test/?q=&size=10&page=1&fields=ids,authors", "next": "http://localhost:5000/api/test/?q=&size=10&page=2&fields=ids,authors", "format1": "http://localhost:5000/api/test/?q=&size=10&page=1&format=format1", "json": "http://localhost:5000/api/test/?q=&size=10&page=1&fields=ids,authors&format=json", } config = { "TEST": { "search_serializers_aliases": { "format1": "format/1", "json": "application/json", } } } with override_config(**config): links_test = { "self": "http://localhost:5000/api/test/?q=&size=10&page=1", "next": "http://localhost:5000/api/test/?q=&size=10&page=2", } with mock.patch("inspirehep.records.links.request") as mock_request: mock_request.path = "/test" mock_request.values = MultiDict([("fields", "ids,authors")]) links_test = inspire_search_links(links_test) assert links_test == expected_links_test
def test_generate_inspire_search_links_gets_proper_formats(inspire_app): expected_links_test2 = { "self": "http://localhost:5000/api/test2/?q=&size=10&page=1", "format4": "http://localhost:5000/api/test2/?q=&size=10&page=1&format=format4", "format5": "http://localhost:5000/api/test2/?q=&size=10&page=1&format=format5", } expected_links_test = { "self": "http://localhost:5000/api/test/?q=&size=10&page=1", "format1": "http://localhost:5000/api/test/?q=&size=10&page=1&format=format1", "format2": "http://localhost:5000/api/test/?q=&size=10&page=1&format=format2", "format3": "http://localhost:5000/api/test/?q=&size=10&page=1&format=format3", } config = { "TEST": { "search_serializers_aliases": { "format1": "format/1", "format2": "format/2", "format3": "format/3", } }, "TEST2": { "search_serializers_aliases": {"format4": "format/4", "format5": "format/5"} }, } with override_config(**config): links_test = {"self": "http://localhost:5000/api/test/?q=&size=10&page=1"} links_test2 = {"self": "http://localhost:5000/api/test2/?q=&size=10&page=1"} with mock.patch("inspirehep.records.links.request") as mock_request: mock_request.values = MultiDict() mock_request.path = "/test" links_test = inspire_search_links(links_test) mock_request.path = "/test2" links_test2 = inspire_search_links(links_test2) assert links_test == expected_links_test assert links_test2 == expected_links_test2
def test_search_services_post_create(self): with self.request_context_with_admin("/", method="POST"): flask.request.form = MultiDict([ ("name", "Name"), ("protocol", ExternalIntegration.ELASTICSEARCH), (ExternalIntegration.URL, "http://search_url"), (ExternalSearchIndex.WORKS_INDEX_PREFIX_KEY, "works-index-prefix"), (ExternalSearchIndex.TEST_SEARCH_TERM_KEY, "sample-search-term") ]) response = self.manager.admin_search_services_controller.process_services( ) eq_(response.status_code, 201) service = get_one(self._db, ExternalIntegration, goal=ExternalIntegration.SEARCH_GOAL) eq_(service.id, int(response.response[0])) eq_(ExternalIntegration.ELASTICSEARCH, service.protocol) eq_("http://search_url", service.url) eq_("works-index-prefix", service.setting(ExternalSearchIndex.WORKS_INDEX_PREFIX_KEY).value) eq_("sample-search-term", service.setting(ExternalSearchIndex.TEST_SEARCH_TERM_KEY).value)
def test_cannot_set_non_storage_integration_as_mirror_integration(self): # The collection exists. collection = self._collection( name="Collection 1", protocol=ExternalIntegration.RB_DIGITAL ) # There is a storage integration not associated with the collection, # which makes it possible to associate storage integrations # with collections through the collections controller. storage = self._external_integration( protocol=ExternalIntegration.S3, goal=ExternalIntegration.STORAGE_GOAL ) # Trying to set a non-storage integration (such as the # integration associated with the collection's licenses) as # the collection's mirror integration gives an error. base_request = self._base_collections_post_request(collection) with self.request_context_with_admin("/", method="POST"): request = MultiDict( base_request + [ ("books_mirror_integration_id", collection.external_integration.id) ] ) flask.request.form = request response = self.manager.admin_collection_settings_controller.process_collections() eq_(response, INTEGRATION_GOAL_CONFLICT)
def test_validate_image(self): def create_image_file(format_string): image_data = '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x01\x03\x00\x00\x00%\xdbV\xca\x00\x00\x00\x06PLTE\xffM\x00\x01\x01\x01\x8e\x1e\xe5\x1b\x00\x00\x00\x01tRNS\xcc\xd24V\xfd\x00\x00\x00\nIDATx\x9cc`\x00\x00\x00\x02\x00\x01H\xaf\xa4q\x00\x00\x00\x00IEND\xaeB`\x82' class TestImageFile(StringIO): headers = {"Content-Type": "image/" + format_string} return TestImageFile(image_data) return result [png, jpeg, gif, invalid] = [ MultiDict([(Configuration.LOGO, create_image_file(x))]) for x in ["png", "jpeg", "gif", "abc"] ] png_response = Validator().validate_image( Configuration.LIBRARY_SETTINGS, {"files": png}) eq_(png_response, None) jpeg_response = Validator().validate_image( Configuration.LIBRARY_SETTINGS, {"files": jpeg}) eq_(jpeg_response, None) gif_response = Validator().validate_image( Configuration.LIBRARY_SETTINGS, {"files": gif}) eq_(gif_response, None) abc_response = Validator().validate_image( Configuration.LIBRARY_SETTINGS, {"files": invalid}) eq_( abc_response.detail, 'Upload for Logo image must be in GIF, PNG, or JPG format. (Upload was image/abc.)' ) eq_(abc_response.status_code, 400)
def validate(self, values): """ Validate the given dict of values against the validators and post validators of this schema. This dict should be a dict with list values or an instance of a werkzeug `MultiDict`. Any parameter that is not explicitely validated will be returned as extra values. If a parameter is found it is passed to the validator's :meth:`~framework.validators.schema.Validator.validate` method that will either return a valid output or trigger a validation error. After individual validators are processed, the resulting valid parameters are passed to each `post_validators`. Each post validator can change the resulting values or trigger a validation error. When a validation error is triggered, an entry is added to the error dict mapping the field name that produced the error to an instance of :exc:`~framework.validators.errors.Invalid` (containing the error message and error value). After those steps, the validated values, the validation errors and the extra values dicts are returned. :param values: The dict of values to validate against this schema :type values: dict :return: The dict of validated values, The dict of error messages, The dict of extra values :rtype: a tuple (dict, dict) """ # Ensure we have a **new** dict with lists as values if it's a werkzeug MultiDict # we are going to pop values from it... values = MultiDict(values) new_values = {} error_values = {} for name, validator in self.validators.iteritems(): # Determine the key to fetch from the received values field = validator.field or name # Get the list of values, which may be empty if the field was not present or contain some values if validator.startswith: value = [(x, values[x]) for x in values.iterkeys() if x.startswith(validator.startswith)] else: value = values.poplist(field) try: value = validator.validate(value) if value is not NO_VALUE: new_values[name] = value except Invalid, e: error_values[e.field or field] = e
def process_calling_args(self): # start with GET arguments that are expected args = MultiDict() if self.expected_get_args: for k in six.iterkeys(rg.request.args): if k in self.expected_get_args: args.setlist(k, rg.request.args.getlist(k)) # add URL arguments, replacing GET arguments if they are there. URL # arguments get precedence and we don't want to just .update() # because that would allow arbitrary get arguments to affect the # values of the URL arguments for k, v in six.iteritems(self.urlargs): args[k] = v # trim down to a real dictionary. self.calling_args = werkzeug_multi_dict_conv(args) log.debug('calling args: %s' % self.calling_args)
def _prep_input(self, method, data, content_type): """Return encoded and packed POST data.""" if data is None or method != 'POST': prepped = { 'input_stream': None, 'content_length': None, 'content_type': None, } if method == 'GET' and data: qs = MultiDict() for key, value in to_pairs(data): qs.setlistdefault(key).append(value) prepped['query_string'] = url_encode(qs) return prepped else: payload = url_encode(MultiDict(to_pairs(data))) content_type = 'application/x-www-form-urlencoded' return { 'input_stream': StringIO(payload), 'content_length': len(payload), 'content_type': content_type }
def current_url(root_only=False, host_only=False, strip_querystring=False, strip_host=False, https=None, environ=None, qs_replace=None, qs_update=None): """ Returns strings based on the current URL. Assume a request with path: /news/list?param=foo to an application mounted at: http://localhost:8080/script Then: :param root_only: set `True` if you only want the root URL. http://localhost:8080/script/ :param host_only: set `True` if you only want the scheme, host, & port. http://localhost:8080/ :param strip_querystring: set to `True` if you don't want the querystring. http://localhost:8080/script/news/list :param strip_host: set to `True` you want to remove the scheme, host, & port: /script/news/list?param=foo :param https: None = use schem of current environ; True = force https scheme; False = force http scheme. Has no effect if strip_host = True. :param qs_update: a dict of key/value pairs that will be used to replace or add values to the current query string arguments. :param qs_replace: a dict of key/value pairs that will be used to replace values of the current query string. Unlike qs_update, if a key is not present in the currenty query string, it will not be added to the returned url. :param environ: the WSGI environment to get the current URL from. If not given, the environement from the current request will be used. This is mostly for use in our unit tests and probably wouldn't have much application in normal use. """ retval = '' if environ: ro = BaseRequest(environ, shallow=True) else: ro = rg.request if qs_replace or qs_update: strip_querystring = True if root_only: retval = ro.url_root elif host_only: retval = ro.host_url else: if strip_querystring: retval = ro.base_url else: retval = ro.url if strip_host: retval = retval.replace(ro.host_url.rstrip('/'), '', 1) if not strip_host and https is not None: if https and retval.startswith('http://'): retval = retval.replace('http://', 'https://', 1) elif not https and retval.startswith('https://'): retval = retval.replace('https://', 'http://', 1) if qs_update or qs_replace: href = Href(retval, sort=True) args = MultiDict(ro.args) if qs_update: # convert to md first so that if we have lists in the kwargs, they # are converted appropriately qs_update = MultiDict(qs_update) for key, value_list in qs_update.lists(): # multidicts extend, not replace, so we need # to get rid of the key first try: del args[key] except KeyError: pass args.setlistdefault(key, []).extend(value_list) if qs_replace: # convert to md first so that if we have lists in the kwargs, they # are converted appropriately qs_replace = MultiDict(qs_replace) for key, value_list in qs_replace.lists(): # multidicts extend, not replace, so we need # to get rid of the key first try: del args[key] args.setlistdefault(key, []).extend(value_list) except KeyError: pass return href(args) return retval
def _jinja2_url_for_other_page(page, remove=None, **kwargs): args = MultiDict() if request.view_args is not None and request.view_args != [] and request.view_args != {}: args.update(convert_type(request.view_args.copy())) if request.args is not None and request.args != [] and request.args != {}: args.update(convert_type(request.args.to_dict(flat=False))) # Process removes if remove is not None: if isinstance(remove, (basestring, int)): args.poplist(remove) elif isinstance(remove, list): for item in remove: if isinstance(item, (basestring, int)): args.poplist(item) elif isinstance(item, tuple): key, value = item arg_values = args.poplist(key) if arg_values is not None and arg_values != []: new_values = [i for i in arg_values if not equal_args(i, value)] args.setlist(key, new_values) else: raise ValueError elif isinstance(remove, dict): for key, value in remove.items(): if isinstance(value, (basestring, int)): arg_values = args.poplist(key) new_values = [i for i in arg_values if not equal_args(i, value)] args.setlist(key, new_values) elif isinstance(value, (list, tuple)): arg_values = args.poplist(key) if arg_values is not None and arg_values != []: new_values = [i for i in arg_values if not equal_args(i, value)] args.setlist(key, new_values) else: if current_app.debug: print("Could not parse value : {}".format(value)) raise ValueError else: raise ValueError if kwargs is not None: args.update(convert_type(kwargs.copy())) # Remove duplicates for key in args.keys(): items = args.poplist(key) items = [convert_type(item) for item in items] items = list(set(items)) args.setlist(key, items) return url_for(page, **args)
def jquery_json_to_multidict(jq_json): """ MultiDicts can be used to populate forms and orm objects """ mdict = MultiDict() mdict.update({i['name']:i['value'] for i in jq_json}) return mdict
def test_update_genres(self): # start with a couple genres [lp] = self.english_1.license_pools genre, ignore = Genre.lookup(self._db, "Occult Horror") lp.work.genres = [genre] # change genres with self.app.test_request_context("/"): requested_genres = ["Drama", "Urban Fantasy", "Women's Fiction"] form = MultiDict() for genre in requested_genres: form.add("genres", genre) flask.request.form = form response = self.manager.admin_work_controller.update_genres(lp.data_source.name, lp.identifier.identifier) new_genre_names = [work_genre.genre.name for work_genre in lp.work.work_genres] eq_(len(new_genre_names), len(requested_genres)) for genre in requested_genres: eq_(True, genre in new_genre_names) # remove a genre with self.app.test_request_context("/"): requested_genres = ["Drama", "Women's Fiction"] form = MultiDict() for genre in requested_genres: form.add("genres", genre) flask.request.form = form response = self.manager.admin_work_controller.update_genres(lp.data_source.name, lp.identifier.identifier) new_genre_names = [work_genre.genre.name for work_genre in lp.work.work_genres] eq_(len(new_genre_names), len(requested_genres)) for genre in requested_genres: eq_(True, genre in new_genre_names) previous_genres = requested_genres # try to add a nonfiction genre with self.app.test_request_context("/"): requested_genres = ["Drama", "Women's Fiction", "Cooking"] form = MultiDict() for genre in requested_genres: form.add("genres", genre) flask.request.form = form response = self.manager.admin_work_controller.update_genres(lp.data_source.name, lp.identifier.identifier) eq_(response, INCOMPATIBLE_GENRE) new_genre_names = [work_genre.genre.name for work_genre in lp.work.work_genres] eq_(len(new_genre_names), len(previous_genres)) for genre in previous_genres: eq_(True, genre in new_genre_names) # try to add a nonexistent genre with self.app.test_request_context("/"): requested_genres = ["Drama", "Women's Fiction", "Epic Military Memoirs"] form = MultiDict() for genre in requested_genres: form.add("genres", genre) flask.request.form = form response = self.manager.admin_work_controller.update_genres(lp.data_source.name, lp.identifier.identifier) eq_(response, GENRE_NOT_FOUND) new_genre_names = [work_genre.genre.name for work_genre in lp.work.work_genres] eq_(len(new_genre_names), len(previous_genres)) for genre in previous_genres: eq_(True, genre in new_genre_names)
def test_send_support_email(app, db, es, users): """Test mail sending.""" with app.extensions['mail'].record_messages() as outbox: with app.test_client() as client: res = client.get(url_for('zenodo_pages.support')) assert res.status_code == 200 res = client.get( url_for('zenodo_pages.support') ) assert b('recaptcha') in res.data assert res.status_code == 200 res = client.post( url_for('zenodo_pages.support'), data=dict() ) assert res.status_code == 200 assert b('field-name has-error') in res.data assert b('field-email has-error') in res.data assert b('field-subject has-error') in res.data assert b('field-description has-error') in res.data assert b('field-attachments has-error') not in res.data form = MultiDict(dict( name='Aman', email='*****@*****.**', subject='hello', issue_category='tech-support', description='Please help us! Troubleshoot our problem.' )) res = client.post( url_for('zenodo_pages.support'), data=form ) assert b('has-error') not in res.data assert len(outbox) == 2 sent_msg = outbox[0] assert sent_msg.sender == 'Aman <*****@*****.**>' assert sent_msg.subject == '[tech-support]: hello' assert sent_msg.reply_to == '*****@*****.**' assert 'Aman <*****@*****.**>' in sent_msg.body sent_msg = outbox[1] assert sent_msg.sender == 'Zenodo <*****@*****.**>' assert sent_msg.subject == 'Zenodo Support' assert sent_msg.body == ( 'Thank you for contacting Zenodo support.' '\n\nWe have received your message, and we will do our best ' 'to get back to you as soon as possible.\nThis is an ' 'automated confirmation of your request, please do not reply ' 'to this email.\n\nZenodo Support\n' 'https://zenodo.org\n' ) form = MultiDict(dict( name='Foo', email='*****@*****.**', subject='Bar', issue_category='tech-support', description='Please help us! Troubleshoot our problem.' )) test_file = BytesIO(b('My other file contents')) test_file2 = BytesIO(b('Another My other file contents')) form.add('attachments', (test_file, 'file2.txt')) form.add('attachments', (test_file2, 'test3.txt')) res = client.post( url_for('zenodo_pages.support'), data=form, content_type='multipart/form-data', follow_redirects=True ) assert len(outbox) == 4 sent_msg = outbox[2] file1 = sent_msg.attachments[0] assert file1.filename == 'file2.txt' assert file1.data == b('My other file contents') file2 = sent_msg.attachments[1] assert file2.filename == 'test3.txt' assert file2.data == b('Another My other file contents') login_user_via_session(client, email=users[1]['email']) res = client.get( url_for('zenodo_pages.support') ) assert b('*****@*****.**') in res.data assert b('recaptcha') not in res.data form = MultiDict(dict( name='Foo', subject='Bar', issue_category='tech-support', description='Please help us! Troubleshoot our problem.' )) res = client.post( url_for('zenodo_pages.support'), data=form ) assert len(outbox) == 6 sent_msg = outbox[4] assert 'From: Foo <*****@*****.**> (2)' in sent_msg.body test_file = BytesIO(b('My file contents')) form.add('attachments', (test_file, 'file1.txt')) res = client.post( url_for('zenodo_pages.support'), data=form, content_type='multipart/form-data', follow_redirects=True ) assert len(outbox) == 8 sent_msg = outbox[6] file1 = sent_msg.attachments[0] assert file1.filename == 'file1.txt' assert file1.data == b('My file contents') form = MultiDict(dict( name='Foo', subject='Bar', issue_category='tech-support', description='Please help us! Troubleshoot our problem.' )) test_file = BytesIO(b('My other file contents')) test_file2 = BytesIO(b('Another My other file contents')) form.add('attachments', (test_file, 'file2.txt')) form.add('attachments', (test_file2, 'test3.txt')) res = client.post( url_for('zenodo_pages.support'), data=form, content_type='multipart/form-data', follow_redirects=True ) assert len(outbox) == 10 sent_msg = outbox[8] file1 = sent_msg.attachments[0] assert file1.filename == 'file2.txt' assert file1.data == b('My other file contents') file2 = sent_msg.attachments[1] assert file2.filename == 'test3.txt' assert file2.data == b('Another My other file contents')