1"""This submodule contains utility code for Prance."""
2
3__author__ = 'Jens Finkhaeuser'
4__copyright__ = 'Copyright (c) 2016-2021 Jens Finkhaeuser'
5__license__ = 'MIT'
6__all__ = ('iterators', 'fs', 'formats', 'resolver', 'url', 'path',
7    'exceptions')
8
9
10def stringify_keys(data):
11  """
12  Recursively stringify keys in a dict-like object.
13
14  :param dict-like data: A dict-like object to stringify keys in.
15  :return: A new dict-like object of the same type with stringified keys,
16      but the same values.
17  """
18  from collections.abc import Mapping
19  assert isinstance(data, Mapping)
20
21  ret = type(data)()
22  for key, value in data.items():
23    if not isinstance(key, str):
24      key = str(key)
25    if isinstance(value, Mapping):
26      value = stringify_keys(value)
27    ret[key] = value
28  return ret
29
30
31def validation_backends():
32  """Return a list of validation backends supported by the environment."""
33  ret = []
34
35  try:
36    import flex  # noqa: F401
37    ret.append('flex')  # pragma: nocover
38  except (ImportError, SyntaxError):  # pragma: nocover
39    pass
40
41  try:
42    import openapi_spec_validator  # noqa: F401
43    ret.append('openapi-spec-validator')  # pragma: nocover
44  except (ImportError, SyntaxError):  # pragma: nocover
45    pass
46
47  try:
48    import swagger_spec_validator  # noqa: F401
49    ret.append('swagger-spec-validator')  # pragma: nocover
50  except (ImportError, SyntaxError):  # pragma: nocover
51    pass
52
53  return tuple(ret)
54
55
56def default_validation_backend():
57  """Return the default validation backend, or raise an error."""
58  backends = validation_backends()
59  if len(backends) <= 0:  # pragma: nocover
60    raise RuntimeError('No validation backend available! Install one of '
61        '"flex", "openapi-spec-validator" or "swagger-spec-validator".')
62  return backends[0]
63