Repository: mandiant/capa
File: capa/features/extractors/dnfile/types.py (Python)

Code before:

    def __hash__(self):
        return hash((self.token, self.access, self.namespace, self.class_, self.member))

    def __eq__(self, other):
        return (
            self.token == other.token
            and self.access == other.access
            and self.namespace == other.namespace
            and self.class_ == other.class_
            and self.member == other.member
        )

    def __str__(self):
        return DnType.format_name(self.class_, namespace=self.namespace, member=self.member)

    def __repr__(self):
        return str(self)

    @staticmethod
    def format_name(class_: tuple, namespace: str = "", member: str = ""):
        if type(class_) == tuple:
            if len(class_) > 2:
                class_ = class_[0] + "." + "/".join(class_[1:])
            else:
                class_ = f"{class_[0]}.{class_[1]}"
        # like File::OpenRead
        name: str = f"{class_}::{member}" if member else class_
        if namespace:
            # like System.IO.File::OpenRead
            name = f"{namespace}.{name}"
        return name

class DnUnmanagedMethod:
    def __init__(self, token: int, module: str, method: str):
        self.token: int = token
        self.module: str = module
        self.method: str = method

    def __hash__(self):
        return hash((self.token, self.module, self.method))

    def __eq__(self, other):
        return self.token == other.token and self.module == other.module and self.method == other.method

    def __str__(self):
        return DnUnmanagedMethod.format_name(self.module, self.method)

    def __repr__(self):
        return str(self)


Review comment (refactor):
Please add comments here with examples e.g. like https://github.com/mandiant/capa/blob/94a8b65b480fa0a5944638b0ce3c3dbfd3737bca/capa/features/extractors/dnfile/types.py#L51-L55

Code after:

        self.member: str = member

    def __hash__(self):
        return hash((self.token, self.access, self.namespace, self.class_, self.member))

    def __eq__(self, other):
        return (
            self.token == other.token
            and self.access == other.access
            and self.namespace == other.namespace
            and self.class_ == other.class_
            and self.member == other.member
        )

    def __str__(self):
        return DnType.format_name(self.class_, namespace=self.namespace, member=self.member)

    def __repr__(self):
        return str(self)

    @staticmethod
    def format_name(class_: Tuple[str, ...], namespace: str = "", member: str = ""):
        if len(class_) > 1:
            class_str = "/".join(class_)  # Concat items in tuple, separated by a "/"
        else:
            class_str = "".join(class_)  # Convert tuple to str
        # like File::OpenRead
        name: str = f"{class_str}::{member}" if member else class_str
        if namespace:
            # like System.IO.File::OpenRead
            name = f"{namespace}.{name}"
        return name


class DnUnmanagedMethod:
    def __init__(self, token: int, module: str, method: str):
        self.token: int = token
        self.module: str = module
        self.method: str = method

    def __hash__(self):
        return hash((self.token, self.module, self.method))

    def __eq__(self, other):
        return self.token == other.token and self.module == other.module and self.method == other.method

    def __str__(self):
        return DnUnmanagedMethod.format_name(self.module, self.method)

    def __repr__(self):