Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various fixes and additions #20

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.7.0]
### Changed
- UnionBlock failing to flush if u_node size is defined by FieldType
- BytesBuffer failing to seek to offset 0(start of buffer)
- BytesArrayBuffer failing to initialize \_pos on instantiation

### Added
- more complete definition for wav audio file
- ability to use BlockDef.str_to_name as a class method
- util.desc_variant has the ability to verify replacements are valid based on field sizes
- util.desc_variant no longer needs name of field specified(taken from replacement desc)

## [1.5.4]
### Changed
- Update build config for Python 3.9.
Expand Down
3 changes: 3 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3 :: Only",
],
zip_safe=False,
Expand Down
4 changes: 2 additions & 2 deletions supyr_struct/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@
# ##############
__author__ = "Sigmmma"
# YYYY.MM.DD
__date__ = "2020.10.30"
__version__ = (1, 5, 4)
__date__ = "2025.01.18"
__version__ = (1, 7, 0)
__website__ = "https://github.com/Sigmmma/supyr_struct"


Expand Down
19 changes: 8 additions & 11 deletions supyr_struct/blocks/array_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from sys import getsizeof

from supyr_struct.blocks.block import Block
from supyr_struct.blocks.list_block import ListBlock
from supyr_struct.blocks.list_block import ListBlock, repeat
from supyr_struct.defs.constants import NAME, UNNAMED, NAME_MAP
from supyr_struct.exceptions import DescEditError, DescKeyError
from supyr_struct.buffer import get_rawdata_context
Expand Down Expand Up @@ -37,7 +37,7 @@ def __init__(self, desc, parent=None, init_attrs=None, **kwargs):
self.parse(init_attrs=init_attrs, **kwargs)
else:
# populate the listblock with the right number of fields
list.__init__(self, [None]*self.get_size())
list.__init__(self, repeat(None, self.get_size()))

def __sizeof__(self, seenset=None):
'''
Expand Down Expand Up @@ -98,8 +98,6 @@ def __setitem__(self, index, new_value):
# a Block, set its parent attribute to this Block.
if isinstance(new_value, Block):
new_value.parent = self

desc = object.__getattribute__(self, 'desc')
elif isinstance(index, slice):
# if this is an array, dont worry about
# the descriptor since its list indexes
Expand Down Expand Up @@ -150,10 +148,9 @@ def __delitem__(self, index):
# the descriptor since its list indexes
# aren't attributes, but instanced objects
start, stop, step = index.indices(len(self))
step = -step if step < 0 else step
if start < stop:
start, stop = stop, start
if step > 0:
step = -step

list.__delitem__(self, index)
self.set_size()
Expand Down Expand Up @@ -239,7 +236,7 @@ def extend(self, new_attrs, **kwargs):
index = len(self)

# create new, empty indices
list.extend(self, [None]*new_attrs)
list.extend(self, repeat(None, new_attrs))
# read new sub_structs into the empty indices
for i in range(index, index + new_attrs):
attr_f_type.parser(attr_desc, parent=self,
Expand Down Expand Up @@ -705,10 +702,10 @@ def parse(self, **kwargs):
# parsing/initializing all array elements, so clear and resize
list.__delitem__(self, slice(None, None, None))
if initdata is not None:
list.extend(self, [None]*len(initdata))
list.extend(self, repeat(None, len(initdata)))
self.set_size() # update the size to the initdata length
else:
list.extend(self, [None]*self.get_size())
list.extend(self, repeat(None, self.get_size()))

if rawdata is not None:
# parse the ArrayBlock from raw data
Expand Down Expand Up @@ -774,7 +771,7 @@ class PArrayBlock(ArrayBlock):
node it describes to be stored as well as a
reference to whatever Block it is parented to
'''
__slots__ = ('STEPTREE')
__slots__ = ('STEPTREE', )

def __init__(self, desc, parent=None, steptree=None,
init_attrs=None, **kwargs):
Expand All @@ -798,7 +795,7 @@ def __init__(self, desc, parent=None, steptree=None,
self.parse(init_attrs=init_attrs, **kwargs)
else:
# populate the listblock with the right number of fields
list.__init__(self, [None]*self.get_size())
list.__init__(self, repeat(None, self.get_size()))

def __sizeof__(self, seenset=None):
'''
Expand Down
23 changes: 10 additions & 13 deletions supyr_struct/blocks/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,11 +252,7 @@ def __sizeof__(self, seenset=None):
return 0

seenset.add(id(self))
bytes_total = object.__sizeof__(self)

desc = object.__getattribute__(self, 'desc')

return bytes_total
return object.__sizeof__(self)

def __binsize__(self, node, substruct=False):
'''You must override this method'''
Expand Down Expand Up @@ -312,16 +308,19 @@ def get_desc(self, desc_key, attr_name=None):
"descriptor of '%s'.") %
(desc_key, desc.get('NAME')))

def get_root(node):
def get_root(self):
'''Navigates up the given node and returns the root node.'''
# rather than name the function argument 'self' it's slightly
# faster to just name it 'root' and not have to do 'root = self'
try:
while node.parent:
node = node.parent
while self.parent:
self = self.parent # pylint: disable=W0642 # SHUTUP PYLINT
# for the sake of minimal operations and
# keeping the method signature clean, we
# will be evil and redefine self
except AttributeError:
pass
return node
return self

def get_neighbor(self, path, node=None):
'''
Expand Down Expand Up @@ -680,12 +679,10 @@ def serialize(self, **kwargs):
else:
parent_tag = self.get_root()

if "calc_pointers" in kwargs:
calc_pointers = kwargs["calc_pointers"]
calc_pointers = kwargs.get("calc_pointers", True)
if isinstance(parent_tag, supyr_struct.tag.Tag):
calc_pointers = parent_tag.calc_pointers
else:
calc_pointers = True
parent_tag = None

# convert string attr_indexes to ints
Expand Down Expand Up @@ -820,7 +817,7 @@ def parent(self, new_val):
except TypeError:
# some object types don't support __weakref__ so we have to
# wrap them in something that our getter will still work with
new_val = lambda val=new_val: val
new_val = lambda val=new_val: val # pylint: disable=C3001

# we just need to set self._parent to the new wrapped value.
# we want to do this as fast as possible, so we're going to
Expand Down
12 changes: 5 additions & 7 deletions supyr_struct/blocks/data_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,12 @@ def __sizeof__(self, seenset=None):

seenset.add(id(self))
data = self.data
if isinstance(data, Block):
bytes_total = object.__sizeof__(self) + data.__sizeof__(seenset)
else:
bytes_total = object.__sizeof__(self) + getsizeof(data)

desc = object.__getattribute__(self, 'desc')

return bytes_total
return object.__sizeof__(self) + (
data.__sizeof__(seenset)
if isinstance(data, Block) else
getsizeof(data)
)

def __copy__(self):
'''
Expand Down
37 changes: 19 additions & 18 deletions supyr_struct/blocks/list_block.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'''
'''
from copy import deepcopy
from itertools import repeat, takewhile
from sys import getsizeof

from supyr_struct.blocks.block import Block
Expand Down Expand Up @@ -46,7 +47,7 @@ def __init__(self, desc, parent=None, init_attrs=None, **kwargs):
self.parse(init_attrs=init_attrs, **kwargs)
else:
# populate the listblock with the right number of fields
list.__init__(self, [None]*desc['ENTRIES'])
list.__init__(self, repeat(None, desc['ENTRIES']))

def __str__(self, **kwargs):
'''
Expand Down Expand Up @@ -214,7 +215,7 @@ def __deepcopy__(self, memo):

# clear the Block so it can be populated
list.__delitem__(dup_block, slice(None, None, None))
list.extend(dup_block, [None]*len(self))
list.extend(dup_block, repeat(None, len(self)))

# populate the duplicate
for i in range(len(self)):
Expand Down Expand Up @@ -248,8 +249,6 @@ def __sizeof__(self, seenset=None):
seenset.add(id(self))
bytes_total = list.__sizeof__(self)

desc = object.__getattribute__(self, 'desc')

for i in range(len(self)):
item = list.__getitem__(self, i)
if not id(item) in seenset:
Expand All @@ -268,9 +267,9 @@ def __getitem__(self, index):

If index is a string, returns self.__getattr__(index)
'''
if isinstance(index, str):
return self.__getattr__(index)
return list.__getitem__(self, index)
return (self.__getattr__(index) if isinstance(index, str) else
list.__getitem__(self, index)
)

def __setitem__(self, index, new_value):
'''
Expand Down Expand Up @@ -299,8 +298,7 @@ def __setitem__(self, index, new_value):
'''
if isinstance(index, int):
# handle accessing negative indexes
if index < 0:
index += len(self)
index = index + len(self) if index < 0 else index

assert not self.assert_is_valid_field_value(index, new_value)
list.__setitem__(self, index, new_value)
Expand Down Expand Up @@ -331,10 +329,9 @@ def __setitem__(self, index, new_value):

elif isinstance(index, slice):
start, stop, step = index.indices(len(self))
step = -step if step < 0 else step
if start > stop:
start, stop = stop, start
if step < 0:
step = -step

assert hasattr(new_value, '__iter__'), (
"must assign iterable to extended slice")
Expand Down Expand Up @@ -422,8 +419,14 @@ def index_by_id(self, node):
Returns the index that node is in.
Raises ValueError if node can not be found.
'''
return [id(list.__getitem__(self, i)) for
i in range(len(self))].index(id(node))
index_finder = takewhile(
id(node).__ne__, map(id, self)
)
index = sum(map(bool, index_finder))
if index < len(self):
return index

raise ValueError("Item '%s' is not in the list" % node)

def get_size(self, attr_index=None, **context):
'''
Expand Down Expand Up @@ -803,7 +806,7 @@ def parse(self, **kwargs):
if kwargs.get("clear", True):
# parsing/initializing all attributes, so clear the block
# and create as many elements as it needs to hold
list.__init__(self, [None]*desc['ENTRIES'])
list.__init__(self, repeat(None, desc['ENTRIES']))

if rawdata is not None:
# parse the ListBlock from raw data
Expand Down Expand Up @@ -868,7 +871,7 @@ class PListBlock(ListBlock):
node it describes to be stored as well as a
reference to whatever Block it is parented to.
'''
__slots__ = ('STEPTREE')
__slots__ = ('STEPTREE', )

def __init__(self, desc, parent=None, steptree=None,
init_attrs=None, **kwargs):
Expand All @@ -892,7 +895,7 @@ def __init__(self, desc, parent=None, steptree=None,
self.parse(init_attrs=init_attrs, **kwargs)
else:
# populate the listblock with the right number of fields
list.__init__(self, [None]*desc['ENTRIES'])
list.__init__(self, repeat(None, desc['ENTRIES']))

def __sizeof__(self, seenset=None):
'''
Expand Down Expand Up @@ -920,8 +923,6 @@ def __sizeof__(self, seenset=None):
seenset.add(id(steptree))
bytes_total += getsizeof(steptree)

desc = object.__getattribute__(self, 'desc')

for i in range(len(self)):
item = list.__getitem__(self, i)
if not id(item) in seenset:
Expand Down
4 changes: 1 addition & 3 deletions supyr_struct/blocks/union_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,6 @@ def __sizeof__(self, seenset=None):
seenset.add(id(self))
bytes_total = object.__sizeof__(self) + getsizeof(self.u_node)

desc = object.__getattribute__(self, 'desc')

return bytes_total

def __binsize__(self, node, substruct=False):
Expand Down Expand Up @@ -387,7 +385,7 @@ def flush(self):
# If they are smaller, some of the most significant bytes
# arent used, which in big endian are the first bytes.
u_type.serializer(u_node, self, None, self, 0,
desc.get(SIZE) - u_desc.get(SIZE))
desc.get(SIZE, 0) - u_desc.get(SIZE, u_type.size))
else:
u_type.serializer(u_node, self, None, self)

Expand Down
5 changes: 4 additions & 1 deletion supyr_struct/blocks/void_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ def __init__(self, desc=None, parent=None, **kwargs):
object.__setattr__(self, "desc", desc)
self.parent = parent

def set_size(self, new_value, attr_index=None, **context):
pass

def __copy__(self):
'''
Creates a copy of this Block which references
Expand Down Expand Up @@ -125,4 +128,4 @@ def get_size(self, attr_index=None, **context):

def parse(self, **kwargs):
'''VoidBlocks have nothing to parse. Does nothing.'''
pass
pass # pylint: disable=W0107 # removing pass here would look horrible
Loading