Source code for as3ninja.schema.formatcheckers
# -*- coding: utf-8 -*-
"""
AS3 Schema Format Checker for F5 specific formats.
"""
# pylint: disable=C0301 # Line too long
import re
from typing import Any
from jsonschema import FormatChecker
from ..types import F5IP, F5IPv4, F5IPv6
[docs]class AS3FormatChecker(FormatChecker):
"""
AS3FormatChecker subclasses jsonschema.FormatChecker to provide AS3 specific format checks.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# update FormatChecker instance's format checkers with AS3 schema specific format checkers
self.checkers.update(self.as3_schema_format_checkers)
@property
def as3_schema_format_checkers(self) -> dict:
"""
Returns dict of AS3 formats: f5ip, f5ipv4, f5ipv6, f5label, f5long-id, f5remark, f5pointer, f5base64
Currently missing formats used in AS3:
- date-time
- uri
- url
"""
return {
# based on F5 IP addressing schemes for Virtual Servers, Nodes and Pool Members
"f5ip": (lambda v: self._is_type(F5IP, v), ()),
"f5ipv4": (lambda v: self._is_type(F5IPv4, v), ()),
"f5ipv6": (lambda v: self._is_type(F5IPv6, v), ()),
# based on AS3 3.17.1 : lib/adcParserFormats.js
"f5name": (
lambda v: self._regex_match(r"^([A-Za-z][0-9A-Za-z_]{0,63})?$", v),
(),
),
"f5bigip": (
lambda v: self._regex_match(
r"^\x2f[^\x00-\x19\x22#\'*<>?\x5b-\x5d\x7b-\x7d\x7f]+$", v
),
(),
),
"f5long-id": (
lambda v: self._regex_match(
r"^[^\x00-\x20\x22\'<>\x5c^`|\x7f]{0,255}$", v
),
(),
),
"f5label": (
lambda v: self._regex_match(
r"^[^\x00-\x1f\x22#&*<>?\x5b-\x5d`\x7f]{0,64}$", v
),
(),
),
"f5remark": (
lambda v: self._regex_match(r"^[^\x00-\x1f\x22\x5c\x7f]{0,64}$", v),
(),
),
"f5pointer": (
lambda v: self._regex_match(
r"((@|[0-9]+)|(([0-9]*\x2f)?((@|[0-9]+|[A-Za-z][0-9A-Za-z_]{0,63})\x2f)*([0-9]+|([A-Za-z][0-9A-Za-z_]{0,63}))))?#?$",
v,
),
(),
),
"f5base64": (
lambda v: self._regex_match(
r"^([0-9A-Za-z\/+_-]*|[0-9A-Za-z\/+_-]+={1,2})$", v
),
(),
),
}
[docs] @staticmethod
def _is_type(is_type: Any, value: Any) -> bool:
"""
Helper function _is_type returns `True` when `is_type(value)` does not raise an exception, `False` otherwise
:param is_type: The type to check against
:param value: Value to check
"""
try:
is_type(value)
return True
except Exception: # pylint: disable=W0703 # we do not care which exception occurs
return False
[docs] @staticmethod
def _regex_match(regex: str, value: str) -> bool:
"""
Helper function _regex_match matches a regular expression against the given value.
Returns `True` when regex matches, `False` otherwise.
:param regex: The regular expression, for example: ``r'^[ -~]+$'``
:param value: Value to apply the regular expression to
"""
if not isinstance(value, str):
return False
reg_ex = re.compile(regex)
if reg_ex.match(value) is None:
return False
return True