Skip to content

Commit

Permalink
Implement Const validator to keep data unchanged (#145)
Browse files Browse the repository at this point in the history
* Implement Const validator to keep data unchanged

* Make pep8 happy

* Fix travis-ci python environments
  • Loading branch information
insideable authored and skorokithakis committed Sep 28, 2017
1 parent ca8a287 commit 56262d7
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 5 deletions.
3 changes: 0 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,9 @@ cache:
install: pip install codecov tox

env:
- TOX_ENV=py26
- TOX_ENV=py27
- TOX_ENV=py33
- TOX_ENV=py34
- TOX_ENV=py35
- TOX_ENV=pypy
- TOX_ENV=coverage
- TOX_ENV=pep8

Expand Down
17 changes: 17 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,23 @@ Dropping the details, ``Use`` is basically:
except Exception as e:
raise SchemaError('%r raised %r' % (self._callable.__name__, e))
Sometimes you need to transform and validate part of data, but keep original data unchanged.
``Const`` helps to keep your data safe:

.. code:: python
>> from schema import Use, Const, And, Schema
>> from datetime import datetime
>> is_future = lambda date: datetime.now() > date
>> to_json = lambda v: {"timestamp": v}
>> Schema(And(Const(And(Use(datetime.fromtimestamp), is_future)), Use(to_json))).validate(1234567890)
{"timestamp": 1234567890}
Now you can write your own validation-aware classes and data types.

Lists, similar containers
Expand Down
8 changes: 7 additions & 1 deletion schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

__version__ = '0.6.6'
__all__ = ['Schema',
'And', 'Or', 'Regex', 'Optional', 'Use', 'Forbidden',
'And', 'Or', 'Regex', 'Optional', 'Use', 'Forbidden', 'Const',
'SchemaError',
'SchemaWrongKeyError',
'SchemaMissingKeyError',
Expand Down Expand Up @@ -372,6 +372,12 @@ def __init__(self, *args, **kwargs):
self.key = self._schema


class Const(Schema):
def validate(self, data):
super(Const, self).validate(data)
return data


def _callable_str(callable_):
if hasattr(callable_, '__name__'):
return callable_.__name__
Expand Down
25 changes: 24 additions & 1 deletion test_schema.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import with_statement
from collections import defaultdict, namedtuple
from functools import partial
from operator import methodcaller
import os
import re
Expand All @@ -8,7 +9,7 @@

from pytest import raises

from schema import (Schema, Use, And, Or, Regex, Optional,
from schema import (Schema, Use, And, Or, Regex, Optional, Const,
SchemaError, SchemaWrongKeyError,
SchemaMissingKeyError, SchemaUnexpectedTypeError,
SchemaForbiddenKeyError, Forbidden)
Expand Down Expand Up @@ -76,6 +77,28 @@ def test_or():
with SE: Or().validate(2)


def test_test():
def unique_list(_list):
return len(_list) == len(set(_list))

def dict_keys(key, _list):
return list(map(lambda d: d[key], _list))

schema = (
Schema(
Const(
And(Use(partial(dict_keys, "index")), unique_list))))
data = [
{"index": 1, "value": "foo"},
{"index": 2, "value": "bar"}]
assert schema.validate(data) == data

bad_data = [
{"index": 1, "value": "foo"},
{"index": 1, "value": "bar"}]
with SE: schema.validate(bad_data)


def test_regex():
# Simple case: validate string
assert Regex(r'foo').validate('afoot') == 'afoot'
Expand Down

0 comments on commit 56262d7

Please sign in to comment.