Skip to content
Back to top
View this page
Edit this page

# Validation schemas

Please see the validation schema guides for an introduction to this API and a list of examples.

Public interface

While the internals are implemented in the `streamlink.validate` package, streamlink.plugin.api.validate provides the main public interface for plugin implementors.

class streamlink.plugin.api.validate.Schema(*schemas)

  Bases: `AllSchema`

  The base class for creating validation schemas.

  A wrapper for `AllSchema` with a wrapper method for `validate()` which by default raises `PluginError` on error.

  validate(value, name='result', exception=<class 'streamlink.exceptions.PluginError'>)
    Parameters:

      - value (Any)

      - name (str)

      - exception (type[Exception])

    Return type:

      Any

streamlink.plugin.api.validate.validate(schema, value)

  The core of the `streamlink.plugin.api.validate` module.

  It validates the given input `value` and returns a value according to the specific validation rules of the `schema`.

  If the validation fails, a `ValidationError` is raised with a detailed error message.

  The `schema` can be any kind of object. Depending on the `schema`, different validation rules apply.

  Simple schema objects like `"abc"` or `123` for example test the equality of `value` and `schema` and return `value` again, while type schema objects like `str` test whether `value` is an instance of `schema`. `schema` objects which are callable receive `value` as a single argument and must return a truthy value, otherwise the validation fails. These are just a few examples.

  The `validate` module implements lots of special schemas, like `validate.all` or `validate.any` for example, which are schema containers that receive a sequence of sub-schemas as arguments and where each sub-schema then gets validated one after another.

  `validate.all` requires each sub-schema to successfully validate. It passes the return value of each sub-schema to the next one and then returns the return value of the last sub-schema.

  `validate.any` on the other hand requires at least one sub-schema to be valid and returns the return value of the first valid sub-schema. Any validation failures prior will be ignored, but at least one must succeed.

  Other special `schema` cases for example are instances of sequences like `list` or `tuple`, or mappings like `dict`. Here, each sequence item or key-value mapping pair is validated against the input `value` and a new sequence/mapping object according to the `schema` validation is returned.

  `validate()` should usually not be called directly when validating schemas. Instead, the wrapper method `Schema.validate()` of the main `Schema` class should be called. Other Streamlink APIs like the methods of the `HTTPSession` or the various `streamlink.utils.parse` functions for example expect this interface when the `schema` keyword is set, which allows for immediate validation of the data using a `Schema` object.

  `validate()` is implemented using the stdlib's `functools.singledispatch()` decorator, where more specific schemas overload the default implementation with more validation logic.

  By default, `validate()` compares `value` and `schema` for equality. This means that simple schema objects like booleans, strings, numbers, None, etc. are validated here, as well as anything unknown.

  Example:

      schema = validate.Schema(123)
      assert schema.validate(123) == 123
      assert schema.validate(123.0) == 123.0
      schema.validate(456)  # raises ValidationError
      schema.validate(None)  # raises ValidationError

  Parameters:

    - schema (Any) -- Any kind of object not handled by a more specific validation function

    - value (Any) -- The input value

  Raises:

    ValidationError -- If `value` and `schema` are not equal

  Returns:

    Unmodified `value`

streamlink.plugin.api.validate._validate_type(schema, value)

  `type` validation.

  Checks if `value` is an instance of `schema`.

  Example:

      schema = validate.Schema(int)
      assert schema.validate(123) == 123
      assert schema.validate(True) is True  # `bool` is a subclass of `int`
      schema.validate("123")  # raises ValidationError

  This function is included for documentation purposes only! (singledispatch overload)

  Parameters:

    - schema (type) -- A `type` object

    - value (Any) -- The input value

  Raises:

    ValidationError -- If `value` is not an instance of `schema`

  Returns:

    Unmodified `value`

streamlink.plugin.api.validate._validate_callable(schema, value)

  `Callable` validation.

  Validates a `schema` function where `value` gets passed as a single argument.

  Must return a truthy value.

  Example:

      schema = validate.Schema(
          lambda val: val < 2,
      )
      assert schema.validate(1) == 1
      schema.validate(2)  # raises ValidationError

  This function is included for documentation purposes only! (singledispatch overload)

  Parameters:

    - schema (Callable) -- A function with one argument

    - value (Any) -- The input value

  Raises:

    ValidationError -- If `schema` returns a non-truthy value

  Returns:

    Unmodified `value`

streamlink.plugin.api.validate._validate_sequence(schema, value)

  `list`, `tuple`, `set` and `frozenset` validation.

  Each item of `value` gets validated against any of the items of `schema`.

  Please note the difference between `list` and the `ListSchema` validation.

  Example:

      schema = validate.Schema([1, 2, 3])
      assert schema.validate([]) == []
      assert schema.validate([1, 2]) == [1, 2]
      assert schema.validate([3, 2, 1]) == [3, 2, 1]
      schema.validate({1, 2, 3})  # raises ValidationError
      schema.validate([1, 2, 3, 4])  # raises ValidationError

  This function is included for documentation purposes only! (singledispatch overload)

  Parameters:

    - schema (Union[list, tuple, set, frozenset]) -- A sequence of validation schemas

    - value (Any) -- The input value

  Raises:

    ValidationError -- If `value` is not an instance of the `schema`'s own type

  Returns:

    A new sequence of the same type as `schema` with each item of `value` being validated

streamlink.plugin.api.validate._validate_dict(schema, value)

  `dict` validation.

  Each key-value pair of `schema` gets validated against the respective key-value pair of `value`.

  Additional keys in `value` are ignored and not included in the validation result.

  If a `schema` key is an instance of `OptionalSchema`, then `value` may omit it.

  If one of the `schema`'s keys is a `type`, `AllSchema`, `AnySchema`, `TransformSchema`, or `UnionSchema`, then all key-value pairs of `value` are validated against the `schema`'s key-value pair.

  Example:

      schema = validate.Schema({
          "key": str,
          validate.optional("opt"): 123,
      })
      assert schema.validate({"key": "val", "other": 123}) == {"key": "val"}
      assert schema.validate({"key": "val", "opt": 123}) == {"key": "val", "opt": 123}
      schema.validate(None)  # raises ValidationError
      schema.validate({})  # raises ValidationError
      schema.validate({"key": 123})  # raises ValidationError
      schema.validate({"key": "val", "opt": 456})  # raises ValidationError

      schema = validate.Schema({
          validate.any("a", "b"): int,
      })
      assert schema.validate({}) == {}
      assert schema.validate({"a": 1}) == {"a": 1}
      assert schema.validate({"b": 2}) == {"b": 2}
      assert schema.validate({"a": 1, "b": 2}) == {"a": 1, "b": 2}
      schema.validate({"a": 1, "b": 2, "other": 0})  # raises ValidationError
      schema.validate({"a": None})  # raises ValidationError

  This function is included for documentation purposes only! (singledispatch overload)

  Parameters:

    - schema (dict) -- A `dict`

    - value (Any) -- The input value

  Raises:

    - ValidationError -- If `value` is not a `dict`

    - ValidationError -- If any of the `schema`'s non-optional keys are not part of the input `value`

  Returns:

    A new `dict`

streamlink.plugin.api.validate._validate_pattern(schema, value)

  `re.Pattern` validation.

  Calls the `re.Pattern.search()` method on the `schema` pattern.

  Please note the difference between `re.Pattern` and the `RegexSchema` validation.

  Example:

      schema = validate.Schema(
          re.compile(r"^Hello, (?P<name>\w+)!$"),
      )
      assert schema.validate("Does not match") is None
      assert schema.validate("Hello, world!")["name"] == "world"
      schema.validate(123)  # raises ValidationError
      schema.validate(b"Hello, world!")  # raises ValidationError

  This function is included for documentation purposes only! (singledispatch overload)

  Parameters:

    - schema (re.Pattern) -- A compiled `re.Pattern` object (`re.compile()` return value)

    - value (Any) -- The input value

  Raises:

    - ValidationError -- If `value` is not an instance of `str` or `bytes`

    - ValidationError -- If the type of `value` doesn't match `schema`'s `str`/`bytes` type

  Returns:

    `None` if `value` doesn't match `schema`, or the resulting `re.Match` object

streamlink.plugin.api.validate.all

  alias of `AllSchema`

streamlink.plugin.api.validate.any

  alias of `AnySchema`

streamlink.plugin.api.validate.attr

  alias of `AttrSchema`

streamlink.plugin.api.validate.contains(obj)

  Utility function for checking whether the input contains a certain element, e.g. a string within a string, an object in a list, a key in a dict, etc.

  Example:

      schema = validate.Schema(
          validate.contains("456"),
      )
      assert schema.validate("123456789") == "123456789"
      schema.validate("987654321")  # raises ValidationError
      schema.validate(None)  # raises ValidationError

      schema = validate.Schema(
          validate.contains(456),
      )
      assert schema.validate([123, 456, 789]) == [123, 456, 789]
      schema.validate([987, 654, 321])  # raises ValidationError
      schema.validate(None)  # raises ValidationError

  Raises:

    - ValidationError -- If input is not an instance of `collections.abc.Container`

    - ValidationError -- If input doesn't contain `obj`

  Parameters:

    obj (object)

  Return type:

    Callable[[Container], bool]

streamlink.plugin.api.validate.endswith(string)

  Utility function for checking whether the input string ends with another string.

  Example:

      schema = validate.Schema(
          validate.endswith("3"),
      )
      assert schema.validate("123") == "123"
      schema.validate("321")  # raises ValidationError
      schema.validate(None)  # raises ValidationError

  Raises:

    - ValidationError -- If input is not an instance of `str`

    - ValidationError -- If input doesn't end with `string`

  Parameters:

    string (str)

  Return type:

    Callable[[str], bool]

streamlink.plugin.api.validate.filter(func)

  Utility function for filtering out unwanted items from the input using the specified function via the built-in `filter()`.

  Supports iterables, as well as instances of `dict` where key-value pairs are expanded.

  Example:

      schema = validate.Schema(
          validate.filter(lambda val: val < 3),
      )
      assert schema.validate([1, 2, 3, 4]) == [1, 2]

      schema = validate.Schema(
          validate.filter(lambda key, val: key > 1 and val < 3),
      )
      assert schema.validate({0: 0, 1: 1, 2: 2, 3: 3, 4: 4}) == {2: 2}

  Parameters:

    func (Callable[..., bool])

  Return type:

    TransformSchema

streamlink.plugin.api.validate.get

  alias of `GetItemSchema`

streamlink.plugin.api.validate.getattr(attr, default=None)

  Utility function for getting an attribute from the input object.

  If a default is set, it is returned when the attribute doesn't exist.

  Example:

      schema = validate.Schema(
          validate.getattr("year", "unknown"),
      )
      assert schema.validate(datetime.date.fromisoformat("2000-01-01")) == 2000
      assert schema.validate("not a date/datetime object") == "unknown"

  Parameters:

    - attr (Any)

    - default (Any)

  Return type:

    TransformSchema

streamlink.plugin.api.validate.hasattr(attr)

  Utility function for checking whether an attribute exists on the input object.

  Example:

      schema = validate.Schema(
          validate.hasattr("year"),
      )
      date = datetime.date.fromisoformat("2000-01-01")
      assert schema.validate(date) is date
      schema.validate("not a date/datetime object")  # raises ValidationError

  Parameters:

    attr (Any)

  Return type:

    Callable[[Any], bool]

streamlink.plugin.api.validate.length(number, op='ge')

  Utility function for checking whether the input has a certain length, by using `len()`. Checks the minimum length by default (`op="ge"`).

  Example:

      schema = validate.Schema(
          validate.length(3),
      )
      assert schema.validate("abc") == "abc"
      assert schema.validate([1, 2, 3, 4]) == [1, 2, 3, 4]
      schema.validate("a")  # raises ValidationError
      schema.validate([1])  # raises ValidationError

      schema = validate.Schema(
          validate.length(3, op="lt"),
      )
      assert schema.validate("ab") == "ab"
      schema.validate([1, 2, 3])  # raises ValidationError

  Parameters:

    - number (int)

    - op (Literal['lt', 'le', 'eq', 'ge', 'gt'])

  Return type:

    Callable[[str], bool]

streamlink.plugin.api.validate.list

  alias of `ListSchema`

streamlink.plugin.api.validate.map(func)

  Utility function for mapping/transforming items from the input using the specified function, via the built-in `map()`.

  Supports iterables, as well as instances of `dict` where key-value pairs are expanded.

  Example:

      schema = validate.Schema(
          validate.map(lambda val: val + 1),
      )
      assert schema.validate([1, 2, 3, 4]) == [2, 3, 4, 5]

      schema = validate.Schema(
          validate.map(lambda key, val: (key + 1, val * 2)),
      )
      assert schema.validate({0: 0, 1: 1, 2: 2, 3: 3, 4: 4}) == {1: 0, 2: 2, 3: 4, 4: 6, 5: 8}

  Parameters:

    func (Callable[..., Any])

  Return type:

    TransformSchema

streamlink.plugin.api.validate.none_or_all

  alias of `NoneOrAllSchema`

streamlink.plugin.api.validate.optional

  alias of `OptionalSchema`

streamlink.plugin.api.validate.parse_html(*args, **kwargs)

  Utility function for parsing HTML data using `streamlink.utils.parse.parse_html()`.

  Example:

      schema = validate.Schema(
          validate.parse_html(),
      )
      assert schema.validate("""<html lang="en">""").attrib["lang"] == "en"
      schema.validate(123)  # raises ValidationError

  Raises:

    ValidationError -- On parsing error

  Return type:

    TransformSchema

streamlink.plugin.api.validate.parse_json(*args, **kwargs)

  Utility function for parsing JSON data using `streamlink.utils.parse.parse_json()`.

  Example:

      schema = validate.Schema(
          validate.parse_json(),
      )
      assert schema.validate("""{"a":[1,2,3],"b":null}""") == {"a": [1, 2, 3], "b": None}
      schema.validate(123)  # raises ValidationError

  Raises:

    ValidationError -- On parsing error

  Return type:

    TransformSchema

streamlink.plugin.api.validate.parse_qsd(*args, **kwargs)

  Utility function for parsing a query string using `streamlink.utils.parse.parse_qsd()`.

  Example:

      schema = validate.Schema(
          validate.parse_qsd(),
      )
      assert schema.validate("a=b&a=c&foo=bar") == {"a": "c", "foo": "bar"}
      schema.validate(123)  # raises ValidationError

  Raises:

    ValidationError -- On parsing error

  Return type:

    TransformSchema

streamlink.plugin.api.validate.parse_xml(*args, **kwargs)

  Utility function for parsing XML data using `streamlink.utils.parse.parse_xml()`.

  Example:

      schema = validate.Schema(
          validate.parse_xml(),
      )
      assert schema.validate("""<a b="c"/>""").attrib["b"] == "c"
      schema.validate(123)  # raises ValidationError

  Raises:

    ValidationError -- On parsing error

  Return type:

    TransformSchema

streamlink.plugin.api.validate.regex

  alias of `RegexSchema`

streamlink.plugin.api.validate.startswith(string)

  Utility function for checking whether the input string starts with another string.

  Example:

      schema = validate.Schema(
          validate.startswith("1"),
      )
      assert schema.validate("123") == "123"
      schema.validate("321")  # raises ValidationError
      schema.validate(None)  # raises ValidationError

  Raises:

    - ValidationError -- If input is not an instance of `str`

    - ValidationError -- If input doesn't start with `string`

  Parameters:

    string (str)

  Return type:

    Callable[[str], bool]

streamlink.plugin.api.validate.transform

  alias of `TransformSchema`

streamlink.plugin.api.validate.union

  alias of `UnionSchema`

streamlink.plugin.api.validate.union_get

  alias of `UnionGetSchema`

streamlink.plugin.api.validate.url(**attributes)

  Utility function for validating a URL using schemas.

  Allows validating all URL attributes returned by `urllib.parse.urlparse()`:

  - `scheme` - updated to `AnySchema("http", "https")` if set to `"http"`

  - `netloc`

  - `path`

  - `params`

  - `query`

  - `fragment`

  - `username`

  - `password`

  - `hostname`

  - `port`

  Example:

      schema = validate.Schema(
          validate.url(path=validate.endswith(".m3u8")),
      )
      assert schema.validate("https://host/pl.m3u8?query") == "https://host/pl.m3u8?query"
      schema.validate(None)  # raises ValidationError
      schema.validate("not a URL")  # raises ValidationError
      schema.validate("https://host/no-pl?pl.m3u8")  # raises ValidationError

  Raises:

    - ValidationError -- If input is not a string

    - ValidationError -- If input is not a URL (doesn't have a `netloc` parsing result)

    - ValidationError -- If an unknown URL attribute is passed as an option

  Return type:

    Callable[[str], bool]

streamlink.plugin.api.validate.xml_element

  alias of `XmlElementSchema`

streamlink.plugin.api.validate.xml_find(path, namespaces=None)

  Utility function for finding an XML element using `Element.find()`.

  This method uses the ElementPath query language, which is a subset of XPath.

  Example:

      schema = validate.Schema(
          validate.xml_find(".//b/c"),
      )
      assert schema.validate(lxml.etree.XML("<a><b><c>d</c></b></a>")).text == "d"
      schema.validate(lxml.etree.XML("<a><b></b></a>"))  # raises ValidationError
      schema.validate("<a><b><c>d</c></b></a>")  # raises ValidationError

  Raises:

    - ValidationError -- If the input is not an `lxml.etree.Element`

    - ValidationError -- On ElementPath evaluation error

    - ValidationError -- If the query didn't return an XML element

  Parameters:

    - path (str)

    - namespaces (Mapping[str, str] | None)

  Return type:

    TransformSchema

streamlink.plugin.api.validate.xml_findall(path, namespaces=None)

  Utility function for finding XML elements using `Element.findall()`.

  This method uses the ElementPath query language, which is a subset of XPath.

  Example:

      schema = validate.Schema(
          validate.xml_findall(".//b"),
          validate.map(lambda elem: elem.text),
      )
      assert schema.validate(lxml.etree.XML("<a><b>1</b><b>2</b></a>")) == ["1", "2"]
      assert schema.validate(lxml.etree.XML("<a><c></c></a>")) == []
      schema.validate("<a><b>1</b><b>2</b></a>")  # raises ValidationError

  Raises:

    - ValidationError -- If the input is not an `lxml.etree.Element`

    - ValidationError -- On ElementPath evaluation error

  Parameters:

    - path (str)

    - namespaces (Mapping[str, str] | None)

  Return type:

    TransformSchema

streamlink.plugin.api.validate.xml_findtext(path, namespaces=None)

  Utility function for finding an XML element using `Element.find()` and returning its `text` attribute.

  This method uses the ElementPath query language, which is a subset of XPath.

  Example:

      schema = validate.Schema(
          validate.xml_findtext(".//b/c"),
      )
      assert schema.validate(lxml.etree.XML("<a><b><c>d</c></b></a>")) == "d"
      schema.validate(lxml.etree.XML("<a><b></b></a>"))  # raises ValidationError
      schema.validate("<a><b><c>d</c></b></a>")  # raises ValidationError

  Raises:

    - ValidationError -- If the input is not an `lxml.etree.Element`

    - ValidationError -- On ElementPath evaluation error

    - ValidationError -- If the query didn't return an XML element

  Parameters:

    - path (str)

    - namespaces (Mapping[str, str] | None)

  Return type:

    AllSchema

streamlink.plugin.api.validate.xml_xpath(xpath, namespaces=None, extensions=None, smart_strings=True, **variables)

  Utility function for querying XML elements using XPath (`Element.xpath()`).

  XPath queries always return a result set, but if the result is an empty set, this function instead returns `None`.

  Allows setting XPath variables (`$var`) as additional keywords.

  Example:

      schema = validate.Schema(
          validate.xml_xpath(".//b[@c=$c][1]/@d", c="2"),
      )
      assert schema.validate(lxml.etree.XML("<a><b c='1' d='A'/><b c='2' d='B'/></a>")) == ["B"]
      assert schema.validate(lxml.etree.XML("<a></a>")) is None
      schema.validate("<a><b c='1' d='A'/><b c='2' d='B'/></a>")  # raises ValidationError

  Raises:

    - ValidationError -- If the input is not an `lxml.etree.Element`

    - ValidationError -- On XPath evaluation error

  Parameters:

    - xpath (str)

    - namespaces (Mapping[str, str] | None)

    - extensions (Mapping[tuple[str | None, str], Callable[..., Any]] | None)

    - smart_strings (bool)

  Return type:

    TransformSchema

streamlink.plugin.api.validate.xml_xpath_string(xpath, namespaces=None, extensions=None, **variables)

  Utility function for querying XML elements using XPath (`Element.xpath()`) and turning the result into a string.

  XPath queries always return a result set, so be aware when querying multiple elements. If the result is an empty set, this function instead returns `None`.

  Allows setting XPath variables (`$var`) as additional keywords.

  Example:

      schema = validate.Schema(
          validate.xml_xpath_string(".//b[2]/text()"),
      )
      assert schema.validate(lxml.etree.XML("<a><b>A</b><b>B</b><b>C</b></a>")) == "B"
      assert schema.validate(lxml.etree.XML("<a></a>")) is None
      schema.validate("<a><b>A</b><b>B</b><b>C</b></a>")  # raises ValidationError

  Raises:

    - ValidationError -- If the input is not an `lxml.etree.Element`

    - ValidationError -- On XPath evaluation error

  Parameters:

    - xpath (str)

    - namespaces (Mapping[str, str] | None)

    - extensions (Mapping[tuple[str | None, str], Callable[..., Any]] | None)

  Return type:

    TransformSchema

class streamlink.validate._schemas.AllSchema(*schemas)

  A collection of schemas where each schema must be valid.

  Validates one schema after another with the input value of the return value of the previous one.

  Example:

      # `validate.Schema` is a subclass of `AllSchema` (`validate.all`)
      schema = validate.Schema(
          int,
          validate.transform(lambda val: val + 1),
          lambda val: val < 3,
      )
      assert schema.validate(1) == 2
      schema.validate("a")  # raises ValidationError
      schema.validate(2)  # raises ValidationError

  Parameters:

    *schemas (Any) -- Schemas where each one must be valid

  Returns:

    The return value of the last schema

class streamlink.validate._schemas.AnySchema(*schemas)

  A collection of schemas where at least one schema must be valid.

  Validates one schema after another with the same input value until the first one succeeds.

  Example:

      schema = validate.Schema(
          validate.any(int, float, str),
      )
      assert schema.validate(123) == 123
      assert schema.validate(123.0) == 123.0
      assert schema.validate("123") == "123"
      schema.validate(None)  # raises ValidationError

  Parameters:

    *schemas (Any) -- Schemas where at least one must be valid

  Raises:

    ValidationError -- Error collection of all schema validations if none succeeded

  Returns:

    The return value of the first valid schema

class streamlink.validate._schemas.NoneOrAllSchema(*schemas)

  Similar to `AllSchema`, but skips the validation if the input value is `None`.

  This is useful for optional validation results, e.g. when validating a potential match of a regular expression.

  Example:

      schema = validate.Schema(
          validate.none_or_all(
              int,
              lambda val: val < 2,
          ),
      )
      assert schema.validate(None) is None
      assert schema.validate(1) == 1
      schema.validate("123")  # raises ValidationError
      schema.validate(2)  # raises ValidationError

  Parameters:

    *schemas (Any) -- Schemas where each one must be valid, unless the input is `None`

  Raises:

    ValidationError -- Error wrapper of the failed schema validation

  Returns:

    `None` if the input is `None`, or the return value of the last schema

class streamlink.validate._schemas.TransformSchema(func, *args, **kwargs)

  A transform function which receives the input value as the argument, with optional custom arguments and keywords.

  Example:

      schema = validate.Schema(
          validate.transform(lambda val: val + 1),
          validate.transform(operator.lt, 3),
      )
      assert schema.validate(1) is True
      assert schema.validate(2) is False

  Parameters:

    - func (Callable) -- A transform function

    - *args -- Additional arguments

    - **kwargs -- Additional keywords

  Raises:

    ValidationError -- If the transform function is not callable

  Returns:

    The return value of the transform function

class streamlink.validate._schemas.OptionalSchema(key)

  An optional key set in a `dict`.

  See the `dict` validation and the `UnionSchema`.

  Parameters:

    key (Any)

class streamlink.validate._schemas.ListSchema(*schemas)

  A list of schemas where every item must be valid, as well as the input type and length.

  Please note the difference between `ListSchema` and the `list` validation.

  Example:

      schema = validate.Schema(
          validate.list(1, 2, int),
      )
      assert schema.validate([1, 2, 3]) == [1, 2, 3]
      schema.validate(None)  # raises ValidationError
      schema.validate([1, 2])  # raises ValidationError
      schema.validate([3, 2, 1])  # raises ValidationError

  Parameters:

    *schema (Any) -- Schemas where each one must be valid

  Raises:

    - ValidationError -- If the input is not a `list`

    - ValidationError -- If the input's length is not equal to the number of schemas

  Returns:

    A new `list` with the validated input

class streamlink.validate._schemas.AttrSchema(schema)

  Validate attributes of an input object according to a `dict`'s key-value pairs.

  Example:

      schema = validate.Schema(
          validate.attr({
              "a": str,
              "b": int,
          }),
      )
      assert schema.validate(obj) is not obj
      schema.validate(obj_without_a)  # raises ValidationError
      schema.validate(obj_b_is_str)  # raises ValidationError

  Parameters:

    schema (dict[str, Any]) -- A `dict` with attribute validations

  Raises:

    ValidationError -- If the input doesn't have one of the schema's attributes

  Returns:

    A copy of the input object with validated attributes

class streamlink.validate._schemas.GetItemSchema(item, default=None, strict=False)

  Get an `item` from the input.

  The input can be anything that implements `__getitem__()`, as well as `lxml.etree.Element` objects where element attributes are looked up.

  Returns the `default` value if `item` was not found.

  Unless `strict` is set to `True`, the `item` can be a `tuple` of items for a recursive lookup. In this case, the `default` value is only returned if the leaf-input-object doesn't contain the current `item`.

  Example:

      schema = validate.Schema(
          validate.get("name", default="unknown"),
      )
      assert schema.validate({"name": "user"}) == "user"
      assert schema.validate(re.match(r"Hello, (?P<name>\w+)!", "Hello, user!")) == "user"
      assert schema.validate(lxml.etree.XML("""<elem name="abc"/>""")) == "abc"
      assert schema.validate({}) == "unknown"
      schema.validate(None)  # raises ValidationError

      schema = validate.Schema(
          validate.get(("a", "b", "c")),
      )
      assert schema.validate({"a": {"b": {"c": "d"}}}) == "d"
      assert schema.validate({"a": {"b": {}}}) is None
      schema.validate({"a": {}})  # raises ValidationError

  Parameters:

    - item (Any | tuple) -- The lookup key, or a `tuple` of recursive lookup keys

    - default (Any) -- Optional custom default value

    - strict (bool) -- If `True`, don't perform recursive lookups with the `tuple` item

  Raises:

    - ValidationError -- If the input doesn't implement `__getitem__()`

    - ValidationError -- If the input doesn't have the current `item` in a recursive non-leaf-input-object lookup

  Returns:

    The `__getitem__()` return value, or an `lxml.etree.Element` attribute

class streamlink.validate._schemas.UnionSchema(schema)

  Validate multiple schemas on the same input.

  Example:

      schema = validate.Schema(
          validate.union((
              validate.transform(str.format, one="abc", two="def"),
              validate.transform(str.format, one="123", two="456"),
          )),
      )
      assert schema.validate("{one} {two}") == ("abc def", "123 456")

      schema = validate.Schema(
          validate.union({
              "one": lambda val: val < 3,
              validate.optional("two"): lambda val: val > 1,
          }),
      )
      assert schema.validate(1) == {"one": 1}
      assert schema.validate(2) == {"one": 2, "two": 2}
      schema.validate(3)  # raises ValidationError

  Parameters:

    schema (Union[tuple, list, set, frozenset, dict]) -- A `tuple`, `list`, `set`, `frozenset` or `dict` of schemas

  Raises:

    ValidationError -- If a sequence item or the value of a non-optional key-value pair doesn't validate

  Returns:

    A new object of the same type, with each item or key-value pair being validated against the same input value

class streamlink.validate._schemas.UnionGetSchema(*getters, seq=<class 'tuple'>)

  Validate multiple `GetItemSchema` schemas on the same input.

  Convenience wrapper for `validate.union((validate.get(...), validate.get(...), ...))`.

  Example:

      schema = validate.Schema(
          validate.union_get("a", "b", ("c", "d")),
      )
      assert schema.validate({"a": 1, "b": 2, "c": {"d": 3}}) == (1, 2, 3)

  Parameters:

    - *getters -- Inputs for each `GetItemSchema`

    - seq (type[tuple | list | set | frozenset])

  Returns:

    A `tuple` (default `seq` type) with items of the respective `GetItemSchema` validations

class streamlink.validate._schemas.RegexSchema(pattern, method='search')

  A `re.Pattern` that must match.

  Allows selecting a different regex pattern method (default is `re.Pattern.search()`).

  Please note the difference between `RegexSchema` and the `re.Pattern` validation.

  Example:

      schema = validate.Schema(
          validate.regex(re.compile(r"Hello, (?P<name>\w+)!")),
      )
      assert schema.validate("Hello, world!")["name"] == "world"
      schema.validate("Does not match")  # raises ValidationError
      schema.validate(123)  # raises ValidationError
      schema.validate(b"Hello, world!")  # raises ValidationError

      schema = validate.Schema(
          validate.regex(re.compile(r"Hello, (?P<name>\w+)!"), method="findall"),
      )
      assert schema.validate("Hello, userA! Hello, userB!") == ["userA", "userB"]
      assert schema.validate("Does not match") == []  # findall does not return None

  Parameters:

    - pattern (Pattern) -- A compiled pattern (`re.compile()` return value)

    - method (Literal['search', 'match', 'fullmatch', 'findall', 'split', 'sub', 'subn']) -- The pattern's method which will be called when validating

  Raises:

    - ValidationError -- If the input is not an instance of `str` or `bytes`

    - ValidationError -- If the type of the input doesn't match the pattern's `str`/`bytes` type

    - ValidationError -- If the return value of the chosen regex pattern method is `None`

class streamlink.validate._schemas.XmlElementSchema(tag=None, text=None, attrib=None, tail=None)

  Validate an XML element.

  Example:

      schema = validate.Schema(
          validate.xml_element(
              tag="foo",
              attrib={"bar": str},
              text=validate.transform(str.upper),
          ),
      )
      elem = lxml.etree.XML("""<foo bar="baz">qux</foo>""")
      new_elem = schema.validate(elem)
      assert new_elem is not elem
      assert new_elem.tag == "foo"
      assert new_elem.attrib == {"bar": "baz"}
      assert new_elem.text == "QUX"
      assert new_elem.tail is None
      schema.validate(123)  # raises ValidationError
      schema.validate(lxml.etree.XML("""<unknown/>"""))  # raises ValidationError

  Parameters:

    - tag (Any) -- Optional element tag validation

    - text (Any) -- Optional element text validation

    - attrib (Any) -- Optional element attributes validation

    - tail (Any) -- Optional element tail validation

  Raises:

    ValidationError -- If `value` is not an `lxml.etree.Element`

  Returns:

    A new `lxml.etree.Element` object, including a deep-copy of the input's child nodes, with optionally validated `tag`, `attrib` mapping, `text` or `tail`.

exception streamlink.validate._exception.ValidationError(*errors, schema=None, **errkeywords)

  Bases: `ValueError`

  Currently not exposed in the public API.

  Parameters:

    schema (str | object | None)