Rename resource_type and resource_id attributes to type and id

The old names were chosen to avoid conflicts with Python's type and id
builtins, but for attribute names this is not necessary.
This commit is contained in:
dgelessus 2019-09-15 15:56:03 +02:00
parent f4c2717720
commit c6337bdfbd
3 changed files with 31 additions and 20 deletions

View File

@ -56,7 +56,7 @@ Simple example
>>> rf >>> rf
<rsrcfork.ResourceFile at 0x1046e6048, attributes ResourceFileAttrs.0, containing 4 resource types: [b'utxt', b'utf8', b'TEXT', b'drag']> <rsrcfork.ResourceFile at 0x1046e6048, attributes ResourceFileAttrs.0, containing 4 resource types: [b'utxt', b'utf8', b'TEXT', b'drag']>
>>> rf[b"TEXT"] >>> rf[b"TEXT"]
<rsrcfork.ResourceFile._LazyResourceMap at 0x10470ed30 containing one resource: rsrcfork.Resource(resource_type=b'TEXT', resource_id=256, name=None, attributes=ResourceAttrs.0, data=b'Here is some text')> <rsrcfork.ResourceFile._LazyResourceMap at 0x10470ed30 containing one resource: rsrcfork.Resource(type=b'TEXT', id=256, name=None, attributes=ResourceAttrs.0, data=b'Here is some text')>
Automatic selection of data/resource fork Automatic selection of data/resource fork
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -133,6 +133,7 @@ Version 1.2.1 (next version)
* Added a ``--sort`` command line option to output resources sorted by type and ID, instead of using the order stored in the file. * Added a ``--sort`` command line option to output resources sorted by type and ID, instead of using the order stored in the file.
* Added a ``--group`` command line option to group resources in list format by type (the default), ID, or with no grouping. * Added a ``--group`` command line option to group resources in list format by type (the default), ID, or with no grouping.
* Added a ``dump-text`` output format to the command line tool. This format is identical to ``dump``, but instead of a hex dump, it outputs the resource data as text. The data is decoded as MacRoman and classic Mac newlines (``\r``) are translated. This is useful for examining resources that contain mostly plain text. * Added a ``dump-text`` output format to the command line tool. This format is identical to ``dump``, but instead of a hex dump, it outputs the resource data as text. The data is decoded as MacRoman and classic Mac newlines (``\r``) are translated. This is useful for examining resources that contain mostly plain text.
* Renamed the ``rsrcfork.Resource`` attributes ``resource_type`` and ``resource_id`` to ``type`` and ``id``, respectively. The old names have been deprecated and will be removed in the future, but are still supported for now.
* Changed ``--format=dump`` output to match ``hexdump -C``'s format - spacing has been adjusted, and multiple subsequent identical lines are collapsed into a single ``*``. * Changed ``--format=dump`` output to match ``hexdump -C``'s format - spacing has been adjusted, and multiple subsequent identical lines are collapsed into a single ``*``.
Version 1.2.0 Version 1.2.0

View File

@ -93,7 +93,7 @@ def _filter_resources(rf: api.ResourceFile, filters: typing.Sequence[str]) -> ty
continue continue
for res in resources.values(): for res in resources.values():
matching[res.resource_type, res.resource_id] = res matching[res.type, res.id] = res
elif filter[0] == filter[-1] == "'": elif filter[0] == filter[-1] == "'":
try: try:
resources = rf[_bytes_unescape(filter[1:-1])] resources = rf[_bytes_unescape(filter[1:-1])]
@ -101,7 +101,7 @@ def _filter_resources(rf: api.ResourceFile, filters: typing.Sequence[str]) -> ty
continue continue
for res in resources.values(): for res in resources.values():
matching[res.resource_type, res.resource_id] = res matching[res.type, res.id] = res
else: else:
pos = filter.find("'", 1) pos = filter.find("'", 1)
if pos == -1: if pos == -1:
@ -134,7 +134,7 @@ def _filter_resources(rf: api.ResourceFile, filters: typing.Sequence[str]) -> ty
for res in resources.values(): for res in resources.values():
if res.name == name: if res.name == name:
matching[res.resource_type, res.resource_id] = res matching[res.type, res.id] = res
break break
elif ":" in resid: elif ":" in resid:
if resid.count(":") > 1: if resid.count(":") > 1:
@ -143,15 +143,15 @@ def _filter_resources(rf: api.ResourceFile, filters: typing.Sequence[str]) -> ty
start, end = int(start), int(end) start, end = int(start), int(end)
for res in resources.values(): for res in resources.values():
if start <= res.resource_id <= end: if start <= res.id <= end:
matching[res.resource_type, res.resource_id] = res matching[res.type, res.id] = res
else: else:
resid = int(resid) resid = int(resid)
try: try:
res = resources[resid] res = resources[resid]
except KeyError: except KeyError:
continue continue
matching[res.resource_type, res.resource_id] = res matching[res.type, res.id] = res
return list(matching.values()) return list(matching.values())
@ -185,7 +185,7 @@ def _translate_text(data: bytes) -> str:
return data.decode(_TEXT_ENCODING).replace("\r", "\n") return data.decode(_TEXT_ENCODING).replace("\r", "\n")
def _describe_resource(res: api.Resource, *, include_type: bool, decompress: bool) -> str: def _describe_resource(res: api.Resource, *, include_type: bool, decompress: bool) -> str:
id_desc_parts = [f"{res.resource_id}"] id_desc_parts = [f"{res.id}"]
if res.name is not None: if res.name is not None:
name = _bytes_escape(res.name, quote='"') name = _bytes_escape(res.name, quote='"')
@ -214,7 +214,7 @@ def _describe_resource(res: api.Resource, *, include_type: bool, decompress: boo
desc = f"({id_desc}): {content_desc}" desc = f"({id_desc}): {content_desc}"
if include_type: if include_type:
restype = _bytes_escape(res.resource_type, quote="'") restype = _bytes_escape(res.type, quote="'")
desc = f"'{restype}' {desc}" desc = f"'{restype}' {desc}"
return desc return desc
@ -327,7 +327,7 @@ def _show_filtered_resources(resources: typing.Sequence[api.Resource], format: s
if None in attr_descs: if None in attr_descs:
attr_descs[:] = [f"${res.attributes.value:02X}"] attr_descs[:] = [f"${res.attributes.value:02X}"]
parts = [str(res.resource_id)] parts = [str(res.id)]
if res.name is not None: if res.name is not None:
name = _bytes_escape(res.name, quote='"') name = _bytes_escape(res.name, quote='"')
@ -335,7 +335,7 @@ def _show_filtered_resources(resources: typing.Sequence[api.Resource], format: s
parts += attr_descs parts += attr_descs
restype = _bytes_escape(res.resource_type, quote="'") restype = _bytes_escape(res.type, quote="'")
print(f"data '{restype}' ({', '.join(parts)}{attrs_comment}) {{") print(f"data '{restype}' ({', '.join(parts)}{attrs_comment}) {{")
for i in range(0, len(data), 16): for i in range(0, len(data), 16):
@ -380,7 +380,7 @@ def _list_resource_file(rf: api.ResourceFile, *, sort: bool, group: str, decompr
for reses in rf.values(): for reses in rf.values():
all_resources.extend(reses.values()) all_resources.extend(reses.values())
if sort: if sort:
all_resources.sort(key=lambda res: (res.resource_type, res.resource_id)) all_resources.sort(key=lambda res: (res.type, res.id))
print(f"{len(all_resources)} resources:") print(f"{len(all_resources)} resources:")
for res in all_resources: for res in all_resources:
print(_describe_resource(res, include_type=True, decompress=decompress)) print(_describe_resource(res, include_type=True, decompress=decompress))
@ -402,13 +402,13 @@ def _list_resource_file(rf: api.ResourceFile, *, sort: bool, group: str, decompr
all_resources = [] all_resources = []
for reses in rf.values(): for reses in rf.values():
all_resources.extend(reses.values()) all_resources.extend(reses.values())
all_resources.sort(key=lambda res: res.resource_id) all_resources.sort(key=lambda res: res.id)
resources_by_id = {resid: list(reses) for resid, reses in itertools.groupby(all_resources, key=lambda res: res.resource_id)} resources_by_id = {resid: list(reses) for resid, reses in itertools.groupby(all_resources, key=lambda res: res.id)}
print(f"{len(resources_by_id)} resource IDs:") print(f"{len(resources_by_id)} resource IDs:")
for resid, resources in resources_by_id.items(): for resid, resources in resources_by_id.items():
print(f"{resid}: {len(resources)} resources:") print(f"{resid}: {len(resources)} resources:")
if sort: if sort:
resources.sort(key=lambda res: res.resource_type) resources.sort(key=lambda res: res.type)
for res in resources: for res in resources:
print(_describe_resource(res, include_type=True, decompress=decompress)) print(_describe_resource(res, include_type=True, decompress=decompress))
print() print()
@ -444,7 +444,7 @@ def main():
resources.extend(reses.values()) resources.extend(reses.values())
if ns.sort: if ns.sort:
resources.sort(key=lambda res: (res.resource_type, res.resource_id)) resources.sort(key=lambda res: (res.type, res.id))
_show_filtered_resources(resources, format=ns.format, decompress=ns.decompress) _show_filtered_resources(resources, format=ns.format, decompress=ns.decompress)
else: else:

View File

@ -96,15 +96,15 @@ class ResourceAttrs(enum.Flag):
class Resource(object): class Resource(object):
"""A single resource from a resource file.""" """A single resource from a resource file."""
__slots__ = ("resource_type", "resource_id", "name", "attributes", "data_raw", "_data_decompressed") __slots__ = ("type", "id", "name", "attributes", "data_raw", "_data_decompressed")
def __init__(self, resource_type: bytes, resource_id: int, name: typing.Optional[bytes], attributes: ResourceAttrs, data_raw: 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.""" """Create a new resource with the given type code, ID, name, attributes, and data."""
super().__init__() super().__init__()
self.resource_type: bytes = resource_type self.type: bytes = resource_type
self.resource_id: int = resource_id self.id: int = resource_id
self.name: typing.Optional[bytes] = name self.name: typing.Optional[bytes] = name
self.attributes: ResourceAttrs = attributes self.attributes: ResourceAttrs = attributes
self.data_raw: bytes = data_raw self.data_raw: bytes = data_raw
@ -126,7 +126,17 @@ class Resource(object):
if not decompress_ok: if not decompress_ok:
data_repr = f"<decompression failed - compressed data: {data_repr}>" data_repr = f"<decompression failed - compressed data: {data_repr}>"
return f"{type(self).__module__}.{type(self).__qualname__}(resource_type={self.resource_type}, resource_id={self.resource_id}, name={self.name}, attributes={self.attributes}, data={data_repr})" return f"{type(self).__module__}.{type(self).__qualname__}(type={self.type}, id={self.id}, name={self.name}, attributes={self.attributes}, data={data_repr})"
@property
def resource_type(self) -> bytes:
warnings.warn(DeprecationWarning("The resource_type attribute has been deprecated and will be removed in a future version. Please use the type attribute instead."))
return self.type
@property
def resource_id(self) -> int:
warnings.warn(DeprecationWarning("The resource_id attribute has been deprecated and will be removed in a future version. Please use the id attribute instead."))
return self.id
@property @property
def data(self) -> bytes: def data(self) -> bytes: