Skip to content

Commit

Permalink
Change linter to Ruff
Browse files Browse the repository at this point in the history
  • Loading branch information
Schamper committed Oct 27, 2024
1 parent ed1daf2 commit 494de3b
Show file tree
Hide file tree
Showing 31 changed files with 279 additions and 214 deletions.
16 changes: 8 additions & 8 deletions dissect/cstruct/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
import logging
from enum import Enum
from textwrap import dedent, indent
from types import MethodType
from typing import TYPE_CHECKING, Iterator
from typing import TYPE_CHECKING

from dissect.cstruct.bitbuffer import BitBuffer
from dissect.cstruct.types import (
Expand All @@ -30,6 +29,9 @@
from dissect.cstruct.types.packed import _struct

if TYPE_CHECKING:
from collections.abc import Iterator
from types import MethodType

Check warning on line 33 in dissect/cstruct/compiler.py

View check run for this annotation

Codecov / codecov/patch

dissect/cstruct/compiler.py#L32-L33

Added lines #L32 - L33 were not covered by tests

from dissect.cstruct.cstruct import cstruct
from dissect.cstruct.types.structure import Field

Expand Down Expand Up @@ -127,8 +129,7 @@ def generate_source(self) -> str:

code = indent(dedent(preamble).lstrip() + read_code + dedent(outro), " ")

template = f"def _read(cls, stream, context=None):\n{code}"
return template
return f"def _read(cls, stream, context=None):\n{code}"

def _generate_fields(self) -> Iterator[str]:
current_offset = 0
Expand Down Expand Up @@ -210,10 +211,9 @@ def align_to_field(field: Field) -> Iterator[str]:
else:
current_block.append(field)

if current_offset is not None and size is not None:
if not field.bits or (field.bits and bits_rollover):
current_offset += size
bits_rollover = False
if current_offset is not None and size is not None and (not field.bits or bits_rollover):
current_offset += size
bits_rollover = False

yield from flush()

Expand Down
20 changes: 11 additions & 9 deletions dissect/cstruct/cstruct.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import struct
import sys
import types
from typing import Any, BinaryIO, Iterator
from pathlib import Path
from typing import TYPE_CHECKING, Any, BinaryIO

from dissect.cstruct.exceptions import ResolveError
from dissect.cstruct.expression import Expression
Expand All @@ -27,6 +28,9 @@
Wchar,
)

if TYPE_CHECKING:
from collections.abc import Iterator

Check warning on line 32 in dissect/cstruct/cstruct.py

View check run for this annotation

Codecov / codecov/patch

dissect/cstruct/cstruct.py#L32

Added line #L32 was not covered by tests


class cstruct:
"""Main class of cstruct. All types are registered in here.
Expand Down Expand Up @@ -134,7 +138,6 @@ def __init__(self, endian: str = "<", pointer: str | None = None):
"unsigned __int32": "uint32",
"unsigned __int64": "uint64",
"unsigned __int128": "uint128",
"unsigned __int128": "uint128",

"wchar_t": "wchar",

Expand Down Expand Up @@ -233,7 +236,7 @@ def add_custom_type(
"""
self.add_type(name, self._make_type(name, (type_,), size, alignment=alignment, attrs=kwargs))

def load(self, definition: str, deftype: int = None, **kwargs) -> cstruct:
def load(self, definition: str, deftype: int | None = None, **kwargs) -> cstruct:
"""Parse structures from the given definitions using the given definition type.
Definitions can be parsed using different parsers. Currently, there's
Expand All @@ -259,7 +262,7 @@ def load(self, definition: str, deftype: int = None, **kwargs) -> cstruct:

return self

def loadfile(self, path: str, deftype: int = None, **kwargs) -> None:
def loadfile(self, path: str, deftype: int | None = None, **kwargs) -> None:
"""Load structure definitions from a file.
The given path will be read and parsed using the .load() function.
Expand All @@ -269,7 +272,7 @@ def loadfile(self, path: str, deftype: int = None, **kwargs) -> None:
deftype: The definition type to parse the definitions with.
**kwargs: Keyword arguments for parsers.
"""
with open(path) as fh:
with Path(path).open() as fh:
self.load(fh.read(), deftype, **kwargs)

def read(self, name: str, stream: BinaryIO) -> Any:
Expand Down Expand Up @@ -354,10 +357,10 @@ def _make_array(self, type_: MetaType, num_entries: int | Expression | None) ->

return self._make_type(name, bases, size, alignment=type_.alignment, attrs=attrs)

def _make_int_type(self, name: str, size: int, signed: bool, *, alignment: int = None) -> type[Int]:
def _make_int_type(self, name: str, size: int, signed: bool, *, alignment: int | None = None) -> type[Int]:
return self._make_type(name, (Int,), size, alignment=alignment, attrs={"signed": signed})

def _make_packed_type(self, name: str, packchar: str, base: type, *, alignment: int = None) -> type[Packed]:
def _make_packed_type(self, name: str, packchar: str, base: type, *, alignment: int | None = None) -> type[Packed]:
return self._make_type(
name,
(base, Packed),
Expand Down Expand Up @@ -414,8 +417,7 @@ def ctypes(structure: Structure) -> _ctypes.Structure:
t = ctypes_type(field.type)
fields.append((field.name, t))

tt = type(structure.name, (_ctypes.Structure,), {"_fields_": fields})
return tt
return type(structure.name, (_ctypes.Structure,), {"_fields_": fields})

Check warning on line 420 in dissect/cstruct/cstruct.py

View check run for this annotation

Codecov / codecov/patch

dissect/cstruct/cstruct.py#L420

Added line #L420 was not covered by tests


def ctypes_type(type_: MetaType) -> Any:
Expand Down
13 changes: 6 additions & 7 deletions dissect/cstruct/expression.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

import string
from typing import TYPE_CHECKING, Callable
from typing import TYPE_CHECKING, Callable, ClassVar

from dissect.cstruct.exceptions import ExpressionParserError, ExpressionTokenizerError

Expand All @@ -21,8 +21,7 @@ def __init__(self, expression: str):
def equal(self, token: str, expected: str | set[str]) -> bool:
if isinstance(expected, set):
return token in expected
else:
return token == expected
return token == expected

def alnum(self, token: str) -> bool:
return token.isalnum()
Expand Down Expand Up @@ -88,7 +87,7 @@ def tokenize(self) -> list[str]:
continue

# If token is a single digit, keep looping over expression and build the number
elif self.match(self.digit, consume=False, append=False):
if self.match(self.digit, consume=False, append=False):
token += self.get_token()
self.consume()

Expand Down Expand Up @@ -154,7 +153,7 @@ def tokenize(self) -> list[str]:
class Expression:
"""Expression parser for calculations in definitions."""

binary_operators = {
binary_operators: ClassVar[dict[str, Callable[[int, int], int]]] = {
"|": lambda a, b: a | b,
"^": lambda a, b: a ^ b,
"&": lambda a, b: a & b,
Expand All @@ -167,12 +166,12 @@ class Expression:
"%": lambda a, b: a % b,
}

unary_operators = {
unary_operators: ClassVar[dict[str, Callable[[int], int]]] = {
"u": lambda a: -a,
"~": lambda a: ~a,
}

precedence_levels = {
precedence_levels: ClassVar[dict[str, int]] = {
"|": 0,
"^": 1,
"&": 2,
Expand Down
38 changes: 15 additions & 23 deletions dissect/cstruct/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import ast
import re
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Any

from dissect.cstruct import compiler
from dissect.cstruct.exceptions import (
Expand Down Expand Up @@ -33,7 +33,7 @@ def parse(self, data: str) -> None:
Args:
data: Data to parse definitions from, usually a string.
"""
raise NotImplementedError()
raise NotImplementedError

Check warning on line 36 in dissect/cstruct/parser.py

View check run for this annotation

Codecov / codecov/patch

dissect/cstruct/parser.py#L36

Added line #L36 was not covered by tests


class TokenParser(Parser):
Expand Down Expand Up @@ -119,10 +119,8 @@ def _enum(self, tokens: TokenConsumer) -> None:
val = val.strip()
if not key:
continue
if not val:
val = nextval
else:
val = Expression(self.cstruct, val).evaluate(values)

val = nextval if not val else Expression(self.cstruct, val).evaluate(values)

if enumtype == "flag":
high_bit = val.bit_length() - 1
Expand Down Expand Up @@ -243,7 +241,7 @@ def _lookup(self, tokens: TokenConsumer) -> None:
# Dirty trick because the regex expects a ; but we don't want it to be part of the value
m = pattern.match(ltok.value + ";")
d = ast.literal_eval(m.group(2))
self.cstruct.lookups[m.group(1)] = dict([(self.cstruct.consts[k], v) for k, v in d.items()])
self.cstruct.lookups[m.group(1)] = {self.cstruct.consts[k]: v for k, v in d.items()}

def _parse_field(self, tokens: TokenConsumer) -> Field:
type_ = None
Expand Down Expand Up @@ -279,10 +277,7 @@ def _parse_field_type(self, type_: MetaType, name: str) -> tuple[MetaType, str,

if count_expression is not None:
# Poor mans multi-dimensional array by abusing the eager regex match of count
if "][" in count_expression:
counts = count_expression.split("][")
else:
counts = [count_expression]
counts = count_expression.split("][") if "][" in count_expression else [count_expression]

for count in reversed(counts):
if count == "":
Expand Down Expand Up @@ -315,8 +310,7 @@ def _names(self, tokens: TokenConsumer) -> list[str]:
if ntoken == self.TOK.NAME:
names.append(ntoken.value.strip())
elif ntoken == self.TOK.DEFS:
for name in ntoken.value.strip().split(","):
names.append(name.strip())
names.extend([name.strip() for name in ntoken.value.strip().split(",")])

return names

Expand All @@ -333,8 +327,8 @@ def _replacer(match: re.Match) -> str:
# it means we have captured a non-quoted (real) comment string.
if comment := match.group(2):
return "\n" * comment.count("\n") # so we will return empty to remove the comment
else: # otherwise, we will return the 1st group
return match.group(1) # captured quoted-string
# otherwise, we will return the 1st group
return match.group(1) # captured quoted-string

return regex.sub(_replacer, string)

Expand Down Expand Up @@ -429,10 +423,8 @@ def _enums(self, data: str) -> None:
val = val.strip()
if not key:
continue
if not val:
val = nextval
else:
val = Expression(self.cstruct, val).evaluate()

val = nextval if not val else Expression(self.cstruct, val).evaluate()

Check warning on line 427 in dissect/cstruct/parser.py

View check run for this annotation

Codecov / codecov/patch

dissect/cstruct/parser.py#L427

Added line #L427 was not covered by tests

if enumtype == "flag":
high_bit = val.bit_length() - 1
Expand Down Expand Up @@ -535,7 +527,7 @@ def _lookups(self, data: str, consts: dict[str, int]) -> None:

for t in r:
d = ast.literal_eval(t.group(2))
self.cstruct.lookups[t.group(1)] = dict([(self.cstruct.consts[k], v) for k, v in d.items()])
self.cstruct.lookups[t.group(1)] = {self.cstruct.consts[k]: v for k, v in d.items()}

Check warning on line 530 in dissect/cstruct/parser.py

View check run for this annotation

Codecov / codecov/patch

dissect/cstruct/parser.py#L530

Added line #L530 was not covered by tests

def parse(self, data: str) -> None:
self._constants(data)
Expand All @@ -552,13 +544,13 @@ def __init__(self, token: str, value: str, match: re.Match):
self.value = value
self.match = match

def __eq__(self, other):
def __eq__(self, other: object) -> bool:
if isinstance(other, Token):
other = other.token

return self.token == other

def __ne__(self, other):
def __ne__(self, other: object) -> bool:
return not self == other

def __repr__(self):
Expand All @@ -571,7 +563,7 @@ def __init__(self):
self.lookup: dict[str, str] = {}
self.patterns: dict[str, re.Pattern] = {}

def __getattr__(self, attr: str):
def __getattr__(self, attr: str) -> str | Any:
try:
return self.lookup[attr]
except AttributeError:
Expand Down
30 changes: 19 additions & 11 deletions dissect/cstruct/types/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def _read(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> BaseT
stream: The stream to read from.
context: Optional reading context.
"""
raise NotImplementedError()
raise NotImplementedError

Check warning on line 125 in dissect/cstruct/types/base.py

View check run for this annotation

Codecov / codecov/patch

dissect/cstruct/types/base.py#L125

Added line #L125 was not covered by tests

def _read_array(cls, stream: BinaryIO, count: int, context: dict[str, Any] | None = None) -> list[BaseType]:
"""Internal function for reading array values.
Expand All @@ -136,11 +136,8 @@ def _read_array(cls, stream: BinaryIO, count: int, context: dict[str, Any] | Non
"""
if count == EOF:
result = []
while True:
try:
result.append(cls._read(stream, context))
except EOFError:
break
while not _is_eof(stream):
result.append(cls._read(stream, context))
return result

return [cls._read(stream, context) for _ in range(count)]
Expand All @@ -154,10 +151,10 @@ def _read_0(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> lis
stream: The stream to read from.
context: Optional reading context.
"""
raise NotImplementedError()
raise NotImplementedError

Check warning on line 154 in dissect/cstruct/types/base.py

View check run for this annotation

Codecov / codecov/patch

dissect/cstruct/types/base.py#L154

Added line #L154 was not covered by tests

def _write(cls, stream: BinaryIO, data: Any) -> int:
raise NotImplementedError()
raise NotImplementedError

Check warning on line 157 in dissect/cstruct/types/base.py

View check run for this annotation

Codecov / codecov/patch

dissect/cstruct/types/base.py#L157

Added line #L157 was not covered by tests

def _write_array(cls, stream: BinaryIO, array: list[BaseType]) -> int:
"""Internal function for writing arrays.
Expand All @@ -179,7 +176,7 @@ def _write_0(cls, stream: BinaryIO, array: list[BaseType]) -> int:
stream: The stream to read from.
array: The array to write.
"""
return cls._write_array(stream, array + [cls.__default__()])
return cls._write_array(stream, [*array, cls.__default__()])


class _overload:
Expand All @@ -200,8 +197,7 @@ def __init__(self, func: Callable[[Any], Any]) -> None:
def __get__(self, instance: BaseType | None, owner: MetaType) -> Callable[[Any], bytes]:
if instance is None:
return functools.partial(self.func, owner)
else:
return functools.partial(self.func, instance.__class__, value=instance)
return functools.partial(self.func, instance.__class__, value=instance)


class BaseType(metaclass=MetaType):
Expand Down Expand Up @@ -283,5 +279,17 @@ def _is_buffer_type(value: Any) -> bool:
return isinstance(value, (bytes, memoryview, bytearray))


def _is_eof(stream: BinaryIO) -> bool:
"""Check if the stream has reached EOF."""
pos = stream.tell()
stream.read(1)

if stream.tell() == pos:
return True

stream.seek(pos)
return False


# As mentioned in the BaseType class, we correctly set the type here
MetaType.ArrayType = Array
2 changes: 1 addition & 1 deletion dissect/cstruct/types/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def _write_array(cls, stream: BinaryIO, array: list[Enum]) -> int:

def _write_0(cls, stream: BinaryIO, array: list[BaseType]) -> int:
data = [entry.value if isinstance(entry, Enum) else entry for entry in array]
return cls._write_array(stream, data + [cls.type.__default__()])
return cls._write_array(stream, [*data, cls.type.__default__()])


def _fix_alias_members(cls: type[Enum]) -> None:
Expand Down
5 changes: 2 additions & 3 deletions dissect/cstruct/types/leb128.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@ def _read(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> LEB12
if (b & 0x80) == 0:
break

if cls.signed:
if b & 0x40 != 0:
result |= ~0 << shift
if cls.signed and b & 0x40 != 0:
result |= ~0 << shift

return cls.__new__(cls, result)

Expand Down
Loading

0 comments on commit 494de3b

Please sign in to comment.