Files
revng-revng/python/revng/model/_common/monkeypatches.py
2022-02-22 18:20:12 +01:00

69 lines
2.2 KiB
Python

#
# This file is distributed under the MIT License. See LICENSE.md for details.
#
import random
from enum import Enum
from typing import Optional
def autoassign_constructor_argument(base_class: type, kwarg_name, kwarg_value):
"""Monkeypatches __init__ so that the given keyword argument is set to the given value if was not set by the caller"""
assert isinstance(base_class, type)
original_init = base_class.__init__
def init_with_value(self, *args, **kwargs):
if kwarg_name not in kwargs:
kwargs[kwarg_name] = kwarg_value
original_init(self, *args, **kwargs)
base_class.__init__ = init_with_value
def autoassign_random_id(base_class: type):
"""Monkeypatches the __init__ method so that the ID is automatically assigned"""
assert isinstance(base_class, type)
original_init = base_class.__init__
def init_with_random_id(self, *args, **kwargs):
if "ID" not in kwargs:
kwargs["ID"] = random.randint(2**10 + 1, 2**64 - 1)
original_init(self, *args, **kwargs)
base_class.__init__ = init_with_random_id
def autoassign_primitive_id(base_class: type):
"""Monkeypatches the __init__ method so that the ID is automatically assigned.
Meant for use with primitive types.
"""
assert isinstance(base_class, type)
original_init = base_class.__init__
def init_with_computed_id(self, *args, PrimitiveKind: "PrimitiveTypeKind", Size: int, **kwargs):
if "ID" not in kwargs:
primitive_kind_value = enum_value_to_index(PrimitiveKind)
kwargs["ID"] = primitive_kind_value << 8 | Size
original_init(self, *args, PrimitiveKind=PrimitiveKind, Size=Size, **kwargs)
base_class.__init__ = init_with_computed_id
def enum_value_to_index(enum_value: Enum):
"""Converts an enum value to its index"""
return list(enum_value.__class__.__members__).index(enum_value.value)
def make_hashable_using_attribute(base_type, attribute_name: Optional[str]):
"""Implements __hash__ by returning the given attribute"""
def __hash__(self):
if attribute_name is None:
return id(self)
return self.__getattribute__(attribute_name)
base_type.__hash__ = __hash__