From e6918187568dbd01842d8d1d2c808ce16a894239 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 21 Apr 2024 13:54:28 +0200 Subject: Adding upstream version 18.2.2. Signed-off-by: Daniel Baumann --- .../rook/rook-client-python/rook_client/_helper.py | 128 +++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 src/pybind/mgr/rook/rook-client-python/rook_client/_helper.py (limited to 'src/pybind/mgr/rook/rook-client-python/rook_client/_helper.py') diff --git a/src/pybind/mgr/rook/rook-client-python/rook_client/_helper.py b/src/pybind/mgr/rook/rook-client-python/rook_client/_helper.py new file mode 100644 index 000000000..382d04c27 --- /dev/null +++ b/src/pybind/mgr/rook/rook-client-python/rook_client/_helper.py @@ -0,0 +1,128 @@ +import logging +import sys +try: + from typing import List, Dict, Any, Optional +except ImportError: + pass + +logger = logging.getLogger(__name__) + +# Tricking mypy to think `_omit`'s type is NoneType +# To make us not add things like `Union[Optional[str], OmitType]` +NoneType = type(None) +_omit = None # type: NoneType +_omit = object() # type: ignore + + +# Don't add any additionalProperties to objects. Useful for completeness testing +STRICT = False + +def _str_to_class(cls, typ_str): + if isinstance(typ_str, str): + return getattr(sys.modules[cls.__module__], typ_str) + return typ_str + + +def _property_from_json(cls, data, breadcrumb, name, py_name, typ_str, required, nullable): + if not required and name not in data: + return _omit + try: + obj = data[name] + except KeyError as e: + raise ValueError('KeyError in {}: {}'.format(breadcrumb, e)) + if nullable and obj is None: + return obj + typ = _str_to_class(cls, typ_str) + if issubclass(typ, CrdObject) or issubclass(typ, CrdObjectList): + return typ.from_json(obj, breadcrumb + '.' + name) + return obj + + +class CrdObject(object): + _properties = [] # type: List + + def __init__(self, **kwargs): + for prop in self._properties: + setattr(self, prop[1], kwargs.pop(prop[1])) + if kwargs: + raise TypeError( + '{} got unexpected arguments {}'.format(self.__class__.__name__, kwargs.keys())) + self._additionalProperties = {} # type: Dict[str, Any] + + def _property_impl(self, name): + obj = getattr(self, '_' + name) + if obj is _omit: + raise AttributeError(name + ' not found') + return obj + + def _property_to_json(self, name, py_name, typ_str, required, nullable): + obj = getattr(self, '_' + py_name) + typ = _str_to_class(self.__class__, typ_str) + if issubclass(typ, CrdObject) or issubclass(typ, CrdObjectList): + if nullable and obj is None: + return obj + if not required and obj is _omit: + return obj + return obj.to_json() + else: + return obj + + def to_json(self): + # type: () -> Dict[str, Any] + res = {p[0]: self._property_to_json(*p) for p in self._properties} + res.update(self._additionalProperties) + return {k: v for k, v in res.items() if v is not _omit} + + @classmethod + def from_json(cls, data, breadcrumb=''): + try: + sanitized = { + p[1]: _property_from_json(cls, data, breadcrumb, *p) for p in cls._properties + } + extra = {k:v for k,v in data.items() if k not in sanitized} + ret = cls(**sanitized) + ret._additionalProperties = {} if STRICT else extra + return ret + except (TypeError, AttributeError, KeyError): + logger.exception(breadcrumb) + raise + + +class CrdClass(CrdObject): + @classmethod + def from_json(cls, data, breadcrumb=''): + kind = data['kind'] + if kind != cls.__name__: + raise ValueError("kind mismatch: {} != {}".format(kind, cls.__name__)) + return super(CrdClass, cls).from_json(data, breadcrumb) + + def to_json(self): + ret = super(CrdClass, self).to_json() + ret['kind'] = self.__class__.__name__ + return ret + + +class CrdObjectList(list): + # Py3: Replace `Any` with `TypeVar('T_CrdObject', bound='CrdObject')` + _items_type = None # type: Optional[Any] + + def to_json(self): + # type: () -> List + if self._items_type is None: + return self + if issubclass(self._items_type, CrdObject) or issubclass(self._items_type, CrdObjectList): + return [e.to_json() for e in self] + return list(self) + + + @classmethod + def from_json(cls, data, breadcrumb=''): + if cls._items_type is None: + return cls(data) + if issubclass(cls._items_type, CrdObject) or issubclass(cls._items_type, CrdObjectList): + return cls(cls._items_type.from_json(e, breadcrumb + '[{}]'.format(i)) for i, e in enumerate(data)) + return cls(data) + + def __repr__(self): + return '{}({})'.format(self.__class__.__name__, repr(list(self))) + -- cgit v1.2.3