Hello community, here is the log from the commit of package python-schema for openSUSE:Factory checked in at 2020-10-15 13:48:43 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-schema (Old) and /work/SRC/openSUSE:Factory/.python-schema.new.3486 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-schema" Thu Oct 15 13:48:43 2020 rev:5 rq:833486 version:0.7.3 Changes: -------- --- /work/SRC/openSUSE:Factory/python-schema/python-schema.changes 2020-03-26 23:35:14.082817516 +0100 +++ /work/SRC/openSUSE:Factory/.python-schema.new.3486/python-schema.changes 2020-10-15 13:49:14.545270309 +0200 @@ -1,0 +2,10 @@ +Thu Sep 10 12:17:04 UTC 2020 - Antonio Larrosa <[email protected]> + +- Update to 0.7.3 + * JSON Schema: Support schemas where the root is not a dict. + * Do not drop previous errors within an Or criterion. + +- Update to 0.7.2 + * Set the contextlib dependency as a minimum, rather than fixed. + +------------------------------------------------------------------- Old: ---- schema-0.7.1.tar.gz New: ---- schema-0.7.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-schema.spec ++++++ --- /var/tmp/diff_new_pack.rIBtA2/_old 2020-10-15 13:49:17.085271372 +0200 +++ /var/tmp/diff_new_pack.rIBtA2/_new 2020-10-15 13:49:17.089271373 +0200 @@ -18,7 +18,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-schema -Version: 0.7.1 +Version: 0.7.3 Release: 0 Summary: Data validation library License: MIT ++++++ schema-0.7.1.tar.gz -> schema-0.7.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schema-0.7.1/PKG-INFO new/schema-0.7.3/PKG-INFO --- old/schema-0.7.1/PKG-INFO 2019-09-09 19:39:48.000000000 +0200 +++ new/schema-0.7.3/PKG-INFO 2020-07-31 13:58:12.272543200 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: schema -Version: 0.7.1 +Version: 0.7.3 Summary: Simple data validation library Home-page: https://github.com/keleshev/schema Author: Vladimir Keleshev @@ -28,7 +28,7 @@ .. code:: python - >>> from schema import Schema, And, Use, Optional + >>> from schema import Schema, And, Use, Optional, SchemaError >>> schema = Schema([{'name': And(str, len), ... 'age': And(Use(int), lambda n: 18 <= n <= 99), @@ -87,7 +87,7 @@ >>> Schema(int).validate('123') Traceback (most recent call last): ... - SchemaUnexpectedTypeError: '123' should be instance of 'int' + schema.SchemaUnexpectedTypeError: '123' should be instance of 'int' >>> Schema(object).validate('hai') 'hai' @@ -109,7 +109,7 @@ >>> Schema(os.path.exists).validate('./non-existent/') Traceback (most recent call last): ... - SchemaError: exists('./non-existent/') should evaluate to True + schema.SchemaError: exists('./non-existent/') should evaluate to True >>> Schema(lambda n: n > 0).validate(123) 123 @@ -117,7 +117,7 @@ >>> Schema(lambda n: n > 0).validate(-12) Traceback (most recent call last): ... - SchemaError: <lambda>(-12) should evaluate to True + schema.SchemaError: <lambda>(-12) should evaluate to True "Validatables" ~~~~~~~~~~~~~~ @@ -142,7 +142,7 @@ >>> Regex(r'^[A-Z]+$', flags=re.I).validate('those-dashes-dont-match') Traceback (most recent call last): ... - SchemaError: Regex('^[A-Z]+$', flags=re.IGNORECASE) does not match 'those-dashes-dont-match' + schema.SchemaError: Regex('^[A-Z]+$', flags=re.IGNORECASE) does not match 'those-dashes-dont-match' For a more general case, you can use ``Use`` for creating such objects. ``Use`` helps to use a function or type to convert a value while validating it: @@ -155,7 +155,7 @@ 123 >>> Schema(Use(lambda f: open(f, 'a'))).validate('LICENSE-MIT') - <open file 'LICENSE-MIT', mode 'a' at 0x...> + <_io.TextIOWrapper name='LICENSE-MIT' mode='a' encoding='UTF-8'> Dropping the details, ``Use`` is basically: @@ -194,10 +194,9 @@ Lists, similar containers ~~~~~~~~~~~~~~~~~~~~~~~~~ - If ``Schema(...)`` encounters an instance of ``list``, ``tuple``, ``set`` or - ``frozenset``, it will validate contents of corresponding data container - against schemas listed inside that container: - + If ``Schema(...)`` encounters an instance of ``list``, ``tuple``, ``set`` + or ``frozenset``, it will validate contents of corresponding data container + against all schemas listed inside that container and aggregate all errors: .. code:: python @@ -207,7 +206,8 @@ >>> Schema((int, float)).validate((5, 7, 8, 'not int or float here')) Traceback (most recent call last): ... - SchemaError: Or(<type 'int'>, <type 'float'>) did not validate 'not int or float here' + schema.SchemaError: Or(<class 'int'>, <class 'float'>) did not validate 'not int or float here' + 'not int or float here' should be instance of 'int' 'not int or float here' should be instance of 'float' Dictionaries @@ -237,7 +237,7 @@ ... 10: 'not None here'}) Traceback (most recent call last): ... - SchemaError: Key '10' error: + schema.SchemaError: Key '10' error: None does not match 'not None here' This is useful if you want to check certain key-values, but don't care @@ -308,7 +308,7 @@ >>> Schema({'password': And(str, lambda s: len(s) > 6)}).validate({'password': 'hai'}) Traceback (most recent call last): ... - SchemaError: Key 'password' error: + schema.SchemaError: Key 'password' error: <lambda>('hai') should evaluate to True >>> Schema(And(Or(int, float), lambda x: x > 0)).validate(3.1415) @@ -330,11 +330,11 @@ >>> schema.validate({"key1": "test", "key2": "test"}) # SchemaError Traceback (most recent call last): ... - SchemaOnlyOneAllowedError: There are multiple keys present from the Or('key1', 'key2') condition + schema.SchemaOnlyOneAllowedError: There are multiple keys present from the Or('key1', 'key2') condition Hooks ~~~~~~~~~~ - You can define hooks which are functions that are executed whenever a valid key:value is found. + You can define hooks which are functions that are executed whenever a valid key:value is found. The `Forbidden` class is an example of this. You can mark a key as forbidden as follows: @@ -345,7 +345,7 @@ >>> Schema({Forbidden('age'): object}).validate({'age': 50}) Traceback (most recent call last): ... - SchemaForbiddenKeyError: Forbidden key encountered: 'age' in {'age': 50} + schema.SchemaForbiddenKeyError: Forbidden key encountered: 'age' in {'age': 50} A few things are worth noting. First, the value paired with the forbidden key determines whether it will be rejected: @@ -366,7 +366,7 @@ >>> Schema({Forbidden('age'): object, Optional(str): object}).validate({'age': 50}) Traceback (most recent call last): ... - SchemaForbiddenKeyError: Forbidden key encountered: 'age' in {'age': 50} + schema.SchemaForbiddenKeyError: Forbidden key encountered: 'age' in {'age': 50} You can also define your own hooks. The following hook will call `_my_function` if `key` is encountered. @@ -418,7 +418,7 @@ >>> Schema(Use(int, error='Invalid year')).validate('XVII') Traceback (most recent call last): ... - SchemaError: Invalid year + schema.SchemaError: Invalid year You can see all errors that occurred by accessing exception's ``exc.autos`` for auto-generated error messages, and ``exc.errors`` for errors @@ -448,10 +448,10 @@ >>> import json >>> gist_schema = Schema(And(Use(json.loads), # first convert from JSON - ... # use basestring since json returns unicode - ... {Optional('description'): basestring, + ... # use str since json returns unicode + ... {Optional('description'): str, ... 'public': bool, - ... 'files': {basestring: {'content': basestring}}})) + ... 'files': {str: {'content': str}}})) >>> gist = gist_schema.validate(gist) @@ -494,7 +494,7 @@ >>> args = s.validate(args) >>> args['<files>'] - [<open file 'LICENSE-MIT', mode 'r' at 0x...>, <open file 'setup.py', mode 'r' at 0x...>] + [<_io.TextIOWrapper name='LICENSE-MIT' ...>, <_io.TextIOWrapper name='setup.py' ...] >>> args['<path>'] '../' @@ -582,9 +582,6 @@ JSON: Supported validations ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The main schema must be a dict. i.e. ``Schema({"test": str})`` works but ``Schema(str)`` does not. - The following examples will assume the main schema is a dict. - The resulting JSON schema is not guaranteed to accept the same objects as the library would accept, since some validations are not implemented or have no JSON schema equivalent. This is the case of the ``Use`` and ``Hook`` objects for example. @@ -638,11 +635,11 @@ ``{'type': 'array', 'items': {'type': 'string'}}`` `Enumerated values <https://json-schema.org/understanding-json-schema/reference/generic.html#enumerated-values>`_ - List the accepted values. + Use `Or`. Example: - ``Schema([1, 2, 3])`` becomes + ``Schema(Or(1, 2, 3))`` becomes ``{"enum": [1, 2, 3]}`` @@ -660,7 +657,7 @@ Example: - ``Regex("^v\d+")`` becomes + ``Schema(Regex("^v\d+"))`` becomes ``{'type': 'string', 'pattern': '^v\\d+'}`` @@ -684,7 +681,7 @@ Example: - ``Schema(And(str, "value")`` + ``Schema(And(str, "value"))`` becomes @@ -963,6 +960,7 @@ Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: License :: OSI Approved :: MIT License Description-Content-Type: text/x-rst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schema-0.7.1/README.rst new/schema-0.7.3/README.rst --- old/schema-0.7.1/README.rst 2019-09-09 19:38:08.000000000 +0200 +++ new/schema-0.7.3/README.rst 2020-07-31 13:56:22.000000000 +0200 @@ -20,7 +20,7 @@ .. code:: python - >>> from schema import Schema, And, Use, Optional + >>> from schema import Schema, And, Use, Optional, SchemaError >>> schema = Schema([{'name': And(str, len), ... 'age': And(Use(int), lambda n: 18 <= n <= 99), @@ -79,7 +79,7 @@ >>> Schema(int).validate('123') Traceback (most recent call last): ... - SchemaUnexpectedTypeError: '123' should be instance of 'int' + schema.SchemaUnexpectedTypeError: '123' should be instance of 'int' >>> Schema(object).validate('hai') 'hai' @@ -101,7 +101,7 @@ >>> Schema(os.path.exists).validate('./non-existent/') Traceback (most recent call last): ... - SchemaError: exists('./non-existent/') should evaluate to True + schema.SchemaError: exists('./non-existent/') should evaluate to True >>> Schema(lambda n: n > 0).validate(123) 123 @@ -109,7 +109,7 @@ >>> Schema(lambda n: n > 0).validate(-12) Traceback (most recent call last): ... - SchemaError: <lambda>(-12) should evaluate to True + schema.SchemaError: <lambda>(-12) should evaluate to True "Validatables" ~~~~~~~~~~~~~~ @@ -134,7 +134,7 @@ >>> Regex(r'^[A-Z]+$', flags=re.I).validate('those-dashes-dont-match') Traceback (most recent call last): ... - SchemaError: Regex('^[A-Z]+$', flags=re.IGNORECASE) does not match 'those-dashes-dont-match' + schema.SchemaError: Regex('^[A-Z]+$', flags=re.IGNORECASE) does not match 'those-dashes-dont-match' For a more general case, you can use ``Use`` for creating such objects. ``Use`` helps to use a function or type to convert a value while validating it: @@ -147,7 +147,7 @@ 123 >>> Schema(Use(lambda f: open(f, 'a'))).validate('LICENSE-MIT') - <open file 'LICENSE-MIT', mode 'a' at 0x...> + <_io.TextIOWrapper name='LICENSE-MIT' mode='a' encoding='UTF-8'> Dropping the details, ``Use`` is basically: @@ -186,10 +186,9 @@ Lists, similar containers ~~~~~~~~~~~~~~~~~~~~~~~~~ -If ``Schema(...)`` encounters an instance of ``list``, ``tuple``, ``set`` or -``frozenset``, it will validate contents of corresponding data container -against schemas listed inside that container: - +If ``Schema(...)`` encounters an instance of ``list``, ``tuple``, ``set`` +or ``frozenset``, it will validate contents of corresponding data container +against all schemas listed inside that container and aggregate all errors: .. code:: python @@ -199,7 +198,8 @@ >>> Schema((int, float)).validate((5, 7, 8, 'not int or float here')) Traceback (most recent call last): ... - SchemaError: Or(<type 'int'>, <type 'float'>) did not validate 'not int or float here' + schema.SchemaError: Or(<class 'int'>, <class 'float'>) did not validate 'not int or float here' + 'not int or float here' should be instance of 'int' 'not int or float here' should be instance of 'float' Dictionaries @@ -229,7 +229,7 @@ ... 10: 'not None here'}) Traceback (most recent call last): ... - SchemaError: Key '10' error: + schema.SchemaError: Key '10' error: None does not match 'not None here' This is useful if you want to check certain key-values, but don't care @@ -300,7 +300,7 @@ >>> Schema({'password': And(str, lambda s: len(s) > 6)}).validate({'password': 'hai'}) Traceback (most recent call last): ... - SchemaError: Key 'password' error: + schema.SchemaError: Key 'password' error: <lambda>('hai') should evaluate to True >>> Schema(And(Or(int, float), lambda x: x > 0)).validate(3.1415) @@ -322,11 +322,11 @@ >>> schema.validate({"key1": "test", "key2": "test"}) # SchemaError Traceback (most recent call last): ... - SchemaOnlyOneAllowedError: There are multiple keys present from the Or('key1', 'key2') condition + schema.SchemaOnlyOneAllowedError: There are multiple keys present from the Or('key1', 'key2') condition Hooks ~~~~~~~~~~ -You can define hooks which are functions that are executed whenever a valid key:value is found. +You can define hooks which are functions that are executed whenever a valid key:value is found. The `Forbidden` class is an example of this. You can mark a key as forbidden as follows: @@ -337,7 +337,7 @@ >>> Schema({Forbidden('age'): object}).validate({'age': 50}) Traceback (most recent call last): ... - SchemaForbiddenKeyError: Forbidden key encountered: 'age' in {'age': 50} + schema.SchemaForbiddenKeyError: Forbidden key encountered: 'age' in {'age': 50} A few things are worth noting. First, the value paired with the forbidden key determines whether it will be rejected: @@ -358,7 +358,7 @@ >>> Schema({Forbidden('age'): object, Optional(str): object}).validate({'age': 50}) Traceback (most recent call last): ... - SchemaForbiddenKeyError: Forbidden key encountered: 'age' in {'age': 50} + schema.SchemaForbiddenKeyError: Forbidden key encountered: 'age' in {'age': 50} You can also define your own hooks. The following hook will call `_my_function` if `key` is encountered. @@ -410,7 +410,7 @@ >>> Schema(Use(int, error='Invalid year')).validate('XVII') Traceback (most recent call last): ... - SchemaError: Invalid year + schema.SchemaError: Invalid year You can see all errors that occurred by accessing exception's ``exc.autos`` for auto-generated error messages, and ``exc.errors`` for errors @@ -440,10 +440,10 @@ >>> import json >>> gist_schema = Schema(And(Use(json.loads), # first convert from JSON - ... # use basestring since json returns unicode - ... {Optional('description'): basestring, + ... # use str since json returns unicode + ... {Optional('description'): str, ... 'public': bool, - ... 'files': {basestring: {'content': basestring}}})) + ... 'files': {str: {'content': str}}})) >>> gist = gist_schema.validate(gist) @@ -486,7 +486,7 @@ >>> args = s.validate(args) >>> args['<files>'] - [<open file 'LICENSE-MIT', mode 'r' at 0x...>, <open file 'setup.py', mode 'r' at 0x...>] + [<_io.TextIOWrapper name='LICENSE-MIT' ...>, <_io.TextIOWrapper name='setup.py' ...] >>> args['<path>'] '../' @@ -574,9 +574,6 @@ JSON: Supported validations ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The main schema must be a dict. i.e. ``Schema({"test": str})`` works but ``Schema(str)`` does not. -The following examples will assume the main schema is a dict. - The resulting JSON schema is not guaranteed to accept the same objects as the library would accept, since some validations are not implemented or have no JSON schema equivalent. This is the case of the ``Use`` and ``Hook`` objects for example. @@ -630,11 +627,11 @@ ``{'type': 'array', 'items': {'type': 'string'}}`` `Enumerated values <https://json-schema.org/understanding-json-schema/reference/generic.html#enumerated-values>`_ - List the accepted values. + Use `Or`. Example: - ``Schema([1, 2, 3])`` becomes + ``Schema(Or(1, 2, 3))`` becomes ``{"enum": [1, 2, 3]}`` @@ -652,7 +649,7 @@ Example: - ``Regex("^v\d+")`` becomes + ``Schema(Regex("^v\d+"))`` becomes ``{'type': 'string', 'pattern': '^v\\d+'}`` @@ -676,7 +673,7 @@ Example: - ``Schema(And(str, "value")`` + ``Schema(And(str, "value"))`` becomes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schema-0.7.1/pyproject.toml new/schema-0.7.3/pyproject.toml --- old/schema-0.7.1/pyproject.toml 1970-01-01 01:00:00.000000000 +0100 +++ new/schema-0.7.3/pyproject.toml 2019-09-09 19:38:08.000000000 +0200 @@ -0,0 +1,20 @@ +[tool.black] +line-length = 120 +target-version = ['py37'] +include = '\.pyi?$' +exclude = ''' +( + /( + \.eggs # exclude a few common directories in the + | \.git # root of the project + | \.hg + | \.mypy_cache + | \.tox + | \.venv + | _build + | buck-out + | build + | dist + )/ +) +''' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schema-0.7.1/requirements.txt new/schema-0.7.3/requirements.txt --- old/schema-0.7.1/requirements.txt 2019-09-09 19:38:08.000000000 +0200 +++ new/schema-0.7.3/requirements.txt 2020-07-31 13:56:22.000000000 +0200 @@ -1 +1 @@ -contextlib2==0.5.5 \ No newline at end of file +contextlib2>=0.5.5 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schema-0.7.1/schema.egg-info/PKG-INFO new/schema-0.7.3/schema.egg-info/PKG-INFO --- old/schema-0.7.1/schema.egg-info/PKG-INFO 2019-09-09 19:39:48.000000000 +0200 +++ new/schema-0.7.3/schema.egg-info/PKG-INFO 2020-07-31 13:58:12.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: schema -Version: 0.7.1 +Version: 0.7.3 Summary: Simple data validation library Home-page: https://github.com/keleshev/schema Author: Vladimir Keleshev @@ -28,7 +28,7 @@ .. code:: python - >>> from schema import Schema, And, Use, Optional + >>> from schema import Schema, And, Use, Optional, SchemaError >>> schema = Schema([{'name': And(str, len), ... 'age': And(Use(int), lambda n: 18 <= n <= 99), @@ -87,7 +87,7 @@ >>> Schema(int).validate('123') Traceback (most recent call last): ... - SchemaUnexpectedTypeError: '123' should be instance of 'int' + schema.SchemaUnexpectedTypeError: '123' should be instance of 'int' >>> Schema(object).validate('hai') 'hai' @@ -109,7 +109,7 @@ >>> Schema(os.path.exists).validate('./non-existent/') Traceback (most recent call last): ... - SchemaError: exists('./non-existent/') should evaluate to True + schema.SchemaError: exists('./non-existent/') should evaluate to True >>> Schema(lambda n: n > 0).validate(123) 123 @@ -117,7 +117,7 @@ >>> Schema(lambda n: n > 0).validate(-12) Traceback (most recent call last): ... - SchemaError: <lambda>(-12) should evaluate to True + schema.SchemaError: <lambda>(-12) should evaluate to True "Validatables" ~~~~~~~~~~~~~~ @@ -142,7 +142,7 @@ >>> Regex(r'^[A-Z]+$', flags=re.I).validate('those-dashes-dont-match') Traceback (most recent call last): ... - SchemaError: Regex('^[A-Z]+$', flags=re.IGNORECASE) does not match 'those-dashes-dont-match' + schema.SchemaError: Regex('^[A-Z]+$', flags=re.IGNORECASE) does not match 'those-dashes-dont-match' For a more general case, you can use ``Use`` for creating such objects. ``Use`` helps to use a function or type to convert a value while validating it: @@ -155,7 +155,7 @@ 123 >>> Schema(Use(lambda f: open(f, 'a'))).validate('LICENSE-MIT') - <open file 'LICENSE-MIT', mode 'a' at 0x...> + <_io.TextIOWrapper name='LICENSE-MIT' mode='a' encoding='UTF-8'> Dropping the details, ``Use`` is basically: @@ -194,10 +194,9 @@ Lists, similar containers ~~~~~~~~~~~~~~~~~~~~~~~~~ - If ``Schema(...)`` encounters an instance of ``list``, ``tuple``, ``set`` or - ``frozenset``, it will validate contents of corresponding data container - against schemas listed inside that container: - + If ``Schema(...)`` encounters an instance of ``list``, ``tuple``, ``set`` + or ``frozenset``, it will validate contents of corresponding data container + against all schemas listed inside that container and aggregate all errors: .. code:: python @@ -207,7 +206,8 @@ >>> Schema((int, float)).validate((5, 7, 8, 'not int or float here')) Traceback (most recent call last): ... - SchemaError: Or(<type 'int'>, <type 'float'>) did not validate 'not int or float here' + schema.SchemaError: Or(<class 'int'>, <class 'float'>) did not validate 'not int or float here' + 'not int or float here' should be instance of 'int' 'not int or float here' should be instance of 'float' Dictionaries @@ -237,7 +237,7 @@ ... 10: 'not None here'}) Traceback (most recent call last): ... - SchemaError: Key '10' error: + schema.SchemaError: Key '10' error: None does not match 'not None here' This is useful if you want to check certain key-values, but don't care @@ -308,7 +308,7 @@ >>> Schema({'password': And(str, lambda s: len(s) > 6)}).validate({'password': 'hai'}) Traceback (most recent call last): ... - SchemaError: Key 'password' error: + schema.SchemaError: Key 'password' error: <lambda>('hai') should evaluate to True >>> Schema(And(Or(int, float), lambda x: x > 0)).validate(3.1415) @@ -330,11 +330,11 @@ >>> schema.validate({"key1": "test", "key2": "test"}) # SchemaError Traceback (most recent call last): ... - SchemaOnlyOneAllowedError: There are multiple keys present from the Or('key1', 'key2') condition + schema.SchemaOnlyOneAllowedError: There are multiple keys present from the Or('key1', 'key2') condition Hooks ~~~~~~~~~~ - You can define hooks which are functions that are executed whenever a valid key:value is found. + You can define hooks which are functions that are executed whenever a valid key:value is found. The `Forbidden` class is an example of this. You can mark a key as forbidden as follows: @@ -345,7 +345,7 @@ >>> Schema({Forbidden('age'): object}).validate({'age': 50}) Traceback (most recent call last): ... - SchemaForbiddenKeyError: Forbidden key encountered: 'age' in {'age': 50} + schema.SchemaForbiddenKeyError: Forbidden key encountered: 'age' in {'age': 50} A few things are worth noting. First, the value paired with the forbidden key determines whether it will be rejected: @@ -366,7 +366,7 @@ >>> Schema({Forbidden('age'): object, Optional(str): object}).validate({'age': 50}) Traceback (most recent call last): ... - SchemaForbiddenKeyError: Forbidden key encountered: 'age' in {'age': 50} + schema.SchemaForbiddenKeyError: Forbidden key encountered: 'age' in {'age': 50} You can also define your own hooks. The following hook will call `_my_function` if `key` is encountered. @@ -418,7 +418,7 @@ >>> Schema(Use(int, error='Invalid year')).validate('XVII') Traceback (most recent call last): ... - SchemaError: Invalid year + schema.SchemaError: Invalid year You can see all errors that occurred by accessing exception's ``exc.autos`` for auto-generated error messages, and ``exc.errors`` for errors @@ -448,10 +448,10 @@ >>> import json >>> gist_schema = Schema(And(Use(json.loads), # first convert from JSON - ... # use basestring since json returns unicode - ... {Optional('description'): basestring, + ... # use str since json returns unicode + ... {Optional('description'): str, ... 'public': bool, - ... 'files': {basestring: {'content': basestring}}})) + ... 'files': {str: {'content': str}}})) >>> gist = gist_schema.validate(gist) @@ -494,7 +494,7 @@ >>> args = s.validate(args) >>> args['<files>'] - [<open file 'LICENSE-MIT', mode 'r' at 0x...>, <open file 'setup.py', mode 'r' at 0x...>] + [<_io.TextIOWrapper name='LICENSE-MIT' ...>, <_io.TextIOWrapper name='setup.py' ...] >>> args['<path>'] '../' @@ -582,9 +582,6 @@ JSON: Supported validations ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The main schema must be a dict. i.e. ``Schema({"test": str})`` works but ``Schema(str)`` does not. - The following examples will assume the main schema is a dict. - The resulting JSON schema is not guaranteed to accept the same objects as the library would accept, since some validations are not implemented or have no JSON schema equivalent. This is the case of the ``Use`` and ``Hook`` objects for example. @@ -638,11 +635,11 @@ ``{'type': 'array', 'items': {'type': 'string'}}`` `Enumerated values <https://json-schema.org/understanding-json-schema/reference/generic.html#enumerated-values>`_ - List the accepted values. + Use `Or`. Example: - ``Schema([1, 2, 3])`` becomes + ``Schema(Or(1, 2, 3))`` becomes ``{"enum": [1, 2, 3]}`` @@ -660,7 +657,7 @@ Example: - ``Regex("^v\d+")`` becomes + ``Schema(Regex("^v\d+"))`` becomes ``{'type': 'string', 'pattern': '^v\\d+'}`` @@ -684,7 +681,7 @@ Example: - ``Schema(And(str, "value")`` + ``Schema(And(str, "value"))`` becomes @@ -963,6 +960,7 @@ Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: License :: OSI Approved :: MIT License Description-Content-Type: text/x-rst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schema-0.7.1/schema.egg-info/SOURCES.txt new/schema-0.7.3/schema.egg-info/SOURCES.txt --- old/schema-0.7.1/schema.egg-info/SOURCES.txt 2019-09-09 19:39:48.000000000 +0200 +++ new/schema-0.7.3/schema.egg-info/SOURCES.txt 2020-07-31 13:58:12.000000000 +0200 @@ -1,6 +1,7 @@ LICENSE-MIT MANIFEST.in README.rst +pyproject.toml requirements.txt schema.py setup.cfg diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schema-0.7.1/schema.egg-info/requires.txt new/schema-0.7.3/schema.egg-info/requires.txt --- old/schema-0.7.1/schema.egg-info/requires.txt 2019-09-09 19:39:48.000000000 +0200 +++ new/schema-0.7.3/schema.egg-info/requires.txt 2020-07-31 13:58:12.000000000 +0200 @@ -1 +1 @@ -contextlib2==0.5.5 +contextlib2>=0.5.5 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schema-0.7.1/schema.py new/schema-0.7.3/schema.py --- old/schema-0.7.1/schema.py 2019-09-09 19:39:33.000000000 +0200 +++ new/schema-0.7.3/schema.py 2020-07-31 13:56:45.000000000 +0200 @@ -9,7 +9,7 @@ except ImportError: from contextlib2 import ExitStack -__version__ = "0.7.1" +__version__ = "0.7.3" __all__ = [ "Schema", "And", @@ -160,7 +160,8 @@ break return validation except SchemaError as _x: - autos, errors = _x.autos, _x.errors + autos += _x.autos + errors += _x.errors raise SchemaError( ["%r did not validate %r" % (self, data)] + autos, [self._error.format(data) if self._error else None] + errors, @@ -341,7 +342,7 @@ def validate(self, data): Schema = self.__class__ s = self._schema - e = self._error + e = self._error.format(data) if self._error else None i = self._ignore_extra_keys if isinstance(s, Literal): @@ -411,7 +412,7 @@ s_wrong_keys = ", ".join(repr(k) for k in sorted(wrong_keys, key=repr)) message = "Wrong key%s %s in %r" % (_plural_s(wrong_keys), s_wrong_keys, data) message = self._prepend_schema_name(message) - raise SchemaWrongKeyError(message, e.format(data) if e else None) + raise SchemaWrongKeyError(message, e) # Apply default-having optionals that haven't been used: defaults = set(k for k in s if type(k) is Optional and hasattr(k, "default")) - coverage @@ -425,7 +426,7 @@ else: message = "%r should be instance of %r" % (data, s.__name__) message = self._prepend_schema_name(message) - raise SchemaUnexpectedTypeError(message, e.format(data) if e else None) + raise SchemaUnexpectedTypeError(message, e) if flavor == VALIDATOR: try: return s.validate(data) @@ -434,7 +435,7 @@ except BaseException as x: message = "%r.validate(%r) raised %r" % (s, data, x) message = self._prepend_schema_name(message) - raise SchemaError(message, self._error.format(data) if self._error else None) + raise SchemaError(message, e) if flavor == CALLABLE: f = _callable_str(s) try: @@ -445,7 +446,7 @@ except BaseException as x: message = "%s(%r) raised %r" % (f, data, x) message = self._prepend_schema_name(message) - raise SchemaError(message, self._error.format(data) if self._error else None) + raise SchemaError(message, e) message = "%s(%r) should evaluate to True" % (f, data) message = self._prepend_schema_name(message) raise SchemaError(message, e) @@ -454,7 +455,7 @@ else: message = "%r does not match %r" % (s, data) message = self._prepend_schema_name(message) - raise SchemaError(message, e.format(data) if e else None) + raise SchemaError(message, e) def json_schema(self, schema_id, use_refs=False): """Generate a draft-07 JSON schema dict representing the Schema. @@ -533,13 +534,9 @@ return_schema = {} is_a_ref = allow_reference and schema.as_reference - if schema.description and not is_a_ref: - return_schema["description"] = schema.description - if description and not is_a_ref: - return_schema["description"] = description - - if flavor != DICT and is_main_schema: - raise ValueError("The main schema must be a dict.") + return_description = description or schema.description + if return_description: + return_schema["description"] = return_description if flavor == TYPE: # Handle type @@ -665,15 +662,15 @@ } ) - if is_main_schema: - return_schema.update({"$id": schema_id, "$schema": "http://json-schema.org/draft-07/schema#"}) - if self._name: - return_schema["title"] = self._name - - if definitions_by_name: - return_schema["definitions"] = {} - for definition_name, definition in definitions_by_name.items(): - return_schema["definitions"][definition_name] = definition + if is_main_schema: + return_schema.update({"$id": schema_id, "$schema": "http://json-schema.org/draft-07/schema#"}) + if self._name: + return_schema["title"] = self._name + + if definitions_by_name: + return_schema["definitions"] = {} + for definition_name, definition in definitions_by_name.items(): + return_schema["definitions"][definition_name] = definition return _create_or_use_ref(return_schema) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schema-0.7.1/setup.py new/schema-0.7.3/setup.py --- old/schema-0.7.1/setup.py 2019-09-09 19:38:08.000000000 +0200 +++ new/schema-0.7.3/setup.py 2020-07-31 13:56:22.000000000 +0200 @@ -37,6 +37,7 @@ "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", "Programming Language :: Python :: Implementation :: PyPy", "License :: OSI Approved :: MIT License", ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/schema-0.7.1/test_schema.py new/schema-0.7.3/test_schema.py --- old/schema-0.7.1/test_schema.py 2019-09-09 19:38:08.000000000 +0200 +++ new/schema-0.7.3/test_schema.py 2020-07-31 13:56:22.000000000 +0200 @@ -12,6 +12,7 @@ from mock import Mock from pytest import mark, raises + from schema import ( And, Const, @@ -1080,10 +1081,55 @@ } -def test_json_schema_not_a_dict(): - s = Schema(int) - with raises(ValueError): - s.json_schema("my-id") [email protected]( + "input_schema, expected_keyword, expected_value", + [ + (int, "type", "integer"), + (float, "type", "number"), + (list, "type", "array"), + (bool, "type", "boolean"), + (dict, "type", "object"), + ("test", "const", "test"), + (Or(1, 2, 3), "enum", [1, 2, 3]), + (Or(str, int), "anyOf", [{"type": "string"}, {"type": "integer"}]), + (And(str, "value"), "allOf", [{"type": "string"}, {"const": "value"}]), + ], +) +def test_json_schema_root_not_dict(input_schema, expected_keyword, expected_value): + """Test generating simple JSON Schemas where the root element is not a dict""" + json_schema = Schema(input_schema).json_schema("my-id") + + assert json_schema == { + expected_keyword: expected_value, + "$id": "my-id", + "$schema": "http://json-schema.org/draft-07/schema#", + } + + [email protected]( + "input_schema, expected_keyword, expected_value", + [([1, 2, 3], "enum", [1, 2, 3]), ([1], "const", 1), ([str], "type", "string")], +) +def test_json_schema_array(input_schema, expected_keyword, expected_value): + json_schema = Schema(input_schema).json_schema("my-id") + + assert json_schema == { + "type": "array", + "items": {expected_keyword: expected_value}, + "$id": "my-id", + "$schema": "http://json-schema.org/draft-07/schema#", + } + + +def test_json_schema_regex_root(): + json_schema = Schema(Regex("^v\\d+")).json_schema("my-id") + + assert json_schema == { + "type": "string", + "pattern": "^v\\d+", + "$id": "my-id", + "$schema": "http://json-schema.org/draft-07/schema#", + } def test_json_schema_dict_type(): @@ -1326,11 +1372,17 @@ def test_json_schema_definitions_and_literals(): - sub_schema = Schema({Literal("sub_key1", description="Sub key 1"): int}, name="sub_schema", as_reference=True) + sub_schema = Schema( + {Literal("sub_key1", description="Sub key 1"): int}, + name="sub_schema", + as_reference=True, + description="Sub Schema", + ) main_schema = Schema( { Literal("main_key1", description="Main Key 1"): str, Literal("main_key2", description="Main Key 2"): sub_schema, + Literal("main_key3", description="Main Key 3"): sub_schema, } ) @@ -1339,14 +1391,16 @@ "type": "object", "properties": { "main_key1": {"description": "Main Key 1", "type": "string"}, - "main_key2": {"$ref": "#/definitions/sub_schema"}, + "main_key2": {"$ref": "#/definitions/sub_schema", "description": "Main Key 2"}, + "main_key3": {"$ref": "#/definitions/sub_schema", "description": "Main Key 3"}, }, - "required": ["main_key1", "main_key2"], + "required": ["main_key1", "main_key2", "main_key3"], "additionalProperties": False, "$id": "my-id", "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "sub_schema": { + "description": "Sub Schema", "type": "object", "properties": {"sub_key1": {"description": "Sub key 1", "type": "integer"}}, "required": ["sub_key1"],
