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

Code before:
            member = "ctor"
        if member == ".cctor":
            member = "cctor"

        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, 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):

Review comment (suggestion):
```suggestion
    def format_name(class_: Tuple[str, ...], namespace: str = "", member: str = ""):
```

Code after:

        if member == ".ctor":
            member = "ctor"
        if member == ".cctor":
            member = "cctor"

        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