1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# 4# Copyright (c) 2024 Huawei Device Co., Ltd. 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18import operator 19from functools import reduce 20from typing import Any, Iterable, Optional, Tuple, Type 21 22import rich.repr 23 24from .base import MirrorMeta, _arkts_str 25from .type_cache import type_cache 26 27 28class ObjectMeta(MirrorMeta): 29 30 def __new__(mcls, name: str, bases: Tuple[Type], namespace: dict[str, Any], **kwargs: Any): 31 namespace = { 32 **namespace, 33 "__eq__": ObjectMeta.__eq__, 34 "__repr__": ObjectMeta.__repr__, 35 "__rich_repr__": ObjectMeta.__rich_repr__, 36 "__arkts_repr__": ObjectMeta.__arkts_repr__, 37 "__arkts_str__": ObjectMeta.__arkts_str__, 38 "__hash__": ObjectMeta.__hash__, 39 } 40 cls = super().__new__(mcls, name, bases, namespace, **kwargs) 41 return rich.repr.auto(cls) 42 43 # CC-OFFNXT(G.NAM.05) Standard function from rich package 44 def __rich_repr__(self) -> Iterable[Tuple[str, Any]]: 45 return [(name, attr) for name, attr in vars(self).items() if not callable(attr)] 46 47 # CC-OFFNXT(G.NAM.05) internal function name 48 def __arkts_repr__(self) -> Iterable[Tuple[str, Any]]: 49 return [ 50 (name, attr) 51 for name, attr in [(name, getattr(self, name)) for name in dir(self) if not name.startswith("_")] 52 if not callable(attr) 53 ] 54 55 def __eq__(self, other: Any) -> bool: 56 if type(self).__name__ != type(other).__name__: 57 return False 58 if vars(self).keys() != vars(other).keys(): 59 return False 60 for k, v in vars(self).items(): 61 if v != vars(other).get(k, None): 62 return False 63 return True 64 65 # CC-OFFNXT(G.NAM.05) internal function name 66 def __arkts_str__(self, *, depth: Optional[int] = None) -> str: 67 if depth == 0: 68 return f"{self.__class__.__name__} {{...}}" 69 next_depth = depth - 1 if depth is not None else None 70 params = ", ".join([f"{name}: {_arkts_str(param, depth=next_depth)}" for name, param in self.__arkts_repr__()]) 71 return f"{self.__class__.__name__} {{{params}}}" 72 73 def __hash__(self) -> int: 74 return reduce(operator.xor, [hash(k) for k in vars(self).keys()]) ^ hash(type(self).__name__) 75 76 77class Object(metaclass=ObjectMeta): 78 """Base class for ArkTS mirror classes.""" 79 80 pass 81 82 83@type_cache(scope="test") 84def mirror_object_type(cls_name: str, /, **kwargs) -> Type: 85 t = ObjectMeta(cls_name, (Object,), kwargs, module=__package__) 86 return t 87 88 89def mirror_object(cls_name: str, /, **kwargs): 90 t = mirror_object_type(cls_name, **dict.fromkeys(kwargs.keys())) 91 obj = t() 92 for k, v in kwargs.items(): 93 setattr(obj, k, v) 94 return obj 95