# Path: avatar2/peripherals/avatar_peripheral.py
# class AvatarPeripheral(object):
#     def __init__(self, name, address, size, **kwargs):
#         self.name = name if name else "%s_%x" % (self.__class__.__name__, address)
#         self.address = address
#         self.size = size
#         self.read_handler = IntervalTree()
#         self.write_handler = IntervalTree()
# 
#     @cached_property
#     def read_supports_pc(self):
#         """
#         Checks if all registered read-handlers support an pc parameter
#         """
#         return all("pc" in signature(rh.data).parameters for rh in self.read_handler)
# 
#     @cached_property
#     def write_supports_pc(self):
#         """
#         Checks if all registered read-handlers support an pc parameter
#         """
#         return all("pc" in signature(rh.data).parameters for rh in self.write_handler)
# 
#     def shutdown(self):
#         """
#         Some peripherals will require to be shutdowned when avatar exits.
#         In those cases, this method should be overwritten.
#         """
#         pass
# 
#     def write_memory(self, address, size, value, num_words=1, raw=False, pc=0):
# 
#         if num_words != 1 or raw is True:
#             raise Exception(
#                 "write_memory for AvatarPeripheral does not support \
#                              'num_words' or 'raw' kwarg"
#             )
# 
#         offset = address - self.address
#         intervals = self.write_handler[offset : offset + size]
#         if intervals == set():
#             raise Exception(
#                 "No write handler for peripheral %s at offset %d \
#                             (0x%x)"
#                 % (self.name, offset, address)
#             )
#         if len(intervals) > 1:
#             raise Exception(
#                 "Multiple write handler for peripheral %s\
#                             at offset %d"
#                 % (self.name, offset)
#             )
# 
#         kwargs = {} if self.write_supports_pc is False else {"pc": pc}
#         return intervals.pop().data(offset, size, value, **kwargs)
# 
#     def read_memory(self, address, size, num_words=1, raw=False, pc=0):
#         if num_words != 1 or raw is True:
#             raise Exception(
#                 "read_memory for AvatarPeripheral does not support \
#                              'num_words' or 'raw' kwarg"
#             )
# 
#         offset = address - self.address
#         intervals = self.read_handler[offset : offset + size]
# 
#         if intervals == set():
#             raise Exception(
#                 "No read handler for peripheral %s at offset %d \
#                             (0x%x)"
#                 % (self.name, offset, address)
#             )
#         if len(intervals) > 1:
#             raise Exception(
#                 "Multiple read handler for peripheral %s\
#                             at offset %d"
#                 % (self.name, offset)
#             )
#         kwargs = {} if self.write_supports_pc is False else {"pc": pc}
#         return intervals.pop().data(offset, size, **kwargs)


from os.path import abspath
from sys import version_info
from .peripherals.avatar_peripheral import AvatarPeripheral
        from .avatar2 import Avatar # we cannot do this import at top-level
        self.permissions = permissions
        self.file = abspath(file) if file is not None else None
        self.file_offset = file_offset if file_offset is not None else None
        self.file_bytes = file_bytes if file_bytes is not None else None
        self.forwarded = forwarded
        self.is_symbolic = is_symbolic
        self.is_special = is_special
        self.forwarded_to = forwarded_to
        self.__dict__.update(kwargs)


    def dictify(self):
        """
        Returns the memory range as *printable* dictionary
        """
        # Assumption: dicts saved in mrs are of primitive types only
        expected_types = (str, bool, int, dict, AvatarPeripheral, Avatar, list)
        if version_info < (3, 0): expected_types += (unicode, )

        tmp_dict = dict(self.__dict__)
        mr_dict = {}
        while tmp_dict != {}:
            k, v = tmp_dict.popitem()
            if v is None or False: continue
            elif k == 'forwarded_to': v = v.name
            # TODO handle emulate
            if not isinstance(v, expected_types):
                raise Exception(
                    "Unsupported type %s for dictifying %s for mem_range at 0x%x"
                    % (type(v), k, self.address))

# Path: avatar2/peripherals/avatar_peripheral.py
# class AvatarPeripheral(object):
#     def __init__(self, name, address, size, **kwargs):
#         self.name = name if name else "%s_%x" % (self.__class__.__name__, address)
#         self.address = address
#         self.size = size
#         self.read_handler = IntervalTree()
#         self.write_handler = IntervalTree()
# 
#     @cached_property
#     def read_supports_pc(self):
#         """
#         Checks if all registered read-handlers support an pc parameter
#         """
#         return all("pc" in signature(rh.data).parameters for rh in self.read_handler)
# 
#     @cached_property
#     def write_supports_pc(self):
#         """
#         Checks if all registered read-handlers support an pc parameter
#         """
#         return all("pc" in signature(rh.data).parameters for rh in self.write_handler)
# 
#     def shutdown(self):
#         """
#         Some peripherals will require to be shutdowned when avatar exits.
#         In those cases, this method should be overwritten.
#         """
#         pass
# 
#     def write_memory(self, address, size, value, num_words=1, raw=False, pc=0):
# 
#         if num_words != 1 or raw is True:
#             raise Exception(
#                 "write_memory for AvatarPeripheral does not support \
#                              'num_words' or 'raw' kwarg"
#             )
# 
#         offset = address - self.address
#         intervals = self.write_handler[offset : offset + size]
#         if intervals == set():
#             raise Exception(
#                 "No write handler for peripheral %s at offset %d \
#                             (0x%x)"
#                 % (self.name, offset, address)
#             )
#         if len(intervals) > 1:
#             raise Exception(
#                 "Multiple write handler for peripheral %s\
#                             at offset %d"
#                 % (self.name, offset)
#             )
# 
#         kwargs = {} if self.write_supports_pc is False else {"pc": pc}
#         return intervals.pop().data(offset, size, value, **kwargs)
# 
#     def read_memory(self, address, size, num_words=1, raw=False, pc=0):
#         if num_words != 1 or raw is True:
#             raise Exception(
#                 "read_memory for AvatarPeripheral does not support \
#                              'num_words' or 'raw' kwarg"
#             )
# 
#         offset = address - self.address
#         intervals = self.read_handler[offset : offset + size]
# 
#         if intervals == set():
#             raise Exception(
#                 "No read handler for peripheral %s at offset %d \
#                             (0x%x)"
#                 % (self.name, offset, address)
#             )
#         if len(intervals) > 1:
#             raise Exception(
#                 "Multiple read handler for peripheral %s\
#                             at offset %d"
#                 % (self.name, offset)
#             )
#         kwargs = {} if self.write_supports_pc is False else {"pc": pc}
#         return intervals.pop().data(offset, size, **kwargs)


# Path: avatar2/memory_range.py
from os.path import abspath
from sys import version_info
from .peripherals.avatar_peripheral import AvatarPeripheral
        from .avatar2 import Avatar # we cannot do this import at top-level

        self.permissions = permissions
        self.file = abspath(file) if file is not None else None
        self.file_offset = file_offset if file_offset is not None else None
        self.file_bytes = file_bytes if file_bytes is not None else None
        self.forwarded = forwarded
        self.is_symbolic = is_symbolic
        self.is_special = is_special
        self.forwarded_to = forwarded_to
        self.__dict__.update(kwargs)


    def dictify(self):
        """
        Returns the memory range as *printable* dictionary
        """
        # Assumption: dicts saved in mrs are of primitive types only
        expected_types = (str, bool, int, dict, AvatarPeripheral, Avatar, list)
        if version_info < (3, 0): expected_types += (unicode, )

        tmp_dict = dict(self.__dict__)
        mr_dict = {}
        while tmp_dict != {}:
            k, v = tmp_dict.popitem()
            if v is None or False: continue
            elif k == 'forwarded_to': v = v.name
            # TODO handle emulate
            if not isinstance(v, expected_types):
                raise Exception(
                    "Unsupported type %s for dictifying %s for mem_range at 0x%x"
                    % (type(v), k, self.address))

            if isinstance(v, AvatarPeripheral):