From 76bfc4cc704961c5914c3690250bf75ee2787384 Mon Sep 17 00:00:00 2001 From: Christophe de Vienne Date: Wed, 19 Dec 2012 15:11:52 +0100 Subject: [PATCH] Add a new parameter 'ignore_extra_args' to the @signature decorator (and its frontends @wsexpose) --- wsme/api.py | 8 +++++++- wsme/rest/args.py | 12 ++++++++---- wsme/rest/json.py | 8 ++++++-- wsme/rest/xml.py | 5 ++++- wsme/tests/test_restjson.py | 17 ++++++++++++++++- 5 files changed, 41 insertions(+), 9 deletions(-) diff --git a/wsme/api.py b/wsme/api.py index da44f0f..ee01c44 100644 --- a/wsme/api.py +++ b/wsme/api.py @@ -66,6 +66,11 @@ class FunctionDefinition(object): #: If the body carry the datas of a single argument, its type self.body_type = None + #: True if extra arguments should be ignored, NOT inserted in + #: the kwargs of the function and not raise UnknownArgument + #: exceptions + self.ignore_extra_args = False + #: Dictionnary of protocol-specific options. self.extra_options = None @@ -94,8 +99,9 @@ class FunctionDefinition(object): for arg in self.arguments: arg.resolve_type(registry) - def set_options(self, body=None, **extra_options): + def set_options(self, body=None, ignore_extra_args=False, **extra_options): self.body_type = body + self.ignore_extra_args = ignore_extra_args self.extra_options = extra_options def set_arg_types(self, argspec, arg_types): diff --git a/wsme/rest/args.py b/wsme/rest/args.py index 8d4f79c..18fb70a 100644 --- a/wsme/rest/args.py +++ b/wsme/rest/args.py @@ -172,7 +172,7 @@ def args_from_params(funcdef, params): kw[argdef.name] = value paths = set(params.keys()) unknown_paths = paths - hit_paths - if unknown_paths: + if not funcdef.ignore_extra_args and unknown_paths: raise UnknownArgument(', '.join(unknown_paths)) return [], kw @@ -195,9 +195,13 @@ def args_from_body(funcdef, body, mimetype): else: raise ValueError("Unknow mimetype: %s" % mimetype) - kw = dataformat.parse( - body, datatypes, bodyarg=funcdef.body_type is not None - ) + try: + kw = dataformat.parse( + body, datatypes, bodyarg=funcdef.body_type is not None + ) + except UnknownArgument: + if not funcdef.ignore_extra_args: + raise return (), kw diff --git a/wsme/rest/json.py b/wsme/rest/json.py index 5aa0ed5..721e673 100644 --- a/wsme/rest/json.py +++ b/wsme/rest/json.py @@ -202,10 +202,14 @@ def parse(s, datatypes, bodyarg): kw = {argname: fromjson(datatypes[argname], jdata)} else: kw = {} + extra_args = [] for key in jdata: if key not in datatypes: - raise UnknownArgument(key) - kw[key] = fromjson(datatypes[key], jdata[key]) + extra_args.append(key) + else: + kw[key] = fromjson(datatypes[key], jdata[key]) + if extra_args: + raise UnknownArgument(', '.join(extra_args)) return kw diff --git a/wsme/rest/xml.py b/wsme/rest/xml.py index 7e05278..57b1e5f 100644 --- a/wsme/rest/xml.py +++ b/wsme/rest/xml.py @@ -232,10 +232,13 @@ def parse(s, datatypes, bodyarg): return fromxml(datatypes[name], tree) else: kw = {} + extra_args = [] for sub in tree: if sub.tag not in datatypes: - raise UnknownArgument(sub.tag) + extra_args.append(sub.tag) kw[sub.tag] = fromxml(datatypes[sub.tag], sub) + if extra_args: + raise UnknownArgument(', '.join(extra_args)) return kw diff --git a/wsme/tests/test_restjson.py b/wsme/tests/test_restjson.py index 9e62749..ac32bf2 100644 --- a/wsme/tests/test_restjson.py +++ b/wsme/tests/test_restjson.py @@ -108,7 +108,7 @@ class MiniCrud(object): print(repr(data)) return CRUDResult(data, u('create')) - @expose(CRUDResult, method='GET') + @expose(CRUDResult, method='GET', ignore_extra_args=True) @validate(Obj) def read(self, ref): print(repr(ref)) @@ -382,3 +382,18 @@ class TestRestJson(wsme.tests.protocol.ProtocolTestCase): assert result['data']['id'] == 1 assert result['data']['name'] == u("test") assert result['message'] == "delete" + + def test_extra_arguments(self): + headers = { + 'Content-Type': 'application/json', + } + res = self.app.get( + '/crud?ref.id=1&extraarg=foo', + headers=headers, + expect_errors=False) + print("Received:", res.body) + result = json.loads(res.text) + print(result) + assert result['data']['id'] == 1 + assert result['data']['name'] == u("test") + assert result['message'] == "read"