# Path: src/cutadapt/modifiers.py
# class ModificationInfo:
#     """
#     An object of this class is created for each read that passes through the pipeline.
#     Any information (except the read itself) that needs to be passed from one modifier
#     to one later in the pipeline or from one modifier to the filters is recorded here.
#     """
# 
#     __slots__ = ["matches", "original_read", "cut_prefix", "cut_suffix", "is_rc"]
# 
#     def __init__(self, read):
#         self.matches = []  # type: List[Match]
#         self.original_read = read
#         self.cut_prefix = None
#         self.cut_suffix = None
#         self.is_rc = None
# 
#     def __repr__(self):
#         return (
#             "ModificationInfo("
#             f"matches={self.matches!r}, "
#             f"original_read={self.original_read}, "
#             f"cut_prefix={self.cut_prefix}, "
#             f"cut_suffix={self.cut_suffix}, "
#             f"is_rc={self.is_rc})"
#         )


from abc import ABC, abstractmethod
from .qualtrim import expected_errors
from .modifiers import ModificationInfo

    def __init__(self, max_errors: float):
        self.max_errors = max_errors

    def __repr__(self):
        return f"TooManyExpectedErrors(max_errors={self.max_errors})"

    def test(self, read, info: ModificationInfo):
        return expected_errors(read.qualities) > self.max_errors


class TooManyN(Predicate):
    """
    Select reads that have too many 'N' bases.

    Both a raw count or a proportion (relative to the sequence length) can be used.
    """

    def __init__(self, count: float):
        """
        count -- if it is below 1.0, it will be considered a proportion, and above and equal to
        1 will be considered as discarding reads with a number of N's greater than this cutoff.
        """
        assert count >= 0
        self.is_proportion = count < 1.0
        self.cutoff = count

    def __repr__(self):
        return f"TooManyN(cutoff={self.cutoff}, is_proportion={self.is_proportion})"


# Path: src/cutadapt/modifiers.py
# class ModificationInfo:
#     """
#     An object of this class is created for each read that passes through the pipeline.
#     Any information (except the read itself) that needs to be passed from one modifier
#     to one later in the pipeline or from one modifier to the filters is recorded here.
#     """
# 
#     __slots__ = ["matches", "original_read", "cut_prefix", "cut_suffix", "is_rc"]
# 
#     def __init__(self, read):
#         self.matches = []  # type: List[Match]
#         self.original_read = read
#         self.cut_prefix = None
#         self.cut_suffix = None
#         self.is_rc = None
# 
#     def __repr__(self):
#         return (
#             "ModificationInfo("
#             f"matches={self.matches!r}, "
#             f"original_read={self.original_read}, "
#             f"cut_prefix={self.cut_prefix}, "
#             f"cut_suffix={self.cut_suffix}, "
#             f"is_rc={self.is_rc})"
#         )


# Path: src/cutadapt/filters.py
from abc import ABC, abstractmethod
from .qualtrim import expected_errors
from .modifiers import ModificationInfo


    def __init__(self, max_errors: float):
        self.max_errors = max_errors

    def __repr__(self):
        return f"TooManyExpectedErrors(max_errors={self.max_errors})"

    def test(self, read, info: ModificationInfo):
        return expected_errors(read.qualities) > self.max_errors


class TooManyN(Predicate):
    """
    Select reads that have too many 'N' bases.

    Both a raw count or a proportion (relative to the sequence length) can be used.
    """

    def __init__(self, count: float):
        """
        count -- if it is below 1.0, it will be considered a proportion, and above and equal to
        1 will be considered as discarding reads with a number of N's greater than this cutoff.
        """
        assert count >= 0
        self.is_proportion = count < 1.0
        self.cutoff = count

    def __repr__(self):
        return f"TooManyN(cutoff={self.cutoff}, is_proportion={self.is_proportion})"


    def test(self, read, info: ModificationInfo):