"""Step parsers."""
from __future__ import annotations

import re as base_re
from typing import Any, Dict, cast

import parse as base_parse
from parse_type import cfparse as base_cfparse


class StepParser:
    """Parser of the individual step."""

    def __init__(self, name: str) -> None:
        self.name = name

    def parse_arguments(self, name):
        """Get step arguments from the given step name.

        :return: `dict` of step arguments
        """
        raise NotImplementedError()  # pragma: no cover

    def is_matching(self, name):
        """Match given name with the step name."""
        raise NotImplementedError()  # pragma: no cover


class re(StepParser):
    """Regex step parser."""

    def __init__(self, name: str, *args: Any, **kwargs: Any) -> None:
        """Compile regex."""
        super().__init__(name)
        self.regex = base_re.compile(self.name, *args, **kwargs)

    def parse_arguments(self, name: str) -> dict[str, str]:
        """Get step arguments.

        :return: `dict` of step arguments
        """
        # TODO: This is a potential bug, as groupdict can return None (found with typing)
        return self.regex.match(name).groupdict()

    def is_matching(self, name: str) -> bool:
        """Match given name with the step name."""
        return bool(self.regex.match(name))


class parse(StepParser):
    """parse step parser."""

    def __init__(self, name: str, *args: Any, **kwargs: Any) -> None:
        """Compile parse expression."""
        super().__init__(name)
        self.parser = base_parse.compile(self.name, *args, **kwargs)

    def parse_arguments(self, name: str) -> dict[str, Any]:
        """Get step arguments.

        :return: `dict` of step arguments
        """
        return cast(Dict[str, Any], self.parser.parse(name).named)

    def is_matching(self, name: str) -> bool:
        """Match given name with the step name."""
        try:
            return bool(self.parser.parse(name))
        except ValueError:
            return False


class cfparse(parse):
    """cfparse step parser."""

    def __init__(self, name: str, *args: Any, **kwargs: Any) -> None:
        """Compile parse expression."""
        super(parse, self).__init__(name)
        self.parser = base_cfparse.Parser(self.name, *args, **kwargs)


class string(StepParser):
    """Exact string step parser."""

    def __init__(self, name: str) -> None:
        """Stringify"""
        name = str(name)
        super().__init__(name)

    def parse_arguments(self, name: str) -> dict:
        """No parameters are available for simple string step.

        :return: `dict` of step arguments
        """
        return {}

    def is_matching(self, name: str) -> bool:
        """Match given name with the step name."""
        return self.name == name


def get_parser(step_name: Any) -> Any:
    """Get parser by given name.

    :param step_name: name of the step to parse

    :return: step parser object
    :rtype: StepArgumentParser
    """

    support_parser_interface = hasattr(step_name, "is_matching") and hasattr(step_name, "parse_arguments")

    if support_parser_interface:
        return step_name
    else:
        return string(step_name)

@@ -49,16 +49,27 @@
 ations%0A%0A
+import abc%0A
 import r
@@ -209,16 +209,25 @@
 epParser
+(abc.ABC)
 :%0A    %22%22
@@ -331,16 +331,40 @@
 = name%0A%0A
+    @abc.abstractmethod%0A
     def 
@@ -381,33 +381,56 @@
 ments(self, name
-)
+: str) -%3E dict%5Bstr, Any%5D
 :%0A        %22%22%22Get
@@ -538,56 +538,36 @@
     
-raise NotImplementedError()  # pragma: no cover%0A
+...%0A%0A    @abc.abstractmethod
 %0A   
@@ -593,17 +593,30 @@
 lf, name
-)
+: str) -%3E bool
 :%0A      
@@ -672,55 +672,11 @@
     
-raise NotImplementedError()  # pragma: no cover
+...
 %0A%0A%0Ac
@@ -2863,19 +2863,26 @@
 Any) -%3E 
-Any
+StepParser
 :%0A    %22%22
@@ -2911,270 +2911,53 @@
 ame.
+%22%22%22
 %0A%0A    
-:param step_name: name of the step to parse%0A%0A    :return: step parser object%0A    :rtype: StepArgumentParser%0A    %22%22%22%0A%0A    support_parser_interface = hasattr(step_name, %22is_matching%22) and hasattr(step_name, %22parse_arguments%22)%0A%0A    if support_parser_interface
+if isinstance(step_name, StepParser)
 :%0A  
@@ -2983,22 +2983,9 @@
 ame%0A
-    else:%0A    
+%0A
     

Use simple inheritance check rather than duck typing checks