Skip to content

Match Stage

The Match stage is the third step in the Pipe lifecycle (after optional Setup and Condition). It is executed only if all previous Conditions have passed.

While Conditions check for structural integrity (type and size), the Match stage focuses on semantic validation - ensuring the content of the data follows a specific pattern or format.

Execution Rule

The Match stage is the bridge between "is this data the right shape?" and "is this data the right content?". It is primarily powered by Regular Expressions (Regex) and format-specific validators.


Best Practices

Combine with Conditions

Use conditions for structural validation, then match for content:

email={
    "type": str,
    "conditions": {Pipe.Condition.MaxLength: 64},  # Structure
    "matches": {Pipe.Match.Format.Email: None}      # Content
}

Use Appropriate Validators

Choose the right validator for your use case:

  • Email: Use Match.Format.Email
  • URL: Use Match.Web.URL
  • Phone: Use Match.Format.E164Phone
  • Custom patterns: Use Match.Regex.FullMatch or Match.Regex.Search

Regex Performance

Complex regex patterns can be slow. Test performance with realistic data:

# Simple and fast
r"^\d{5}$"

# Complex and potentially slow
r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$"

Run conditions before match to increase performance:

email={
    "type": str,
    "conditions": {Pipe.Condition.MaxLength: 64},  # Structure
    "matches": {Pipe.Match.Format.Email: None}      # Content
}

Case Sensitivity

Most match handlers are case-sensitive.


Technical Reference

The following section is automatically generated from the source code, detailing the available condition handlers and their configurations.

Match

Central registry for all match handler units.

This class provides a convenient way to access different match handlers (e.g., Text, Regex, Web) from a single location.

Source code in pipeline/handlers/match_handler/match.py
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Match:
    """
    Central registry for all match handler units.

    This class provides a convenient way to access different match handlers
    (e.g., Text, Regex, Web) from a single location.
    """
    Text: ClassVar[Type[MatchText]] = MatchText
    Regex: ClassVar[Type[MatchRegex]] = MatchRegex

    Web: ClassVar[Type[MatchWeb]] = MatchWeb
    Network: ClassVar[Type[MatchNetwork]] = MatchNetwork

    Time: ClassVar[Type[MatchTime]] = MatchTime
    Localization: ClassVar[Type[MatchLocalization]] = MatchLocalization

    Format: ClassVar[Type[MatchFormat]] = MatchFormat
    Encoding: ClassVar[Type[MatchEncoding]] = MatchEncoding

MatchEncoding

Registry for encoding-related match handlers.

Includes handlers for Base64, JSON, etc.

Source code in pipeline/handlers/match_handler/units/match_encoding.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class MatchEncoding:
    """
    Registry for encoding-related match handlers.

    Includes handlers for Base64, JSON, etc.
    """
    class Base64(MatchHandler[str, None]):
        """Checks if string is valid Base64 encoded"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT: lambda _: "Invalid Base64 encoding."
        }

        def query(self):
            return self.fullmatch(
                r"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"
            )

    class JSON(MatchHandler[str, None]):
        """Validates that a string is a correctly formatted JSON object or array"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT: lambda _: "String is not valid JSON."
        }

        def query(self):
            try:
                json.loads(self.value)

                return True
            except (ValueError, TypeError):
                return False

Base64

Bases: MatchHandler[str, None]

Checks if string is valid Base64 encoded

Source code in pipeline/handlers/match_handler/units/match_encoding.py
15
16
17
18
19
20
21
22
23
24
25
26
class Base64(MatchHandler[str, None]):
    """Checks if string is valid Base64 encoded"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT: lambda _: "Invalid Base64 encoding."
    }

    def query(self):
        return self.fullmatch(
            r"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"
        )

JSON

Bases: MatchHandler[str, None]

Validates that a string is a correctly formatted JSON object or array

Source code in pipeline/handlers/match_handler/units/match_encoding.py
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class JSON(MatchHandler[str, None]):
    """Validates that a string is a correctly formatted JSON object or array"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT: lambda _: "String is not valid JSON."
    }

    def query(self):
        try:
            json.loads(self.value)

            return True
        except (ValueError, TypeError):
            return False

MatchFormat

Registry for format-related match handlers.

Includes handlers for Email, UUID, HexColor, etc.

Source code in pipeline/handlers/match_handler/units/match_format.py
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
class MatchFormat:
    """
    Registry for format-related match handlers.

    Includes handlers for Email, UUID, HexColor, etc.
    """
    class Email(MatchHandler[str, None]):
        """Accepts email addresses with standard user, domain, and TLD parts"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _:
                "Invalid email address format (e.g., 'user@example.com')."
        }

        def query(self):
            return self.fullmatch(
                r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"
            )

    class UUID(MatchHandler[str, None]):
        """Validates 36-character hexadecimal unique identifiers (8-4-4-4-12)"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {HandlerMode.ROOT: lambda _: "Invalid UUID format."}

        def query(self):
            return self.fullmatch(
                r"^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$", re.IGNORECASE
            )

    class HexColor(MatchHandler[str, None]):
        """Accepts hex colors in 3 or 6 digit formats (e.g., #F00, #FF0000)"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _: "Must be a valid hex color code (e.g., #FFFFFF)."
        }

        def query(self):
            return self.fullmatch(r"^#(?:[0-9a-fA-F]{3}){1,2}$")

    class E164Phone(MatchHandler[str, None]):
        """International phone numbers in E.164 format (e.g., +1234567890)"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _:
                "Invalid phone number format. Must use international format (e.g., '+1234567890')."
        }

        def query(self):
            return self.fullmatch(r"^\+[1-9]\d{1,14}$")

    class Password(MatchHandler[str, str]):
        """Validates password strength based on three policies: RELAXED, NORMAL, or STRICT.

        Policies:
        - RELAXED: 6-64 chars, 1 uppercase, 1 lowercase.
        - NORMAL: 6-64 chars, 1 uppercase, 1 lowercase, 1 digit.
        - STRICT: 6-64 chars, 1 uppercase, 1 lowercase, 1 digit, 1 special character.

        Requires a policy argument (e.g., Match.Format.Password.NORMAL)
        """
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        RELAXED = "relaxed"
        NORMAL = "normal"
        STRICT = "strict"

        ERROR_MESSAGE = {
            RELAXED:
                "Password too weak. Required: 6-64 characters, at least 1 uppercase and 1 lowercase letter.",
            NORMAL:
                "Password too weak. Required: 6-64 characters, at least 1 uppercase, 1 lowercase, and 1 digit.",
            STRICT:
                "Password too weak. Required: 6-64 characters, at least 1 uppercase, 1 lowercase, 1 digit, and 1 special character."
        }

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda self: self.ERROR_MESSAGE[self.argument]  # type: ignore
        }

        def query(self):
            if self.argument == self.RELAXED:
                # Min 6, Max 64, 1 Upper, 1 Lower
                pattern = r"^(?=.*[a-z])(?=.*[A-Z]).{6,64}$"
            elif self.argument == self.NORMAL:
                # Min 6, Max 64, 1 Upper, 1 Lower, 1 Digit
                pattern = r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{6,64}$"
            elif self.argument == self.STRICT:
                # Min 6, Max 64, 1 Upper, 1 Lower, 1 Digit, 1 Special
                pattern = r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*(),.?\":{}|<>]).{6,64}$"
            else:
                raise HandlerException(
                    f"{self.argument} is not a valid password policy. Use Password.RELAXED, Password.NORMAL, or Password.STRICT."
                )

            return self.fullmatch(pattern)

    class JWT(MatchHandler[str, None]):
        """Validates the structure of a JSON Web Token (header.payload.signature)"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {HandlerMode.ROOT: lambda _: "Invalid JWT format."}

        def query(self):
            return self.fullmatch(
                r"^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+$"
            )

E164Phone

Bases: MatchHandler[str, None]

International phone numbers in E.164 format (e.g., +1234567890)

Source code in pipeline/handlers/match_handler/units/match_format.py
55
56
57
58
59
60
61
62
63
64
65
66
class E164Phone(MatchHandler[str, None]):
    """International phone numbers in E.164 format (e.g., +1234567890)"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _:
            "Invalid phone number format. Must use international format (e.g., '+1234567890')."
    }

    def query(self):
        return self.fullmatch(r"^\+[1-9]\d{1,14}$")

Email

Bases: MatchHandler[str, None]

Accepts email addresses with standard user, domain, and TLD parts

Source code in pipeline/handlers/match_handler/units/match_format.py
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Email(MatchHandler[str, None]):
    """Accepts email addresses with standard user, domain, and TLD parts"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _:
            "Invalid email address format (e.g., 'user@example.com')."
    }

    def query(self):
        return self.fullmatch(
            r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"
        )

HexColor

Bases: MatchHandler[str, None]

Accepts hex colors in 3 or 6 digit formats (e.g., #F00, #FF0000)

Source code in pipeline/handlers/match_handler/units/match_format.py
43
44
45
46
47
48
49
50
51
52
53
class HexColor(MatchHandler[str, None]):
    """Accepts hex colors in 3 or 6 digit formats (e.g., #F00, #FF0000)"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _: "Must be a valid hex color code (e.g., #FFFFFF)."
    }

    def query(self):
        return self.fullmatch(r"^#(?:[0-9a-fA-F]{3}){1,2}$")

JWT

Bases: MatchHandler[str, None]

Validates the structure of a JSON Web Token (header.payload.signature)

Source code in pipeline/handlers/match_handler/units/match_format.py
115
116
117
118
119
120
121
122
123
124
class JWT(MatchHandler[str, None]):
    """Validates the structure of a JSON Web Token (header.payload.signature)"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {HandlerMode.ROOT: lambda _: "Invalid JWT format."}

    def query(self):
        return self.fullmatch(
            r"^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+$"
        )

Password

Bases: MatchHandler[str, str]

Validates password strength based on three policies: RELAXED, NORMAL, or STRICT.

Policies: - RELAXED: 6-64 chars, 1 uppercase, 1 lowercase. - NORMAL: 6-64 chars, 1 uppercase, 1 lowercase, 1 digit. - STRICT: 6-64 chars, 1 uppercase, 1 lowercase, 1 digit, 1 special character.

Requires a policy argument (e.g., Match.Format.Password.NORMAL)

Source code in pipeline/handlers/match_handler/units/match_format.py
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
class Password(MatchHandler[str, str]):
    """Validates password strength based on three policies: RELAXED, NORMAL, or STRICT.

    Policies:
    - RELAXED: 6-64 chars, 1 uppercase, 1 lowercase.
    - NORMAL: 6-64 chars, 1 uppercase, 1 lowercase, 1 digit.
    - STRICT: 6-64 chars, 1 uppercase, 1 lowercase, 1 digit, 1 special character.

    Requires a policy argument (e.g., Match.Format.Password.NORMAL)
    """
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    RELAXED = "relaxed"
    NORMAL = "normal"
    STRICT = "strict"

    ERROR_MESSAGE = {
        RELAXED:
            "Password too weak. Required: 6-64 characters, at least 1 uppercase and 1 lowercase letter.",
        NORMAL:
            "Password too weak. Required: 6-64 characters, at least 1 uppercase, 1 lowercase, and 1 digit.",
        STRICT:
            "Password too weak. Required: 6-64 characters, at least 1 uppercase, 1 lowercase, 1 digit, and 1 special character."
    }

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda self: self.ERROR_MESSAGE[self.argument]  # type: ignore
    }

    def query(self):
        if self.argument == self.RELAXED:
            # Min 6, Max 64, 1 Upper, 1 Lower
            pattern = r"^(?=.*[a-z])(?=.*[A-Z]).{6,64}$"
        elif self.argument == self.NORMAL:
            # Min 6, Max 64, 1 Upper, 1 Lower, 1 Digit
            pattern = r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{6,64}$"
        elif self.argument == self.STRICT:
            # Min 6, Max 64, 1 Upper, 1 Lower, 1 Digit, 1 Special
            pattern = r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*(),.?\":{}|<>]).{6,64}$"
        else:
            raise HandlerException(
                f"{self.argument} is not a valid password policy. Use Password.RELAXED, Password.NORMAL, or Password.STRICT."
            )

        return self.fullmatch(pattern)

UUID

Bases: MatchHandler[str, None]

Validates 36-character hexadecimal unique identifiers (8-4-4-4-12)

Source code in pipeline/handlers/match_handler/units/match_format.py
32
33
34
35
36
37
38
39
40
41
class UUID(MatchHandler[str, None]):
    """Validates 36-character hexadecimal unique identifiers (8-4-4-4-12)"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {HandlerMode.ROOT: lambda _: "Invalid UUID format."}

    def query(self):
        return self.fullmatch(
            r"^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$", re.IGNORECASE
        )

MatchLocalization

Registry for localization-related match handlers.

Includes handlers for Country, Currency, Language (ISO codes), and Timezones.

Source code in pipeline/handlers/match_handler/units/match_localization.py
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
class MatchLocalization:
    """
    Registry for localization-related match handlers.

    Includes handlers for Country, Currency, Language (ISO codes), and Timezones.
    """
    class Country(MatchHandler[str, None]):
        """ISO 3166-1 alpha-2 (e.g., 'US', 'DE', 'JP')"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _:
                "Must be a valid 2-letter ISO country code (e.g., US)."
        }

        def query(self):
            return self.value in ISO_3166

    class Currency(MatchHandler[str, None]):
        """ISO 4217 (e.g., 'USD', 'EUR', 'BTC')"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _: "Must be a valid 3-letter currency code (e.g., USD)."
        }

        def query(self):
            return self.value in ISO_4217

    class Language(MatchHandler[str, None]):
        """ISO 639-1 (e.g., 'en', 'fr', 'zh')"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _: "Must be a valid 2-letter language code (e.g., en)."
        }

        def query(self):
            return self.value in ISO_639_1

    class Timezone(MatchHandler[str, None]):
        """IANA Timezone (e.g., 'America/New_York', 'Europe/London')"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _:
                "Invalid IANA timezone string (e.g., America/New_York)."
        }

        def query(self):
            return self.value in available_timezones()

Country

Bases: MatchHandler[str, None]

ISO 3166-1 alpha-2 (e.g., 'US', 'DE', 'JP')

Source code in pipeline/handlers/match_handler/units/match_localization.py
18
19
20
21
22
23
24
25
26
27
28
29
class Country(MatchHandler[str, None]):
    """ISO 3166-1 alpha-2 (e.g., 'US', 'DE', 'JP')"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _:
            "Must be a valid 2-letter ISO country code (e.g., US)."
    }

    def query(self):
        return self.value in ISO_3166

Currency

Bases: MatchHandler[str, None]

ISO 4217 (e.g., 'USD', 'EUR', 'BTC')

Source code in pipeline/handlers/match_handler/units/match_localization.py
31
32
33
34
35
36
37
38
39
40
41
class Currency(MatchHandler[str, None]):
    """ISO 4217 (e.g., 'USD', 'EUR', 'BTC')"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _: "Must be a valid 3-letter currency code (e.g., USD)."
    }

    def query(self):
        return self.value in ISO_4217

Language

Bases: MatchHandler[str, None]

ISO 639-1 (e.g., 'en', 'fr', 'zh')

Source code in pipeline/handlers/match_handler/units/match_localization.py
43
44
45
46
47
48
49
50
51
52
53
class Language(MatchHandler[str, None]):
    """ISO 639-1 (e.g., 'en', 'fr', 'zh')"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _: "Must be a valid 2-letter language code (e.g., en)."
    }

    def query(self):
        return self.value in ISO_639_1

Timezone

Bases: MatchHandler[str, None]

IANA Timezone (e.g., 'America/New_York', 'Europe/London')

Source code in pipeline/handlers/match_handler/units/match_localization.py
55
56
57
58
59
60
61
62
63
64
65
66
class Timezone(MatchHandler[str, None]):
    """IANA Timezone (e.g., 'America/New_York', 'Europe/London')"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _:
            "Invalid IANA timezone string (e.g., America/New_York)."
    }

    def query(self):
        return self.value in available_timezones()

MatchNetwork

Registry for network-related match handlers.

Includes handlers for IPv4, IPv6, MAC Addresses, etc.

Source code in pipeline/handlers/match_handler/units/match_network.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class MatchNetwork:
    """
    Registry for network-related match handlers.

    Includes handlers for IPv4, IPv6, MAC Addresses, etc.
    """
    class IPv4(MatchHandler[str, None]):
        """Validates a standard IPv4 address (e.g., '192.168.1.1')"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {HandlerMode.ROOT: lambda _: "Invalid IPv4 address."}

        def query(self):
            try:
                return ip_address(address=self.value).version == 4
            except:
                return False

    class IPv6(MatchHandler[str, None]):
        """Validates an IPv6 address (e.g., '2001:db8::ff00:42:8329')"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {HandlerMode.ROOT: lambda _: "Invalid IPv6 address."}

        def query(self):
            try:
                return ip_address(address=self.value).version == 6
            except:
                return False

    class MACAddress(MatchHandler[str, None]):
        """Accepts hardware MAC addresses using colon, hyphen, or dot separators"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT: lambda _: "Invalid MAC address format."
        }

        def query(self):
            return self.fullmatch(
                r"^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})|([0-9a-fA-F]{4}\.[0-9a-fA-F]{4}\.[0-9a-fA-F]{4})$"
            )

IPv4

Bases: MatchHandler[str, None]

Validates a standard IPv4 address (e.g., '192.168.1.1')

Source code in pipeline/handlers/match_handler/units/match_network.py
15
16
17
18
19
20
21
22
23
24
25
class IPv4(MatchHandler[str, None]):
    """Validates a standard IPv4 address (e.g., '192.168.1.1')"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {HandlerMode.ROOT: lambda _: "Invalid IPv4 address."}

    def query(self):
        try:
            return ip_address(address=self.value).version == 4
        except:
            return False

IPv6

Bases: MatchHandler[str, None]

Validates an IPv6 address (e.g., '2001:db8::ff00:42:8329')

Source code in pipeline/handlers/match_handler/units/match_network.py
27
28
29
30
31
32
33
34
35
36
37
class IPv6(MatchHandler[str, None]):
    """Validates an IPv6 address (e.g., '2001:db8::ff00:42:8329')"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {HandlerMode.ROOT: lambda _: "Invalid IPv6 address."}

    def query(self):
        try:
            return ip_address(address=self.value).version == 6
        except:
            return False

MACAddress

Bases: MatchHandler[str, None]

Accepts hardware MAC addresses using colon, hyphen, or dot separators

Source code in pipeline/handlers/match_handler/units/match_network.py
39
40
41
42
43
44
45
46
47
48
49
50
class MACAddress(MatchHandler[str, None]):
    """Accepts hardware MAC addresses using colon, hyphen, or dot separators"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT: lambda _: "Invalid MAC address format."
    }

    def query(self):
        return self.fullmatch(
            r"^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})|([0-9a-fA-F]{4}\.[0-9a-fA-F]{4}\.[0-9a-fA-F]{4})$"
        )

MatchRegex

Registry for regex-related match handlers.

Includes handlers for Search and FullMatch.

Source code in pipeline/handlers/match_handler/units/match_regex.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class MatchRegex:
    """
    Registry for regex-related match handlers.

    Includes handlers for Search and FullMatch.
    """
    class Search(MatchHandler[str, str | Pattern]):
        """Accepts values that contain at least one match of the provided regex pattern"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda self:
                f"Invalid value. Valid pattern for value is {self.argument}."
        }

        def query(self):
            return self.search(self.argument)

    class FullMatch(MatchHandler[str, str | Pattern]):
        """Accepts values that match the provided regex pattern in their entirety"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda self:
                f"Invalid value. Valid pattern for value is {self.argument}."
        }

        def query(self):
            return self.fullmatch(self.argument)

FullMatch

Bases: MatchHandler[str, str | Pattern]

Accepts values that match the provided regex pattern in their entirety

Source code in pipeline/handlers/match_handler/units/match_regex.py
28
29
30
31
32
33
34
35
36
37
38
39
class FullMatch(MatchHandler[str, str | Pattern]):
    """Accepts values that match the provided regex pattern in their entirety"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda self:
            f"Invalid value. Valid pattern for value is {self.argument}."
    }

    def query(self):
        return self.fullmatch(self.argument)

Search

Bases: MatchHandler[str, str | Pattern]

Accepts values that contain at least one match of the provided regex pattern

Source code in pipeline/handlers/match_handler/units/match_regex.py
15
16
17
18
19
20
21
22
23
24
25
26
class Search(MatchHandler[str, str | Pattern]):
    """Accepts values that contain at least one match of the provided regex pattern"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda self:
            f"Invalid value. Valid pattern for value is {self.argument}."
    }

    def query(self):
        return self.search(self.argument)

MatchText

Registry for text-related match handlers.

Includes handlers for Lowercase, Uppercase, Digits, etc.

Source code in pipeline/handlers/match_handler/units/match_text.py
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
class MatchText:
    """
    Registry for text-related match handlers.

    Includes handlers for Lowercase, Uppercase, Digits, etc.
    """
    class Lowercase(MatchHandler[str, None]):
        """Accepts ONLY lowercase English letters (a-z)"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT: lambda _: "Must contain only lowercase letters (a-z)."
        }

        def query(self):
            return self.fullmatch(r"^[a-z]+$")

    class LowercaseWithSpaces(MatchHandler[str, None]):
        """Accepts lowercase English letters (a-z) and spaces"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _:
                "Must contain only lowercase letters and spaces (e.g., 'hello world')."
        }

        def query(self):
            return self.fullmatch(r"^[a-z ]+$")

    class Uppercase(MatchHandler[str, None]):
        """Accepts ONLY uppercase English letters (A-Z)"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT: lambda _: "Must contain only uppercase letters (A-Z)."
        }

        def query(self):
            return self.fullmatch(r"^[A-Z]+$")

    class UppercaseWithSpaces(MatchHandler[str, None]):
        """Accepts uppercase English letters (A-Z) and spaces"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _:
                "Must contain only uppercase letters and spaces (e.g., 'HELLO WORLD')."
        }

        def query(self):
            return self.fullmatch(r"^[A-Z ]+$")

    class Letters(MatchHandler[str, None]):
        """Accepts ONLY case English letters (a-z, A-Z)"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT: lambda _: "Must contain only letters (a-z, A-Z)."
        }

        def query(self):
            return self.fullmatch(r"^[a-zA-Z]+$")

    class LettersWithSpaces(MatchHandler[str, None]):
        """Accepts English letters (a-z, A-Z) and spaces"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _:
                "Must contain only letters and spaces (e.g., 'Hello World')."
        }

        def query(self):
            return self.fullmatch(r"^[a-zA-Z ]+$")

    class Digits(MatchHandler[str, None]):
        """Accepts ONLY numeric digits (0-9)"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT: lambda _: "Must contain only digits (0-9)."
        }

        def query(self):
            return self.fullmatch(r"^\d+$")

    class DigitsWithSpaces(MatchHandler[str, None]):
        """Accepts numeric digits (0-9) and spaces"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _:
                "Must contain only digits and spaces (e.g., '123 456')."
        }

        def query(self):
            return self.fullmatch(r"^[\d ]+$")

    class Alphanumeric(MatchHandler[str, None]):
        """Accepts letters and numeric digits. No symbols or spaces"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _: "Must contain only letters and digits (e.g., 'abc123')."
        }

        def query(self):
            return self.fullmatch(r"^[a-zA-Z0-9]+$")

    class AlphanumericWithSpaces(MatchHandler[str, None]):
        """Accepts letters, numeric digits, and spaces. No symbols"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _:
                "Must contain only letters, digits, and spaces (e.g., 'abc 123')."
        }

        def query(self):
            return self.fullmatch(r"^[a-zA-Z0-9 ]+$")

    class Printable(MatchHandler[str, None]):
        """Accepts letters, numbers, symbols, and spaces (ASCII 20-7E)"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _:
                "Contains invalid characters. Only printable ASCII characters are allowed."
        }

        def query(self):
            return self.fullmatch(r"^[ -~]+$")

    class NoWhitespace(MatchHandler[str, None]):
        """Ensures string contains no spaces, tabs, or line breaks"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _: "Must not contain spaces, tabs, or line breaks."
        }

        def query(self):
            return not self.search(r"\s")

    class Slug(MatchHandler[str, None]):
        """URL-friendly strings: 'my-cool-post-123'"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _:
                "Must contain only lowercase letters, numbers, and hyphens (e.g., 'my-post-123')."
        }

        def query(self):
            return self.fullmatch(r"^[a-z0-9]+(?:-[a-z0-9]+)*$")

Alphanumeric

Bases: MatchHandler[str, None]

Accepts letters and numeric digits. No symbols or spaces

Source code in pipeline/handlers/match_handler/units/match_text.py
109
110
111
112
113
114
115
116
117
118
119
class Alphanumeric(MatchHandler[str, None]):
    """Accepts letters and numeric digits. No symbols or spaces"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _: "Must contain only letters and digits (e.g., 'abc123')."
    }

    def query(self):
        return self.fullmatch(r"^[a-zA-Z0-9]+$")

AlphanumericWithSpaces

Bases: MatchHandler[str, None]

Accepts letters, numeric digits, and spaces. No symbols

Source code in pipeline/handlers/match_handler/units/match_text.py
121
122
123
124
125
126
127
128
129
130
131
132
class AlphanumericWithSpaces(MatchHandler[str, None]):
    """Accepts letters, numeric digits, and spaces. No symbols"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _:
            "Must contain only letters, digits, and spaces (e.g., 'abc 123')."
    }

    def query(self):
        return self.fullmatch(r"^[a-zA-Z0-9 ]+$")

Digits

Bases: MatchHandler[str, None]

Accepts ONLY numeric digits (0-9)

Source code in pipeline/handlers/match_handler/units/match_text.py
85
86
87
88
89
90
91
92
93
94
class Digits(MatchHandler[str, None]):
    """Accepts ONLY numeric digits (0-9)"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT: lambda _: "Must contain only digits (0-9)."
    }

    def query(self):
        return self.fullmatch(r"^\d+$")

DigitsWithSpaces

Bases: MatchHandler[str, None]

Accepts numeric digits (0-9) and spaces

Source code in pipeline/handlers/match_handler/units/match_text.py
 96
 97
 98
 99
100
101
102
103
104
105
106
107
class DigitsWithSpaces(MatchHandler[str, None]):
    """Accepts numeric digits (0-9) and spaces"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _:
            "Must contain only digits and spaces (e.g., '123 456')."
    }

    def query(self):
        return self.fullmatch(r"^[\d ]+$")

Letters

Bases: MatchHandler[str, None]

Accepts ONLY case English letters (a-z, A-Z)

Source code in pipeline/handlers/match_handler/units/match_text.py
61
62
63
64
65
66
67
68
69
70
class Letters(MatchHandler[str, None]):
    """Accepts ONLY case English letters (a-z, A-Z)"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT: lambda _: "Must contain only letters (a-z, A-Z)."
    }

    def query(self):
        return self.fullmatch(r"^[a-zA-Z]+$")

LettersWithSpaces

Bases: MatchHandler[str, None]

Accepts English letters (a-z, A-Z) and spaces

Source code in pipeline/handlers/match_handler/units/match_text.py
72
73
74
75
76
77
78
79
80
81
82
83
class LettersWithSpaces(MatchHandler[str, None]):
    """Accepts English letters (a-z, A-Z) and spaces"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _:
            "Must contain only letters and spaces (e.g., 'Hello World')."
    }

    def query(self):
        return self.fullmatch(r"^[a-zA-Z ]+$")

Lowercase

Bases: MatchHandler[str, None]

Accepts ONLY lowercase English letters (a-z)

Source code in pipeline/handlers/match_handler/units/match_text.py
13
14
15
16
17
18
19
20
21
22
class Lowercase(MatchHandler[str, None]):
    """Accepts ONLY lowercase English letters (a-z)"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT: lambda _: "Must contain only lowercase letters (a-z)."
    }

    def query(self):
        return self.fullmatch(r"^[a-z]+$")

LowercaseWithSpaces

Bases: MatchHandler[str, None]

Accepts lowercase English letters (a-z) and spaces

Source code in pipeline/handlers/match_handler/units/match_text.py
24
25
26
27
28
29
30
31
32
33
34
35
class LowercaseWithSpaces(MatchHandler[str, None]):
    """Accepts lowercase English letters (a-z) and spaces"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _:
            "Must contain only lowercase letters and spaces (e.g., 'hello world')."
    }

    def query(self):
        return self.fullmatch(r"^[a-z ]+$")

NoWhitespace

Bases: MatchHandler[str, None]

Ensures string contains no spaces, tabs, or line breaks

Source code in pipeline/handlers/match_handler/units/match_text.py
147
148
149
150
151
152
153
154
155
156
157
class NoWhitespace(MatchHandler[str, None]):
    """Ensures string contains no spaces, tabs, or line breaks"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _: "Must not contain spaces, tabs, or line breaks."
    }

    def query(self):
        return not self.search(r"\s")

Printable

Bases: MatchHandler[str, None]

Accepts letters, numbers, symbols, and spaces (ASCII 20-7E)

Source code in pipeline/handlers/match_handler/units/match_text.py
134
135
136
137
138
139
140
141
142
143
144
145
class Printable(MatchHandler[str, None]):
    """Accepts letters, numbers, symbols, and spaces (ASCII 20-7E)"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _:
            "Contains invalid characters. Only printable ASCII characters are allowed."
    }

    def query(self):
        return self.fullmatch(r"^[ -~]+$")

Slug

Bases: MatchHandler[str, None]

URL-friendly strings: 'my-cool-post-123'

Source code in pipeline/handlers/match_handler/units/match_text.py
159
160
161
162
163
164
165
166
167
168
169
170
class Slug(MatchHandler[str, None]):
    """URL-friendly strings: 'my-cool-post-123'"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _:
            "Must contain only lowercase letters, numbers, and hyphens (e.g., 'my-post-123')."
    }

    def query(self):
        return self.fullmatch(r"^[a-z0-9]+(?:-[a-z0-9]+)*$")

Uppercase

Bases: MatchHandler[str, None]

Accepts ONLY uppercase English letters (A-Z)

Source code in pipeline/handlers/match_handler/units/match_text.py
37
38
39
40
41
42
43
44
45
46
class Uppercase(MatchHandler[str, None]):
    """Accepts ONLY uppercase English letters (A-Z)"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT: lambda _: "Must contain only uppercase letters (A-Z)."
    }

    def query(self):
        return self.fullmatch(r"^[A-Z]+$")

UppercaseWithSpaces

Bases: MatchHandler[str, None]

Accepts uppercase English letters (A-Z) and spaces

Source code in pipeline/handlers/match_handler/units/match_text.py
48
49
50
51
52
53
54
55
56
57
58
59
class UppercaseWithSpaces(MatchHandler[str, None]):
    """Accepts uppercase English letters (A-Z) and spaces"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _:
            "Must contain only uppercase letters and spaces (e.g., 'HELLO WORLD')."
    }

    def query(self):
        return self.fullmatch(r"^[A-Z ]+$")

MatchTime

Registry for time-related match handlers.

Includes handlers for Date, Time, and DateTime (ISO 8601).

Source code in pipeline/handlers/match_handler/units/match_time.py
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class MatchTime:
    """
    Registry for time-related match handlers.

    Includes handlers for Date, Time, and DateTime (ISO 8601).
    """
    class Date(MatchHandler[str, None]):
        """Validates YYYY-MM-DD format"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _:
                "Date must be in YYYY-MM-DD format (e.g., 2023-10-01)."
        }

        def query(self):
            return self.fullmatch(
                r"^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$"
            )

    class Time(MatchHandler[str, None]):
        """Validates 24h time in HH:MM or HH:MM:SS format"""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _: "Invalid time format (HH:MM[:SS]) (e.g., 14:30:00)."
        }

        def query(self):
            return self.fullmatch(r"^(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d)?$")

    class DateTime(MatchHandler[str, None]):
        """Validates ISO 8601 combined Date and Time (e.g., 2023-10-01T14:30:00Z)."""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _:
                "Invalid ISO 8601 DateTime format (e.g., 2023-10-01T14:30:00Z)."
        }

        def query(self):
            return self.fullmatch(
                r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})$"
            )

Date

Bases: MatchHandler[str, None]

Validates YYYY-MM-DD format

Source code in pipeline/handlers/match_handler/units/match_time.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Date(MatchHandler[str, None]):
    """Validates YYYY-MM-DD format"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _:
            "Date must be in YYYY-MM-DD format (e.g., 2023-10-01)."
    }

    def query(self):
        return self.fullmatch(
            r"^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$"
        )

DateTime

Bases: MatchHandler[str, None]

Validates ISO 8601 combined Date and Time (e.g., 2023-10-01T14:30:00Z).

Source code in pipeline/handlers/match_handler/units/match_time.py
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class DateTime(MatchHandler[str, None]):
    """Validates ISO 8601 combined Date and Time (e.g., 2023-10-01T14:30:00Z)."""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _:
            "Invalid ISO 8601 DateTime format (e.g., 2023-10-01T14:30:00Z)."
    }

    def query(self):
        return self.fullmatch(
            r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})$"
        )

Time

Bases: MatchHandler[str, None]

Validates 24h time in HH:MM or HH:MM:SS format

Source code in pipeline/handlers/match_handler/units/match_time.py
28
29
30
31
32
33
34
35
36
37
38
class Time(MatchHandler[str, None]):
    """Validates 24h time in HH:MM or HH:MM:SS format"""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _: "Invalid time format (HH:MM[:SS]) (e.g., 14:30:00)."
    }

    def query(self):
        return self.fullmatch(r"^(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d)?$")

MatchWeb

Registry for web-related match handlers.

Includes handlers for Domain and URL.

Source code in pipeline/handlers/match_handler/units/match_web.py
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class MatchWeb:
    """
    Registry for web-related match handlers.

    Includes handlers for Domain and URL.
    """

    class Domain(MatchHandler[str, None]):
        """Validates a domain name based on RFC 1035."""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT: lambda _: "Invalid domain format (e.g., 'example.com')."
        }

        def query(self):
            return self.fullmatch(
                r"^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$"
            )

    class URL(MatchHandler[str, None]):
        """Validates web URLs using HTTP or HTTPS protocols."""
        SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

        ERROR_TEMPLATES = {
            HandlerMode.ROOT:
                lambda _:
                "Invalid URL format. Must be a valid HTTP/HTTPS URL (e.g., 'https://example.com')."
        }

        def query(self):
            return self.fullmatch(
                r"^https?://(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&//=]*)$"
            )

Domain

Bases: MatchHandler[str, None]

Validates a domain name based on RFC 1035.

Source code in pipeline/handlers/match_handler/units/match_web.py
14
15
16
17
18
19
20
21
22
23
24
25
class Domain(MatchHandler[str, None]):
    """Validates a domain name based on RFC 1035."""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT: lambda _: "Invalid domain format (e.g., 'example.com')."
    }

    def query(self):
        return self.fullmatch(
            r"^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$"
        )

URL

Bases: MatchHandler[str, None]

Validates web URLs using HTTP or HTTPS protocols.

Source code in pipeline/handlers/match_handler/units/match_web.py
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class URL(MatchHandler[str, None]):
    """Validates web URLs using HTTP or HTTPS protocols."""
    SUPPORT = (HandlerMode.ROOT, HandlerMode.ITEM)

    ERROR_TEMPLATES = {
        HandlerMode.ROOT:
            lambda _:
            "Invalid URL format. Must be a valid HTTP/HTTPS URL (e.g., 'https://example.com')."
    }

    def query(self):
        return self.fullmatch(
            r"^https?://(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&//=]*)$"
        )