pykwalify

repository·master·Indexed 43 days ago

https://github.com/grokzen/pykwalify

A YAML/JSON validation library that ports and extends the Java-based Kwalify framework. It allows developers to define validation rules in a schema file and apply them to data files via a CLI or the pykwalify.core.Core Python API. Features include support for custom validation extensions, partial schemas for reusability, and a variety of constraints such as regex patterns, numeric ranges, and enum restrictions.

Tokens
4.7K
Snippets
26
Records
28
Agent score
50%

What's inside pykwalify

  1. Apply numeric and length ranges

    master

    The range constraint works for:

    • Numeric types (int, float, number): Validates the value itself.
    • Non-numeric types (map, seq, str): Validates the length (len()) of the object.

    Available keys:

    • min: Inclusive lower bound (a <= x)
    • max: Inclusive upper bound (x <= b)
    • min-ex: Exclusive lower bound (a < x)
    • max-ex: Exclusive upper bound (x < b)
    # Schema
    type: map
    mapping:
      password:
        type: str
        range:
          min: 8
          max: 16
      age:
        type: int
        range:
          min: 18
          max-ex: 30
    
    # Data
    password: foobar123
    age: 25
  2. Define and use partial schemas

    master

    pyKwalify allows you to define small, reusable partial schemas that can be included in other schemas. This is handled via custom keywords rather than standard YAML or JSON linking.

    Defining a partial schema

    Use the keyword schema;(schema-id): at the top level of your schema file. The (schema-id) must be globally unique across all schemas being processed; if a collision is detected, an error will be raised.

    Including a partial schema

    Use the keyword include: (schema-id) to embed a partial schema. This directive can be used anywhere you would normally specify a type keyword.

    Note: The include directive cannot be used inside a partial schema itself (partial schemas cannot be nested via inclusion).

    Key constraints

    • Partial schemas must be defined at the top level of the schema file.
    • Includes are loaded lazily during the parsing/validation phase.
    # Schema file
    schema;map_str:
      type: map
      mapping:
        foo:
          type: str
    
    type: seq
    sequence:
      - include: map_str
  3. Control sequence item matching with 'matching'

    master

    When using a sequence type, the matching constraint controls how the parser handles a list of different subrules for the sequence block:

    • any: Each list item must satisfy at least one subrule.
    • all: Each list item must satisfy every subrule.
    • *: At least one list item must satisfy at least one subrule.
    # Schema
    type: seq
    matching: "any"
    sequence:
      - type: str
      - type: seq
        sequence:
          - type: int
    
    # Data
    - - 123
    - "foobar"
  4. Validate timestamps and dates

    master

    Timestamps

    Use type: timestamp to validate Unix timestamps (between 1 and 2147483647). It supports strings, integers, and datetime objects.

    Dates

    Use type: date to validate date strings or datetime objects. You can specify a custom format using the format keyword with python-strptime syntax.

    # Schema for custom date format
    type: date
    format: "%Y-%m-%d"
    
    # Data
    "2015-12-31"
  5. Apply constraints: required, enum, and pattern

    master

    Required

    Set required: True (or req: True) to ensure a key and its value are present. Default is False.

    Enum

    Use enum: [item1, item2] to restrict a value to a specific set of exact-case members.

    Pattern

    Use pattern: <regex> to validate scalar types against a regular expression using re.match.

    # Schema
    type: map
    mapping:
      blood: 
        type: str
        enum: ['A', 'B', 'O', 'AB']
      email: 
        type: str
        pattern: .+@.+
    
    # Data
    blood: AB
    email: foo@mail.com
  6. Validate sequences (lists)

    master

    A sequence validates a list. You can use type: seq or type: sequence. The sequence type is implicitly assumed if the sequence or seq key is present.

    PyKwalify supports multiple entries in the sequence list to allow different types of data within the same list. You can also use the unique: True constraint to ensure no repeated entries exist in the list.

    # Schema
    type: seq
    sequence:
      - type: str
      - type: int
    
    # Data
    - 'Foobar'
    - 123456
  7. Validate mapping keys with regex

    master

    You can use regex to match key names within a mapping. Use the syntax regex;(regex-pattern) or the alias re;(regex-pattern).

    Note: The regex must be wrapped in parentheses ( ), which are removed at runtime. If using multiple regex rules, set matching-rule (e.g., any or all) to define behavior.

    # Schema
    type: map
    matching-rule: 'any'
    mapping:
      regex;(mi.+):
        type: seq
        sequence:
          - type: str
      regex;(me.+):
        type: number
    
    # Data
    mic:
      - foo
      - bar
    media: 1
  8. Validate mappings (dictionaries)

    master

    A mapping validates a dict structure. You can use type: map or type: mapping. The mapping type is implicitly assumed if the mapping or map key is present in the rule.

    By default, keys specified in the mapping are optional unless required: True is set. Use allowempty: True to allow keys in the data that are not defined in the schema.

    # Schema
    type: map
    mapping:
      key_one:
        type: str
        required: True
    
    # Data
    key_one: 'bar'
  9. Implement custom validation functions

    master

    To create a custom validation extension, define functions in a Python file. Each function must have a globally unique name and accept exactly three arguments: value, rule_obj, and path.

    Argument Behavior

    • For seq (sequence): value is the entire list content.
    • For map (mapping): value is the entire dictionary content.
    • For scalar: value is the scalar value itself.

    Reporting Validation Results

    You can signal the result of a validation in three ways:

    1. Return True: Validation passed.
    2. Return False: Validation failed; pykwalify will raise a CoreError.
    3. Raise an Exception: Any exception you raise will propagate up to the caller.
    4. Return a non-boolean value: If you return something other than True or False, the value is converted to a string (via unicode()) and formatted as a parse error in the final error list.
    def method_name(value, rule_obj, path):
        # Implementation logic
        return True
  10. Validate YAML or JSON files via CLI

    master

    You can validate a data file against a schema file using the pykwalify command-line interface. Use the -d flag to specify the data file (JSON or YAML) and the -s flag to specify the schema file.

    Example data file (data.yaml):

    - foo
    - bar

    Example schema file (schema.yaml):

    type: seq
    sequence:
      - type: str
    pykwalify -d data.yaml -s schema.yaml