firefox/build-python-2.patch

608 lines
25 KiB
Diff

diff -up firefox-90.0/third_party/python/requirements.in.build-python-2 firefox-90.0/third_party/python/requirements.in
--- firefox-90.0/third_party/python/requirements.in.build-python-2 2021-07-05 21:16:03.000000000 +0200
+++ firefox-90.0/third_party/python/requirements.in 2021-07-21 09:42:47.772128103 +0200
@@ -44,5 +44,5 @@ requests==2.25.1
responses==0.10.6
sentry-sdk==0.14.3
six==1.13.0
-voluptuous==0.11.5
+voluptuous==0.12.1
yamllint==1.23
diff -up firefox-90.0/third_party/python/requirements.txt.build-python-2 firefox-90.0/third_party/python/requirements.txt
--- firefox-90.0/third_party/python/requirements.txt.build-python-2 2021-07-05 21:16:03.000000000 +0200
+++ firefox-90.0/third_party/python/requirements.txt 2021-07-21 09:42:47.773128134 +0200
@@ -286,9 +286,9 @@ urllib3==1.25.9 \
# via
# requests
# sentry-sdk
-voluptuous==0.11.5 \
- --hash=sha256:303542b3fc07fb52ec3d7a1c614b329cdbee13a9d681935353d8ea56a7bfa9f1 \
- --hash=sha256:567a56286ef82a9d7ae0628c5842f65f516abcb496e74f3f59f1d7b28df314ef
+voluptuous==0.12.1 \
+ --hash=sha256:663572419281ddfaf4b4197fd4942d181630120fb39b333e3adad70aeb56444b \
+ --hash=sha256:8ace33fcf9e6b1f59406bfaf6b8ec7bcc44266a9f29080b4deb4fe6ff2492386
# via -r requirements-mach-vendor-python.in
yamllint==1.23 \
--hash=sha256:0fa69bf8a86182b7fe14918bdd3a30354c869966bbc7cbfff176af71bda9c806 \
diff -up firefox-90.0/third_party/python/voluptuous/voluptuous-0.11.5.dist-info/RECORD.build-python-2 firefox-90.0/third_party/python/voluptuous/voluptuous-0.11.5.dist-info/RECORD
diff -up firefox-90.0/third_party/python/voluptuous/voluptuous-0.12.1.dist-info/COPYING.build-python-2 firefox-90.0/third_party/python/voluptuous/voluptuous-0.12.1.dist-info/COPYING
--- firefox-90.0/third_party/python/voluptuous/voluptuous-0.12.1.dist-info/COPYING.build-python-2 2021-07-21 09:42:47.774128166 +0200
+++ firefox-90.0/third_party/python/voluptuous/voluptuous-0.12.1.dist-info/COPYING 2021-07-21 09:42:47.774128166 +0200
@@ -0,0 +1,25 @@
+Copyright (c) 2010, Alec Thomas
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ - Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of SwapOff.org nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff -up firefox-90.0/third_party/python/voluptuous/voluptuous-0.12.1.dist-info/RECORD.build-python-2 firefox-90.0/third_party/python/voluptuous/voluptuous-0.12.1.dist-info/RECORD
--- firefox-90.0/third_party/python/voluptuous/voluptuous-0.12.1.dist-info/RECORD.build-python-2 2021-07-21 09:42:47.774128166 +0200
+++ firefox-90.0/third_party/python/voluptuous/voluptuous-0.12.1.dist-info/RECORD 2021-07-21 09:42:47.774128166 +0200
@@ -0,0 +1,11 @@
+voluptuous/__init__.py,sha256=tSYWPAIWee6YwcMK8hxmaiagG_swokUMeH8MluJLWZM,203
+voluptuous/error.py,sha256=fLRmJwKp0bqRGgBM34ztg9MTxhEOf465sbQcvJlEtAk,4026
+voluptuous/humanize.py,sha256=hZlhdN4aVeGDIXdtSTeyEbmku65SDPRuut3mOfuRQP0,1606
+voluptuous/schema_builder.py,sha256=xVJpf3uJMyS1CKwzDw3rEK39ebqDiF_A2Kbq4VnZ3Aw,43677
+voluptuous/util.py,sha256=RXLZ2b5y-A4az3teG6UpCx2UZcXpS11sIVCdORyKar8,3150
+voluptuous/validators.py,sha256=xZgyKH-EVqUHCHral5gzViXq4HfEjJEsGdQy7z6llc0,32798
+voluptuous-0.12.1.dist-info/COPYING,sha256=JHtJdren-k2J2Vh8qlCVVh60bcVFfyJ59ipitUUq3qk,1486
+voluptuous-0.12.1.dist-info/METADATA,sha256=OdEydy5NydPFFzAhP8qj_YqJsQPQvoIt5ZT1t8B14Ok,20120
+voluptuous-0.12.1.dist-info/WHEEL,sha256=S6zePDbUAjzMmpYOg2cHDxuYFWw7WiOXt6ogM6hIB5Q,92
+voluptuous-0.12.1.dist-info/top_level.txt,sha256=TTdVb7M-vndb67UqTmAxuVjpAUakrlAWJYqvo3w4Iqc,11
+voluptuous-0.12.1.dist-info/RECORD,,
diff -up firefox-90.0/third_party/python/voluptuous/voluptuous/error.py.build-python-2 firefox-90.0/third_party/python/voluptuous/voluptuous/error.py
--- firefox-90.0/third_party/python/voluptuous/voluptuous/error.py.build-python-2 2021-07-05 21:16:03.000000000 +0200
+++ firefox-90.0/third_party/python/voluptuous/voluptuous/error.py 2021-07-21 09:42:47.775128197 +0200
@@ -142,11 +142,11 @@ class BooleanInvalid(Invalid):
class UrlInvalid(Invalid):
- """The value is not a url."""
+ """The value is not a URL."""
class EmailInvalid(Invalid):
- """The value is not a email."""
+ """The value is not an email address."""
class FileInvalid(Invalid):
diff -up firefox-90.0/third_party/python/voluptuous/voluptuous/__init__.py.build-python-2 firefox-90.0/third_party/python/voluptuous/voluptuous/__init__.py
--- firefox-90.0/third_party/python/voluptuous/voluptuous/__init__.py.build-python-2 2021-07-05 21:16:03.000000000 +0200
+++ firefox-90.0/third_party/python/voluptuous/voluptuous/__init__.py 2021-07-21 09:42:47.775128197 +0200
@@ -5,5 +5,5 @@ from voluptuous.validators import *
from voluptuous.util import *
from voluptuous.error import *
-__version__ = '0.11.5'
+__version__ = '0.12.1'
__author__ = 'alecthomas'
diff -up firefox-90.0/third_party/python/voluptuous/voluptuous/schema_builder.py.build-python-2 firefox-90.0/third_party/python/voluptuous/voluptuous/schema_builder.py
--- firefox-90.0/third_party/python/voluptuous/voluptuous/schema_builder.py.build-python-2 2021-07-05 21:16:03.000000000 +0200
+++ firefox-90.0/third_party/python/voluptuous/voluptuous/schema_builder.py 2021-07-21 09:42:47.775128197 +0200
@@ -22,6 +22,11 @@ else:
def iteritems(d):
return d.iteritems()
+if sys.version_info >= (3, 3):
+ _Mapping = collections.abc.Mapping
+else:
+ _Mapping = collections.Mapping
+
"""Schema validation for Python data structures.
Given eg. a nested data structure like this:
@@ -280,7 +285,7 @@ class Schema(object):
return schema.__voluptuous_compile__(self)
if isinstance(schema, Object):
return self._compile_object(schema)
- if isinstance(schema, collections.Mapping):
+ if isinstance(schema, _Mapping):
return self._compile_dict(schema)
elif isinstance(schema, list):
return self._compile_list(schema)
@@ -610,11 +615,11 @@ class Schema(object):
if not isinstance(data, seq_type):
raise er.SequenceTypeInvalid('expected a %s' % seq_type_name, path)
- # Empty seq schema, allow any data.
+ # Empty seq schema, reject any data.
if not schema:
if data:
raise er.MultipleInvalid([
- er.ValueInvalid('not a valid value', [value]) for value in data
+ er.ValueInvalid('not a valid value', path if path else data)
])
return data
@@ -735,7 +740,7 @@ class Schema(object):
result = self.schema.copy()
- # returns the key that may have been passed as arugment to Marker constructor
+ # returns the key that may have been passed as an argument to Marker constructor
def key_literal(key):
return (key.schema if isinstance(key, Marker) else key)
@@ -771,9 +776,10 @@ class Schema(object):
result[key] = value
# recompile and send old object
+ result_cls = type(self)
result_required = (required if required is not None else self.required)
result_extra = (extra if extra is not None else self.extra)
- return Schema(result, required=result_required, extra=result_extra)
+ return result_cls(result, required=result_required, extra=result_extra)
def _compile_scalar(schema):
@@ -809,7 +815,7 @@ def _compile_scalar(schema):
def validate_callable(path, data):
try:
return schema(data)
- except ValueError as e:
+ except ValueError:
raise er.ValueInvalid('not a valid value', path)
except er.Invalid as e:
e.prepend(path)
@@ -1121,8 +1127,11 @@ class Inclusive(Optional):
True
"""
- def __init__(self, schema, group_of_inclusion, msg=None):
- super(Inclusive, self).__init__(schema, msg=msg)
+ def __init__(self, schema, group_of_inclusion,
+ msg=None, description=None, default=UNDEFINED):
+ super(Inclusive, self).__init__(schema, msg=msg,
+ default=default,
+ description=description)
self.group_of_inclusion = group_of_inclusion
diff -up firefox-90.0/third_party/python/voluptuous/voluptuous/util.py.build-python-2 firefox-90.0/third_party/python/voluptuous/voluptuous/util.py
--- firefox-90.0/third_party/python/voluptuous/voluptuous/util.py.build-python-2 2021-07-05 21:16:03.000000000 +0200
+++ firefox-90.0/third_party/python/voluptuous/voluptuous/util.py 2021-07-21 09:42:47.776128229 +0200
@@ -7,6 +7,14 @@ from voluptuous import validators
__author__ = 'tusharmakkar08'
+def _fix_str(v):
+ if sys.version_info[0] == 2 and isinstance(v, unicode):
+ s = v
+ else:
+ s = str(v)
+ return s
+
+
def Lower(v):
"""Transform a string to lower case.
@@ -14,7 +22,7 @@ def Lower(v):
>>> s('HI')
'hi'
"""
- return str(v).lower()
+ return _fix_str(v).lower()
def Upper(v):
@@ -24,7 +32,7 @@ def Upper(v):
>>> s('hi')
'HI'
"""
- return str(v).upper()
+ return _fix_str(v).upper()
def Capitalize(v):
@@ -34,7 +42,7 @@ def Capitalize(v):
>>> s('hello world')
'Hello world'
"""
- return str(v).capitalize()
+ return _fix_str(v).capitalize()
def Title(v):
@@ -44,7 +52,7 @@ def Title(v):
>>> s('hello world')
'Hello World'
"""
- return str(v).title()
+ return _fix_str(v).title()
def Strip(v):
@@ -54,7 +62,7 @@ def Strip(v):
>>> s(' hello world ')
'hello world'
"""
- return str(v).strip()
+ return _fix_str(v).strip()
class DefaultTo(object):
diff -up firefox-90.0/third_party/python/voluptuous/voluptuous/validators.py.build-python-2 firefox-90.0/third_party/python/voluptuous/voluptuous/validators.py
--- firefox-90.0/third_party/python/voluptuous/voluptuous/validators.py.build-python-2 2021-07-05 21:16:03.000000000 +0200
+++ firefox-90.0/third_party/python/voluptuous/voluptuous/validators.py 2021-07-21 09:42:47.776128229 +0200
@@ -192,15 +192,26 @@ class _WithSubValidators(object):
def __init__(self, *validators, **kwargs):
self.validators = validators
self.msg = kwargs.pop('msg', None)
+ self.required = kwargs.pop('required', False)
+ self.discriminant = kwargs.pop('discriminant', None)
def __voluptuous_compile__(self, schema):
- self._compiled = [
- schema._compile(v)
- for v in self.validators
- ]
+ self._compiled = []
+ old_required = schema.required
+ self.schema = schema
+ for v in self.validators:
+ schema.required = self.required
+ self._compiled.append(schema._compile(v))
+ schema.required = old_required
return self._run
def _run(self, path, value):
+ if self.discriminant is not None:
+ self._compiled = [
+ self.schema._compile(v)
+ for v in self.discriminant(value, self.validators)
+ ]
+
return self._exec(self._compiled, value, path)
def __call__(self, v):
@@ -218,7 +229,7 @@ class Any(_WithSubValidators):
"""Use the first validated value.
:param msg: Message to deliver to user if validation fails.
- :param kwargs: All other keyword arguments are passed to the sub-Schema constructors.
+ :param kwargs: All other keyword arguments are passed to the sub-schema constructors.
:returns: Return value of the first validator that passes.
>>> validate = Schema(Any('true', 'false',
@@ -262,13 +273,57 @@ class Any(_WithSubValidators):
Or = Any
+class Union(_WithSubValidators):
+ """Use the first validated value among those selected by discriminant.
+
+ :param msg: Message to deliver to user if validation fails.
+ :param discriminant(value, validators): Returns the filtered list of validators based on the value.
+ :param kwargs: All other keyword arguments are passed to the sub-schema constructors.
+ :returns: Return value of the first validator that passes.
+
+ >>> validate = Schema(Union({'type':'a', 'a_val':'1'},{'type':'b', 'b_val':'2'},
+ ... discriminant=lambda val, alt: filter(
+ ... lambda v : v['type'] == val['type'] , alt)))
+ >>> validate({'type':'a', 'a_val':'1'}) == {'type':'a', 'a_val':'1'}
+ True
+ >>> with raises(MultipleInvalid, "not a valid value for dictionary value @ data['b_val']"):
+ ... validate({'type':'b', 'b_val':'5'})
+
+ ```discriminant({'type':'b', 'a_val':'5'}, [{'type':'a', 'a_val':'1'},{'type':'b', 'b_val':'2'}])``` is invoked
+
+ Without the discriminant, the exception would be "extra keys not allowed @ data['b_val']"
+ """
+
+ def _exec(self, funcs, v, path=None):
+ error = None
+ for func in funcs:
+ try:
+ if path is None:
+ return func(v)
+ else:
+ return func(path, v)
+ except Invalid as e:
+ if error is None or len(e.path) > len(error.path):
+ error = e
+ else:
+ if error:
+ raise error if self.msg is None else AnyInvalid(
+ self.msg, path=path)
+ raise AnyInvalid(self.msg or 'no valid value found',
+ path=path)
+
+
+# Convenience alias
+Switch = Union
+
+
class All(_WithSubValidators):
"""Value must pass all validators.
The output of each validator is passed as input to the next.
:param msg: Message to deliver to user if validation fails.
- :param kwargs: All other keyword arguments are passed to the sub-Schema constructors.
+ :param kwargs: All other keyword arguments are passed to the sub-schema constructors.
>>> validate = Schema(All('10', Coerce(int)))
>>> validate('10')
@@ -303,7 +358,7 @@ class Match(object):
>>> with raises(MultipleInvalid, 'expected string or buffer'):
... validate(123)
- Pattern may also be a _compiled regular expression:
+ Pattern may also be a compiled regular expression:
>>> validate = Schema(Match(re.compile(r'0x[A-F0-9]+', re.I)))
>>> validate('0x123ef4')
@@ -361,38 +416,38 @@ def _url_validation(v):
return parsed
-@message('expected an Email', cls=EmailInvalid)
+@message('expected an email address', cls=EmailInvalid)
def Email(v):
- """Verify that the value is an Email or not.
+ """Verify that the value is an email address or not.
>>> s = Schema(Email())
- >>> with raises(MultipleInvalid, 'expected an Email'):
+ >>> with raises(MultipleInvalid, 'expected an email address'):
... s("a.com")
- >>> with raises(MultipleInvalid, 'expected an Email'):
+ >>> with raises(MultipleInvalid, 'expected an email address'):
... s("a@.com")
- >>> with raises(MultipleInvalid, 'expected an Email'):
+ >>> with raises(MultipleInvalid, 'expected an email address'):
... s("a@.com")
>>> s('t@x.com')
't@x.com'
"""
try:
if not v or "@" not in v:
- raise EmailInvalid("Invalid Email")
+ raise EmailInvalid("Invalid email address")
user_part, domain_part = v.rsplit('@', 1)
if not (USER_REGEX.match(user_part) and DOMAIN_REGEX.match(domain_part)):
- raise EmailInvalid("Invalid Email")
+ raise EmailInvalid("Invalid email address")
return v
except:
raise ValueError
-@message('expected a Fully qualified domain name URL', cls=UrlInvalid)
+@message('expected a fully qualified domain name URL', cls=UrlInvalid)
def FqdnUrl(v):
- """Verify that the value is a Fully qualified domain name URL.
+ """Verify that the value is a fully qualified domain name URL.
>>> s = Schema(FqdnUrl())
- >>> with raises(MultipleInvalid, 'expected a Fully qualified domain name URL'):
+ >>> with raises(MultipleInvalid, 'expected a fully qualified domain name URL'):
... s("http://localhost/")
>>> s('http://w3.org')
'http://w3.org'
@@ -423,14 +478,14 @@ def Url(v):
raise ValueError
-@message('not a file', cls=FileInvalid)
+@message('Not a file', cls=FileInvalid)
@truth
def IsFile(v):
"""Verify the file exists.
>>> os.path.basename(IsFile()(__file__)).startswith('validators.py')
True
- >>> with raises(FileInvalid, 'not a file'):
+ >>> with raises(FileInvalid, 'Not a file'):
... IsFile()("random_filename_goes_here.py")
>>> with raises(FileInvalid, 'Not a file'):
... IsFile()(None)
@@ -445,7 +500,7 @@ def IsFile(v):
raise FileInvalid('Not a file')
-@message('not a directory', cls=DirInvalid)
+@message('Not a directory', cls=DirInvalid)
@truth
def IsDir(v):
"""Verify the directory exists.
@@ -487,11 +542,11 @@ def PathExists(v):
raise PathInvalid("Not a Path")
-def Maybe(validator):
+def Maybe(validator, msg=None):
"""Validate that the object matches given validator or is None.
- :raises Invalid: if the value does not match the given validator and is not
- None
+ :raises Invalid: If the value does not match the given validator and is not
+ None.
>>> s = Schema(Maybe(int))
>>> s(10)
@@ -500,7 +555,7 @@ def Maybe(validator):
... s("string")
"""
- return Any(None, validator)
+ return Any(validator, None, msg=msg)
class Range(object):
@@ -533,23 +588,30 @@ class Range(object):
self.msg = msg
def __call__(self, v):
- if self.min_included:
- if self.min is not None and not v >= self.min:
- raise RangeInvalid(
- self.msg or 'value must be at least %s' % self.min)
- else:
- if self.min is not None and not v > self.min:
- raise RangeInvalid(
- self.msg or 'value must be higher than %s' % self.min)
- if self.max_included:
- if self.max is not None and not v <= self.max:
- raise RangeInvalid(
- self.msg or 'value must be at most %s' % self.max)
- else:
- if self.max is not None and not v < self.max:
- raise RangeInvalid(
- self.msg or 'value must be lower than %s' % self.max)
- return v
+ try:
+ if self.min_included:
+ if self.min is not None and not v >= self.min:
+ raise RangeInvalid(
+ self.msg or 'value must be at least %s' % self.min)
+ else:
+ if self.min is not None and not v > self.min:
+ raise RangeInvalid(
+ self.msg or 'value must be higher than %s' % self.min)
+ if self.max_included:
+ if self.max is not None and not v <= self.max:
+ raise RangeInvalid(
+ self.msg or 'value must be at most %s' % self.max)
+ else:
+ if self.max is not None and not v < self.max:
+ raise RangeInvalid(
+ self.msg or 'value must be lower than %s' % self.max)
+
+ return v
+
+ # Objects that lack a partial ordering, e.g. None or strings will raise TypeError
+ except TypeError:
+ raise RangeInvalid(
+ self.msg or 'invalid value or type (must have a partial ordering)')
def __repr__(self):
return ('Range(min=%r, max=%r, min_included=%r,'
@@ -579,11 +641,17 @@ class Clamp(object):
self.msg = msg
def __call__(self, v):
- if self.min is not None and v < self.min:
- v = self.min
- if self.max is not None and v > self.max:
- v = self.max
- return v
+ try:
+ if self.min is not None and v < self.min:
+ v = self.min
+ if self.max is not None and v > self.max:
+ v = self.max
+ return v
+
+ # Objects that lack a partial ordering, e.g. None or strings will raise TypeError
+ except TypeError:
+ raise RangeInvalid(
+ self.msg or 'invalid value or type (must have a partial ordering)')
def __repr__(self):
return 'Clamp(min=%s, max=%s)' % (self.min, self.max)
@@ -598,13 +666,19 @@ class Length(object):
self.msg = msg
def __call__(self, v):
- if self.min is not None and len(v) < self.min:
- raise LengthInvalid(
- self.msg or 'length of value must be at least %s' % self.min)
- if self.max is not None and len(v) > self.max:
- raise LengthInvalid(
- self.msg or 'length of value must be at most %s' % self.max)
- return v
+ try:
+ if self.min is not None and len(v) < self.min:
+ raise LengthInvalid(
+ self.msg or 'length of value must be at least %s' % self.min)
+ if self.max is not None and len(v) > self.max:
+ raise LengthInvalid(
+ self.msg or 'length of value must be at most %s' % self.max)
+ return v
+
+ # Objects that havbe no length e.g. None or strings will raise TypeError
+ except TypeError:
+ raise RangeInvalid(
+ self.msg or 'invalid value or type')
def __repr__(self):
return 'Length(min=%s, max=%s)' % (self.min, self.max)
@@ -663,7 +737,8 @@ class In(object):
except TypeError:
check = True
if check:
- raise InInvalid(self.msg or 'value is not allowed')
+ raise InInvalid(self.msg or
+ 'value must be one of {}'.format(sorted(self.container)))
return v
def __repr__(self):
@@ -683,7 +758,8 @@ class NotIn(object):
except TypeError:
check = True
if check:
- raise NotInInvalid(self.msg or 'value is not allowed')
+ raise NotInInvalid(self.msg or
+ 'value must not be one of {}'.format(sorted(self.container)))
return v
def __repr__(self):
@@ -722,7 +798,7 @@ class ExactSequence(object):
the validators.
:param msg: Message to deliver to user if validation fails.
- :param kwargs: All other keyword arguments are passed to the sub-Schema
+ :param kwargs: All other keyword arguments are passed to the sub-schema
constructors.
>>> from voluptuous import Schema, ExactSequence
@@ -887,7 +963,7 @@ class Unordered(object):
class Number(object):
"""
Verify the number of digits that are present in the number(Precision),
- and the decimal places(Scale)
+ and the decimal places(Scale).
:raises Invalid: If the value does not match the provided Precision and Scale.
@@ -951,13 +1027,13 @@ class SomeOf(_WithSubValidators):
The output of each validator is passed as input to the next.
:param min_valid: Minimum number of valid schemas.
- :param validators: a list of schemas or validators to match input against
+ :param validators: List of schemas or validators to match input against.
:param max_valid: Maximum number of valid schemas.
:param msg: Message to deliver to user if validation fails.
- :param kwargs: All other keyword arguments are passed to the sub-Schema constructors.
+ :param kwargs: All other keyword arguments are passed to the sub-schema constructors.
- :raises NotEnoughValid: if the minimum number of validations isn't met
- :raises TooManyValid: if the more validations than the given amount is met
+ :raises NotEnoughValid: If the minimum number of validations isn't met.
+ :raises TooManyValid: If the maximum number of validations is exceeded.
>>> validate = Schema(SomeOf(min_valid=2, validators=[Range(1, 5), Any(float, int), 6.6]))
>>> validate(6.6)