# Path: src/cutadapt/align.py
# START_WITHIN_SEQ1 = 1
# START_WITHIN_SEQ2 = 2
# STOP_WITHIN_SEQ1 = 4
# STOP_WITHIN_SEQ2 = 8
# SEMIGLOBAL = 15
#     REFERENCE_START = 1  # a prefix of the reference may be skipped at no cost
#     QUERY_START = 2  # a prefix of the query may be skipped at no cost
#     REFERENCE_END = 4  # a suffix of the reference may be skipeed at no cost
#     QUERY_STOP = 8  # a suffix of the query may be skipeed at no cost
#     SEMIGLOBAL = 15  # all of the above
# class EndSkip(IntFlag):
# def edit_distance(s: str, t: str) -> int:
# def hamming_sphere(s: str, k: int) -> Iterator[str]:
# def hamming_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:
# def naive_edit_environment(s: str, k: int) -> Iterator[str]:
# def edit_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:
# def slow_edit_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:


import logging
from enum import IntFlag
from collections import defaultdict
from typing import Optional, Tuple, Sequence, Dict, Any, List, Union
from abc import ABC, abstractmethod
from .align import (
    EndSkip,
    Aligner,
    PrefixComparer,
    SuffixComparer,
    edit_environment,
    hamming_environment,
)
        # The locate function takes care of uppercasing the sequence
        alignment = self.aligner.locate(sequence)
        if self._debug:
            try:
                print(self.aligner.dpmatrix)  # pragma: no cover
            except AttributeError:
                pass
        if alignment is None:
            return None
        return RemoveAfterMatch(*alignment, adapter=self, sequence=sequence)  # type: ignore

    def spec(self) -> str:
        return f"{self.sequence}X"


class PrefixAdapter(NonInternalFrontAdapter):
    """An anchored 5' adapter"""

    description = "anchored 5'"
    allows_partial_matches = False

    def __init__(self, sequence: str, *args, **kwargs):
        kwargs["min_overlap"] = len(sequence)
        super().__init__(sequence, *args, **kwargs)

    def descriptive_identifier(self) -> str:
        return "anchored_five_prime"

    def _aligner(self):
        if not self.indels:  # TODO or if error rate allows 0 errors anyway

# Path: src/cutadapt/align.py
# START_WITHIN_SEQ1 = 1
# START_WITHIN_SEQ2 = 2
# STOP_WITHIN_SEQ1 = 4
# STOP_WITHIN_SEQ2 = 8
# SEMIGLOBAL = 15
#     REFERENCE_START = 1  # a prefix of the reference may be skipped at no cost
#     QUERY_START = 2  # a prefix of the query may be skipped at no cost
#     REFERENCE_END = 4  # a suffix of the reference may be skipeed at no cost
#     QUERY_STOP = 8  # a suffix of the query may be skipeed at no cost
#     SEMIGLOBAL = 15  # all of the above
# class EndSkip(IntFlag):
# def edit_distance(s: str, t: str) -> int:
# def hamming_sphere(s: str, k: int) -> Iterator[str]:
# def hamming_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:
# def naive_edit_environment(s: str, k: int) -> Iterator[str]:
# def edit_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:
# def slow_edit_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:


# Path: src/cutadapt/adapters.py
import logging
from enum import IntFlag
from collections import defaultdict
from typing import Optional, Tuple, Sequence, Dict, Any, List, Union
from abc import ABC, abstractmethod
from .align import (
    EndSkip,
    Aligner,
    PrefixComparer,
    SuffixComparer,
    edit_environment,
    hamming_environment,
)

        # The locate function takes care of uppercasing the sequence
        alignment = self.aligner.locate(sequence)
        if self._debug:
            try:
                print(self.aligner.dpmatrix)  # pragma: no cover
            except AttributeError:
                pass
        if alignment is None:
            return None
        return RemoveAfterMatch(*alignment, adapter=self, sequence=sequence)  # type: ignore

    def spec(self) -> str:
        return f"{self.sequence}X"


class PrefixAdapter(NonInternalFrontAdapter):
    """An anchored 5' adapter"""

    description = "anchored 5'"
    allows_partial_matches = False

    def __init__(self, sequence: str, *args, **kwargs):
        kwargs["min_overlap"] = len(sequence)
        super().__init__(sequence, *args, **kwargs)

    def descriptive_identifier(self) -> str:
        return "anchored_five_prime"

    def _aligner(self):
        if not self.indels:  # TODO or if error rate allows 0 errors anyway

            return PrefixComparer(