/testsuite/databases/mongo/mongo_schema.py

https://github.com/yandex/yandex-taxi-testsuite
Python | 83 lines | 66 code | 17 blank | 0 comment | 11 complexity | f2002ddf93ecb5a195e5a369d84c9bd8 MD5 | raw file
  1. import collections.abc
  2. import glob
  3. import os
  4. import typing
  5. from testsuite.utils import yaml_util
  6. class MongoSchema(collections.abc.Mapping):
  7. def __init__(self, directory):
  8. self._directory = directory
  9. self._loaded = {}
  10. self._paths = _get_paths(directory)
  11. def __getitem__(self, name):
  12. if name not in self._paths:
  13. raise KeyError(f'Missing schema file for collection {name}')
  14. if name not in self._loaded:
  15. self._loaded[name] = yaml_util.load_file(self._paths[name])
  16. return self._loaded[name]
  17. def __iter__(self):
  18. return iter(self._paths)
  19. def __len__(self) -> int:
  20. return len(self._paths)
  21. @property
  22. def directory(self):
  23. return self._directory
  24. class MongoSchemaCache:
  25. def __init__(self):
  26. self._cache: typing.Dict[str, MongoSchema] = {}
  27. def get_schema(self, directory):
  28. if directory not in self._cache:
  29. self._cache[directory] = MongoSchema(directory)
  30. return self._cache[directory]
  31. class MongoSchemas(collections.abc.Mapping):
  32. def __init__(
  33. self, cache: MongoSchemaCache, directories: typing.Iterable[str],
  34. ):
  35. self._cache = cache
  36. self._directories = directories
  37. self._schema_by_collection: typing.Dict[str, MongoSchema] = {}
  38. for directory in directories:
  39. schema = cache.get_schema(directory)
  40. for name in schema:
  41. if name in self._schema_by_collection:
  42. raise RuntimeError(
  43. f'Duplicate definition of collection {name}:\n'
  44. f' at {self._schema_by_collection[name].directory}\n'
  45. f' at {directory}',
  46. )
  47. self._schema_by_collection[name] = schema
  48. def __getitem__(self, name):
  49. if name not in self._schema_by_collection:
  50. raise KeyError(f'Missing schema file for collection {name}')
  51. return self._schema_by_collection[name][name]
  52. def __iter__(self):
  53. for directory in self._directories:
  54. for name in self._cache.get_schema(directory):
  55. yield name
  56. def __len__(self) -> int:
  57. return sum(
  58. len(self._cache.get_schema(directory))
  59. for directory in self._directories
  60. )
  61. def _get_paths(directory) -> typing.Dict[str, str]:
  62. result = {}
  63. for path in glob.glob(os.path.join(directory, '*.yaml')):
  64. collection, _ = os.path.splitext(os.path.basename(path))
  65. result[collection] = path
  66. return result