class TestCall(unittest.TestCase): TRAFARET = T.Dict({ T.Key("call_dict", optional=True): # The following is the ordered dict because we want to obey order # in the error messages. Otherwise, it could be normal dict as well T.Call(lambda _: T.DataError({ "anything": "bad idea", "bad": "another bad idea", })), T.Key("call_str", optional=True): T.Call(lambda _: T.DataError("some error")), }) def test_call_dict(self): self.assertEqual( get_err(self.TRAFARET, u""" call_dict: "hello" """), dedent(u"""\ config.yaml:2: call_dict.anything: bad idea config.yaml:2: call_dict.bad: another bad idea """)) def test_call_str(self): self.assertEqual( get_err(self.TRAFARET, u""" call_str: "hello" """), dedent(u"""\ config.yaml:2: call_str: some error -> 'hello' """))
def test_call(self): def validator(value): if value != "foo": return t.DataError("I want only foo!") return 'foo' trafaret = t.Call(validator) res = trafaret.check("foo") self.assertEqual(res, 'foo') err = extract_error(trafaret, "bar") self.assertEqual(err, 'I want only foo!')
def deep_schema(key): def inner(data, context=None): register = context register.push(key) try: schema = json_schema(data, context=register) register.save_schema(schema) return schema finally: register.pop() return t.Call(inner)
def construct(arg): ''' Shortcut syntax to define trafarets. - int, str, float and bool will return t.Int, t.String, t.Float and t.Bool - one element list will return t.List - tuple or list with several args will return t.Tuple - dict will return t.Dict. If key has '?' at the and it will be optional and '?' will be removed - any callable will be t.Call - otherwise it will be returned as is construct is recursive and will try construct all lists, tuples and dicts args ''' if isinstance(arg, t.Trafaret): return arg elif isinstance(arg, tuple) or (isinstance(arg, list) and len(arg) > 1): return t.Tuple(*(construct(a) for a in arg)) elif isinstance(arg, list): # if len(arg) == 1 return t.List(construct(arg[0])) elif isinstance(arg, dict): return t.Dict({ construct_key(key): construct(value) for key, value in arg.items() }) elif isinstance(arg, str): return t.Atom(arg) elif isinstance(arg, type): if arg is int: return t.Int() elif arg is float: return t.Float() elif arg is str: return t.String() elif arg is bool: return t.Bool() else: return t.Type(arg) elif callable(arg): return t.Call(arg) else: return arg
def test_callable(self): import functools to_int_10000 = functools.partial(int, '10000') trafaret = t.Regexp('2|10|16') & t.ToInt & t.Call(to_int_10000) assert trafaret('10') == 10000
def test_should_be_callable(self): with pytest.raises(RuntimeError): t.Call(5)
def test_repr(self): assert repr(t.Call(self.validator)) == '<Call(validator)>'
def test_call(self): trafaret = t.Call(self.validator) res = trafaret.check("foo") assert res == 'foo' err = extract_error(trafaret, "bar") assert err == 'I want only foo!'
def check_headers(headers): if not isinstance(headers, dict): return t.DataError('value is not a dict') headers = dict((k.lower(), v) for k, v in headers.items()) for item in ('fs-signature', 'fs-timestamp'): if item.lower() not in headers: return t.DataError('{} header is missing'.format(item)) return headers VerificationArguments = t.Dict({ 'secret': t.String, 'body': t.Call(check_body), 'headers': t.Call(check_headers) }) def verify_webhook_signature(secret=None, body=None, headers=None): """ Checks if webhook, which you received was sent Filestack, based on your secret for webhook endpoint which was generated in Filestack developer portal. Body suppose to be raw content of received webhook returns [Tuple] ```python from filestack import Client result, details = verify_webhook_signature(
schema_name = schema.get('$id') or uuid4().urn schema_register = register.reg_schema(schema_name) elif isinstance(context, SchemaRegister): schema_register = context else: ValueError('You need to provide Register instance to json_schema and nothing else') touched_names = set() errors = {} keywords_checks = [] format_transform = t.Any for key in all_keywords: for k, v, names in key(schema, context=schema_register): if isinstance(v, t.DataError): errors[k] = v else: if k == 'format': format_transform = v keywords_checks.append(v) touched_names = touched_names.union(names) schema_keys = set(schema.keys()) for key in schema_keys - touched_names: errors[key] = '%s is not allowed key' % key if errors: raise t.DataError(errors) schema_trafaret = All(keywords_checks) & format_transform return schema_trafaret json_schema << (t.Type(dict) & t.Call(validate_schema))