Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A preview on Cerberus 2 #431

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ develop-eggs
# Installer logs
pip-log.txt

# Unit test / coverage reports
.cache
.coverage
# tests / coverage reports
.cache/
.coverage/
.mypy_cache/
.pytest_cache/
.tox
.tox/

# Translations
*.mo
Expand Down
1 change: 1 addition & 0 deletions .linting-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ repos:
python_version: python3.6
types:
- python
exclude: ^docs/conf.py$
- repo: https:/pre-commit/pre-commit-hooks
rev: v1.3.0
hooks:
Expand Down
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ repos:
python_version: python3.6
types:
- python
exclude: ^docs/conf.py$
- repo: https:/pre-commit/pre-commit-hooks
rev: v1.3.0
hooks:
Expand Down
3 changes: 0 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@ sudo: false
language: python
cache: pip
python:
- 2.7
- 3.4
- 3.5
- 3.6
- pypy
funkyfuture marked this conversation as resolved.
Show resolved Hide resolved
- pypy3
install: travis_retry pip install tox-travis
script: tox --recreate
39 changes: 34 additions & 5 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,41 @@ First time contributor?
-----------------------
It's alright. We've all been there.

Dont' know where to start?
Type annotations
----------------
There are two purposes for type annotations in the codebase: The first one is
to provide information for applications such as IDEs, so they can give useful
hints within the client codebase when unexpected types of values are passed to
Cerberus' interfaces. The other is to document the intended use of variables,
such as ``bar = {} # type: Dict[str, int]``.
Though testing type annotations with checkers like mypy_ can reveal possible
problems, this is not what they're intended for. The annotations however must
be checked for correctness. As Python's typing system and the most advanced
type checker aren't mature yet and it isn't possible to annotate every part
correctly with a reasonable effort due to the nature of Cerberus architecture,
there has to be a compromise to comply with the afore mentioned goals and
requirement:

1. All parts of the public API (functions, methods, class variables) *must* be
type annotated. It is okay to cast_ variables and instruct type checkers
to ignore errors (``# type: ignore``). It should occasionally be checked
whether these can be removed due to progress both within Cerberus' code
and the used checker.

2. The annotation of code that is not supposed to be used directly is helpful
for maintenance and *should* be added if the checker doesn't need to be
pleased with the previously mentioned methods. If such are required,
type annotations *must not* be added at all.

Don't know where to start?
--------------------------
There are usually several TODO comments scattered around the codebase, maybe
check them out and see if you have ideas, or can help with them. Also, check
check them out and see if you have ideas and can help with them. Also, check
the `open issues`_ in case there's something that sparks your interest. What
about documentation? I suck at english so if you're fluent with it (or notice
any error), why not help with that? In any case, other than GitHub help_ pages,
you might want to check this excellent `Effective Guide to Pull Requests`_
about documentation? We're contributors and reviewers with different mother
tongues, so if you're fluent with it (or notice any error), why not help with
that? In any case, other than GitHub help_ pages, you might want to check this
excellent `Effective Guide to Pull Requests`_

.. _`the repository`: https:/pyeve/cerberus
.. _AUTHORS: https:/pyeve/cerberus/blob/master/AUTHORS
Expand All @@ -69,3 +96,5 @@ you might want to check this excellent `Effective Guide to Pull Requests`_
.. _`Effective Guide to Pull Requests`: http://codeinthehole.com/writing/pull-requests-and-other-good-practices-for-teams-using-github/
.. _`fork and edit`: https:/blog/844-forking-with-the-edit-button
.. _`Pull Request`: https://help.github.com/articles/creating-a-pull-request
.. _mypy: https://mypy.readthedocs.io/
.. _cast: https://docs.python.org/3/library/typing.html#typing.cast
19 changes: 9 additions & 10 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,21 @@ implications.

#### Checklist

- [ ] All Python 2 related code is removed.
- [ ] Python 3 features that allow simpler code are applied where feasible.
- [ ] A Python 3-style metaclass.
- [ ] Using `super()` to call overridden methods.
- [ ] Usage of dictionary comprehensions.
- [x] Deprecated features are removed.
- [x] The `schema` rule only handles mappings, a new `itemrules` replaces the
part where `schema` tested items in sequences so far. There will be no
backward-compatibility for schemas. (#385)
- [x] All Python 2 related code is removed.
- [x] Python 3 features that allow simpler code are applied where feasible.
- [x] A Python 3-style metaclass.
- [x] Using `super()` to call overridden methods.
- [x] Usage of dictionary comprehensions and set literals.
- [ ] All functions and methods are type annotated. MyPy is added to the test
suite.
- [ ] A wider choice of type names that are closer oriented on the builtin
names are available. (#374)
- [ ] Objects from the `typing` module can be used as constraints for the
`type` rule. (#374)
- [ ] The `schema` rule only handles mappings, a new `itemrules` replaces the
part where `schema` tested items in sequences so far. There will be no
backward-compatibility for schemas. (#385)
- [ ] The rules `keyschema` and `valueschema` are renamed to `keyrules` and
`valuerules`, backward-compatibility for schemas will be provided. (#385)
- [ ] Implementations of rules, coercers etc. can and the contributed should be
qualified as such by metadata-annotating decorators. (With the intend to
clean the code and make extensions simpler.) (#372)
Expand Down
56 changes: 54 additions & 2 deletions UPGRADING.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,57 @@
Upgrading to Cerberus 1.0
=========================
Upgrading to Cerberus 2.0 from any 1.x version
==============================================

Major Changes and Deprecations
------------------------------

Rules
.....

A few rules have been renamed:

======================== ===============
Old name New name
======================== ===============
``keyschema`` ``keysrules``
``schema`` for sequences ``itemsrules``
funkyfuture marked this conversation as resolved.
Show resolved Hide resolved
``validator`` ``check_with``
``valueschema`` ``valuesrules``
======================== ===============

As a consequence custom validators' methods that are referenced by name in
constraints for the ``check_with`` rule must be prefixed with ``_check_with_``
instead of ``_validator_``.

Errors
......

A few constant names of error definitions in the :mod:`~cerberus.errors`
module have been renamed:

===================== ==============
Old name New name
===================== ==============
``BAD_ITEMS`` ``ITEMS``
``BAD_TYPE`` ``TYPE``
``EMPTY_NOT_ALLOWED`` ``EMPTY``
``MAPPING_SCHEMA`` ``SCHEMA``
``NOT_NULLABLE`` ``NULLABLE``
``SEQUENCE_SCHEMA`` ``ITEMSRULES``
===================== ==============

The constant ``BAD_TYPE_FOR_SCHEMA`` has been removed permanently.

Type checking
.............

The use of methods prefixes with ``_validate_type_`` for checking the type of
a value has been abandoned. See :doc:`customize` how to define custom types
with :class:`TypeDefinition` objects. If you used such methods to test more
than the type of the value, use the ``check_with`` rules instead.


Upgrading to Cerberus 1.0 from prior versions
=============================================

Major Additions
---------------
Expand Down
54 changes: 50 additions & 4 deletions cerberus/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,68 @@

"""

from __future__ import absolute_import
from typing import Dict, Optional, Tuple, Union
funkyfuture marked this conversation as resolved.
Show resolved Hide resolved

import pkg_resources

from cerberus.validator import DocumentError, Validator
from cerberus.schema import rules_set_registry, schema_registry, SchemaError
from cerberus.utils import TypeDefinition
from cerberus.base import (
rules_set_registry,
schema_registry,
DocumentError,
TypeDefinition,
UnconcernedValidator,
)
from cerberus.schema import SchemaError
from cerberus.validator import Validator


__version__ = pkg_resources.get_distribution('Cerberus').version


def validator_factory(
name: str,
bases: Union[type, Tuple[type], None] = None,
namespace: Optional[Dict] = None,
validated_schema: bool = True,
) -> type:
""" Dynamically create a :class:`~cerberus.Validator` subclass.
Docstrings of mixin-classes will be added to the resulting
class' one if ``__doc__`` is not in :obj:`namespace`.

:param name: The name of the new class.
:param bases: Class(es) with additional and overriding attributes.
:param namespace: Attributes for the new class.
:param validated_schema: Indicates that schemas that are provided to the validator
are to be validated.
:return: The created class.
"""

validator_class = Validator if validated_schema else UnconcernedValidator

if namespace is None:
namespace = {}

if bases is None:
computed_bases = (validator_class,)
elif isinstance(bases, tuple) and validator_class not in bases:
computed_bases = bases + (validator_class,) # type: ignore
else:
computed_bases = (bases, validator_class) # type: ignore

docstrings = [x.__doc__ for x in computed_bases if x.__doc__]
if len(docstrings) > 1 and '__doc__' not in namespace:
namespace.update({'__doc__': '\n'.join(docstrings)})

return type(name, computed_bases, namespace)


__all__ = [
DocumentError.__name__,
SchemaError.__name__,
TypeDefinition.__name__,
UnconcernedValidator.__name__,
Validator.__name__,
'schema_registry',
'rules_set_registry',
validator_factory.__name__,
]
Loading