From 97c459bca7268300f90901a57dccfd434772073b Mon Sep 17 00:00:00 2001 From: dgelessus Date: Sun, 29 Sep 2019 14:58:18 +0200 Subject: [PATCH] Change attribute type annotations to standard format Previously, the types of instance attributes were annotated with the first assignment of each attribute. The standard way to annotate instance attributes is to do so at class level without assigning any value. --- rsrcfork/api.py | 65 ++++++++++++++++++++++++------------- rsrcfork/compress/common.py | 24 ++++++++++---- 2 files changed, 59 insertions(+), 30 deletions(-) diff --git a/rsrcfork/api.py b/rsrcfork/api.py index 1d91192..f2625bf 100644 --- a/rsrcfork/api.py +++ b/rsrcfork/api.py @@ -98,16 +98,24 @@ class Resource(object): __slots__ = ("type", "id", "name", "attributes", "data_raw", "_compressed_info", "_data_decompressed") + type: bytes + id: int + name: typing.Optional[bytes] + attributes: ResourceAttrs + data_raw: bytes + _compressed_info: compress.common.CompressedHeaderInfo + _data_decompressed: bytes + def __init__(self, resource_type: bytes, resource_id: int, name: typing.Optional[bytes], attributes: ResourceAttrs, data_raw: bytes): """Create a new resource with the given type code, ID, name, attributes, and data.""" super().__init__() - self.type: bytes = resource_type - self.id: int = resource_id - self.name: typing.Optional[bytes] = name - self.attributes: ResourceAttrs = attributes - self.data_raw: bytes = data_raw + self.type = resource_type + self.id = resource_id + self.name = name + self.attributes = attributes + self.data_raw = data_raw def __repr__(self): try: @@ -198,14 +206,18 @@ class ResourceFile(collections.abc.Mapping): class _LazyResourceMap(collections.abc.Mapping): """Internal class: Lazy mapping of resource IDs to resource objects, returned when subscripting a ResourceFile.""" + _resfile: "ResourceFile" + _restype: bytes + _submap: typing.Mapping[int, typing.Tuple[int, ResourceAttrs, int]] + def __init__(self, resfile: "ResourceFile", restype: bytes): """Create a new _LazyResourceMap "containing" all resources in resfile that have the type code restype.""" super().__init__() - self._resfile: "ResourceFile" = resfile - self._restype: bytes = restype - self._submap: typing.Mapping[int, typing.Tuple[int, ResourceAttrs, int]] = self._resfile._references[self._restype] + self._resfile = resfile + self._restype = restype + self._submap = self._resfile._references[self._restype] def __len__(self): """Get the number of resources with this type code.""" @@ -246,6 +258,23 @@ class ResourceFile(collections.abc.Mapping): else: return f"<{type(self).__module__}.{type(self).__qualname__} at {id(self):#x} containing {len(self)} resources with IDs: {list(self)}>" + _close_stream: bool + _stream: typing.BinaryIO + + data_offset: int + map_offset: int + data_length: int + map_length: int + header_system_data: bytes + header_application_data: bytes + + map_type_list_offset: int + map_name_list_offset: int + file_attributes: ResourceFileAttrs + + _reference_counts: typing.MutableMapping[bytes, int] + _references: typing.MutableMapping[bytes, typing.MutableMapping[int, typing.Tuple[int, ResourceAttrs, int]]] + @classmethod def open(cls, filename: typing.Union[str, bytes, os.PathLike], *, fork: str="auto", **kwargs) -> "ResourceFile": """Open the file at the given path as a ResourceFile. @@ -320,8 +349,7 @@ class ResourceFile(collections.abc.Mapping): super().__init__() - self._close_stream: bool = close - self._stream: typing.BinaryIO + self._close_stream = close if stream.seekable(): self._stream = stream else: @@ -358,12 +386,6 @@ class ResourceFile(collections.abc.Mapping): assert self._stream.tell() == 0 - self.data_offset: int - self.map_offset: int - self.data_length: int - self.map_length: int - self.header_system_data: bytes - self.header_application_data: bytes ( self.data_offset, self.map_offset, @@ -381,20 +403,18 @@ class ResourceFile(collections.abc.Mapping): assert self._stream.tell() == self.map_offset - self.map_type_list_offset: int - self.map_name_list_offset: int ( _file_attributes, self.map_type_list_offset, self.map_name_list_offset, ) = self._stream_unpack(STRUCT_RESOURCE_MAP_HEADER) - self.file_attributes: ResourceFileAttrs = ResourceFileAttrs(_file_attributes) + self.file_attributes = ResourceFileAttrs(_file_attributes) def _read_all_resource_types(self): """Read all resource types, starting at the current stream position.""" - self._reference_counts: typing.MutableMapping[bytes, int] = collections.OrderedDict() + self._reference_counts = collections.OrderedDict() (type_list_length_m1,) = self._stream_unpack(STRUCT_RESOURCE_TYPE_LIST_HEADER) type_list_length = (type_list_length_m1 + 1) % 0x10000 @@ -411,11 +431,10 @@ class ResourceFile(collections.abc.Mapping): def _read_all_references(self): """Read all resource references, starting at the current stream position.""" - self._references: typing.MutableMapping[bytes, typing.MutableMapping[int, typing.Tuple[int, ResourceAttrs, int]]] = collections.OrderedDict() + self._references = collections.OrderedDict() for resource_type, count in self._reference_counts.items(): - resmap: typing.MutableMapping[int, typing.Tuple[int, ResourceAttrs, int]] = collections.OrderedDict() - self._references[resource_type] = resmap + self._references[resource_type] = resmap = collections.OrderedDict() for _ in range(count): ( resource_id, diff --git a/rsrcfork/compress/common.py b/rsrcfork/compress/common.py index 7eea684..23d9c18 100644 --- a/rsrcfork/compress/common.py +++ b/rsrcfork/compress/common.py @@ -60,31 +60,41 @@ class CompressedHeaderInfo(object): else: raise DecompressError(f"Unsupported compression type: 0x{compression_type:>04x}") + header_length: int + compression_type: int + decompressed_length: int + dcmp_id: int + def __init__(self, header_length: int, compression_type: int, decompressed_length: int, dcmp_id: int) -> None: super().__init__() - self.header_length: int = header_length - self.compression_type: int = compression_type - self.decompressed_length: int = decompressed_length - self.dcmp_id: int = dcmp_id + self.header_length = header_length + self.compression_type = compression_type + self.decompressed_length = decompressed_length + self.dcmp_id = dcmp_id class CompressedApplicationHeaderInfo(CompressedHeaderInfo): + working_buffer_fractional_size: int + expansion_buffer_size: int + def __init__(self, header_length: int, compression_type: int, decompressed_length: int, dcmp_id: int, working_buffer_fractional_size: int, expansion_buffer_size: int) -> None: super().__init__(header_length, compression_type, decompressed_length, dcmp_id) - self.working_buffer_fractional_size: int = working_buffer_fractional_size - self.expansion_buffer_size: int = expansion_buffer_size + self.working_buffer_fractional_size = working_buffer_fractional_size + self.expansion_buffer_size = expansion_buffer_size def __repr__(self): return f"{type(self).__qualname__}(header_length={self.header_length}, compression_type=0x{self.compression_type:>04x}, decompressed_length={self.decompressed_length}, dcmp_id={self.dcmp_id}, working_buffer_fractional_size={self.working_buffer_fractional_size}, expansion_buffer_size={self.expansion_buffer_size})" class CompressedSystemHeaderInfo(CompressedHeaderInfo): + parameters: bytes + def __init__(self, header_length: int, compression_type: int, decompressed_length: int, dcmp_id: int, parameters: bytes) -> None: super().__init__(header_length, compression_type, decompressed_length, dcmp_id) - self.parameters: bytes = parameters + self.parameters = parameters def __repr__(self): return f"{type(self).__qualname__}(header_length={self.header_length}, compression_type=0x{self.compression_type:>04x}, decompressed_length={self.decompressed_length}, dcmp_id={self.dcmp_id}, parameters={self.parameters!r})"