<commit_before>import inspect
import json
import os
from inspect import FrameInfo
from typing import Dict, List, Optional

from approvaltests.approval_exception import FrameNotFound


class Namer(object):
    APPROVED = ".approved"
    RECEIVED = ".received"

    def __init__(self, extension: Optional[str] = None) -> None:
        self.extension_with_dot = extension or ".txt"

    def get_file_name(self):
        raise Exception("This class is abstract, override this method in a subclass")

    def get_directory(self):
        raise Exception("This class is abstract, override this method in a subclass")

    def get_config(self):
        raise Exception("This class is abstract, override this method in a subclass")

    def get_basename(self) -> str:
        file_name = self.get_file_name()
        subdirectory = self.get_config().get("subdirectory", "")
        return os.path.join(self.get_directory(), subdirectory, file_name)

    def get_received_filename(self, basename: Optional[str] = None) -> str:
        basename = basename or self.get_basename()
        return basename + Namer.RECEIVED + self.extension_with_dot

    def get_approved_filename(self, basename: Optional[str] = None) -> str:
        basename = basename or self.get_basename()
        return basename + Namer.APPROVED + self.extension_with_dot

    def set_extension(self, extension):
        self.extension_with_dot = extension


class StackFrameNamer(Namer):
    Directory = ""
    MethodName = ""
    ClassName = ""

    def __init__(self, extension: Optional[str] = None) -> None:
        Namer.__init__(self, extension)
        self.set_for_stack(inspect.stack(1))
        self.config = {}
        self.config_loaded = False

    def set_for_stack(self, caller: List[FrameInfo]) -> None:
        frame = self.get_test_frame(caller)<commit_msg>R mypy happier<commit_after>import inspect
import json
import os
from inspect import FrameInfo
from typing import Dict, List, Optional

from approvaltests.approval_exception import FrameNotFound


class Namer(object):
    APPROVED = ".approved"
    RECEIVED = ".received"

    def __init__(self, extension: Optional[str] = None) -> None:
        self.extension_with_dot = extension or ".txt"

    def get_file_name(self):
        raise Exception("This class is abstract, override this method in a subclass")

    def get_directory(self):
        raise Exception("This class is abstract, override this method in a subclass")

    def get_config(self):
        raise Exception("This class is abstract, override this method in a subclass")

    def get_basename(self) -> str:
        file_name = self.get_file_name()
        subdirectory = self.get_config().get("subdirectory", "")
        return os.path.join(self.get_directory(), subdirectory, file_name)

    def get_received_filename(self, basename: Optional[str] = None) -> str:
        basename = basename or self.get_basename()
        return basename + Namer.RECEIVED + self.extension_with_dot

    def get_approved_filename(self, basename: Optional[str] = None) -> str:
        basename = basename or self.get_basename()
        return basename + Namer.APPROVED + self.extension_with_dot

    def set_extension(self, extension):
        self.extension_with_dot = extension


class StackFrameNamer(Namer):
    Directory = ""
    MethodName = ""
    ClassName = ""

    def __init__(self, extension: Optional[str] = None) -> None:
        Namer.__init__(self, extension)
        self.set_for_stack(inspect.stack(1))
        self.config: Dict[str,str] = {}
        self.config_loaded = False

    def set_for_stack(self, caller: List[FrameInfo]) -> None:
        frame = self.get_test_frame(caller)
{'fraction_non_alphanumeric': 0.09820944112859468, 'fraction_numerical': 0.0005425935973955507, 'mean_word_length': 3.410287081339713, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '635156', 'n_tokens_mistral': 1097, 'n_tokens_neox': 1056, 'n_words': 288}