Skip to main content

Safe Shield is a powerful, elegant, and highly extensible validation library for Python. Inspired by modern validation systems like Laravel, it provides a fluent syntax for validating complex data structures, including nested dictionaries and wildcard patterns.

Project description

Safe Shield ๐Ÿ›ก๏ธ (v2.0.0)

Safe Shield is a powerful, elegant, and highly extensible validation library for Python. Inspired by modern validation systems like Laravel, it provides a fluent syntax for validating complex data structures, including nested dictionaries and wildcard patterns.

โš ๏ธ IMPORTANT: Safe Shield v1.x.x and v2.x.x have different APIs. Make sure you're reading the documentation that matches your installed version.


๐Ÿ“– Table of Contents


โœจ Features

  • ๐Ÿ“ Fluent Syntax: Define rules using simple strings or rich objects.
  • ๐ŸŒฒ Nested Validation: Validate deeply nested data with ease using dot notation.
  • ๐Ÿƒ Wildcard Support: Apply rules across arrays or object collections with *.
  • ๐Ÿงฉ Modular & Extensible: Easily create and register your own custom rules.
  • ๐Ÿ’ฌ Customizable Messages: Fine-grained control over error messages and attribute names.

๐Ÿ“ฅ Installation

Install Safe Shield using pip:

pip install safeshield

๐Ÿš€ Quick Start

from validator import Validator

data = {
    "username": "john_doe",
    "email": "invalid-email",
    "profile": {
        "age": 17
    },
    "tags": ["python", "validation"]
}

rules = {
    "username": "required|string|min:3",
    "email": "required|email",
    "profile.age": "required|numeric|min:18",
    "tags": "required|array|min:1",
    "tags.*": "string|alpha"
}

v = Validator(data, rules)

if v.validate():
    print("Success!")
else:
    print(v.errors)

๐Ÿ› ๏ธ 3 Ways to Define Rules

Safe Shield is extremely flexible in how you define validation rules. You can use whichever format fits your coding style. Below are full examples of how to implement each style in your code.

1. Pipe String (Laravel Style)

The most concise way. Rules are separated by | and parameters follow a :.

from validator import Validator

data = {"email": "invalid-email", "age": 15}
rules = {
    "email": "required|email|max:255",
    "age": "required|numeric|min:18"
}

v = Validator(data, rules)

if v.validate():
    print("Validation Passed!")
else:
    print(v.errors) # {'email': ['The email must be a valid email.'], 'age': ['The age must be at least 18.']}

2. List of Strings & Tuples

Cleaner when dealing with complex parameters or when you want to avoid string parsing.

from validator import Validator

data = {"email": "user@example.com", "age": 20}
rules = {
    "email": ["required", "email", "max:255"],
    "age": ["required", "numeric", ("min", 18)] # Tuples are great for params
}

v = Validator(data, rules)
if not v.validate():
    handle_your_errors(v.errors)

3. Rule Instances (Object Oriented)

The most powerful way. Allows for IDE autocompletion and passing complex objects or custom logic as parameters.

from validator import Validator
from validator.rules import Required, Email, Min

data = {"email": "user@example.com", "age": 25}
rules = {
    "email": [Required(), Email()],
    "age": [Required(), Min(18)]
}

v = Validator(data, rules)
# Use it in your logic
validated_data = v.data if v.validate() else None

๐Ÿงฉ Custom Rules

Creating and using your own rules is straightforward.

1. Create the Rule

Extend the Rule class and implement validate and message.

from validator.rules import Rule

class StrongPassword(Rule):
    def validate(self, field, value, params):
        # Your custom logic here
        return len(value) >= 10 and any(c.isdigit() for c in value)
    
    def message(self):
        return "The :attribute must be at least 10 characters and contain a number."

2. Use the Rule

There are two ways to use your custom rule:

Option A: Direct Instance (Recommended for one-offs)

Just pass it in the list of rules.

rules = {
    "password": ["required", StrongPassword()]
}

Option B: Register & Use String (Global usage)

Register the rule with a name, then use that name anywhere.

from validator.factory import RuleFactory

# Register (name, validate_func, message_func)
RuleFactory.register_rule(
    "strong_pass", 
    lambda f, v, p: len(v) > 10, 
    lambda f, p: "Password is too weak!"
)

rules = {
    "password": "required|strong_pass"
}

๐ŸŒฒ Nested Data & Wildcards

Safe Shield makes validating complex JSON-like structures simple using Dot Notation and Wildcards.

Dot Notation

Validate nested keys regardless of depth.

rules = {
    "user.profile.address.city": "required|string"
}

Wildcards (*)

Apply rules to every element in a list or every key in a dictionary.

data = {
    "items": [
        {"id": 1, "price": 10},
        {"id": 2, "price": 20}
    ]
}

rules = {
    "items.*.id": "required|integer",
    "items.*.price": "numeric|min:0"
}

๐ŸŽจ Error Messages & Customization

1. Custom Attribute Names

Instead of showing "profile.age", show a friendly name like "Age".

attributes = {
    "profile.age": "Age",
    "user.email": "Email Address"
}
v = Validator(data, rules, custom_attributes=attributes)
# Error will say: "The Age must be at least 18."

2. Custom Error Messages

You can customize messages globally or for specific field-rule combinations.

messages = {
    "required": "Field :attribute is mandatory.",
    "email": "The :input value is not a valid email.",
    "profile.age.min": "You must be at least :min years old to join!"
}
v = Validator(data, rules, messages=messages)

3. Placeholders

Safe Shield provides several placeholders to make your messages dynamic:

Placeholder Description Example Rule
:attribute The name of the field (or its custom name). All rules
:input The actual value that failed validation. All rules
:value The primary parameter of the rule. min, max, size
:other The name of another field being compared to. same, required_if
:others A list of other fields. required_with, prohibits
:values A list of values provided in the rule params. in, starts_with, required_if

Example usage of :other and :values:

messages = {
    "password.same": "The :attribute must match :other.",
    "status.in": "The :attribute must be one of these: :values."
}

๐Ÿš€ Advanced Logic: any_of & when

For more complex validation scenarios, Safe Shield provides two powerful logic rules.

1. any_of (Logical OR)

Validates that a field passes at least one set of rules. Ideal for fields that can be multiple formats (e.g., a username can be an email OR a numeric ID).

  • How it works: It takes multiple rule sets separated by commas.
  • Example Usage:
# Pass if it's a valid email OR a number with at least 10000
rules = {
    "identifier": "any_of:required|email,required|numeric|min:10000"
}

# Documentation via different styles:
# String: "any_of:rule1|rule2,rule3|rule4"
# List:   ("any_of", ["required", "email"], ["numeric"])
# Class:  AnyOf(["required", "email"], ["numeric"])

2. when (Conditional rules)

Dynamically applies rules to a field based on the value of other fields in the dataset.

  • How it works: You define a "watch map". If a watched field matches a value, specific rules are injected.
  • Example Usage:
from validator import Validator
from validator.rules import When

data = {
    "user_type": "admin",
    "access_level": "" # This should be required if user_type is admin
}

rules = {
    "access_level": [
        When({
            "user_type": {
                "admin": "required|integer", # If user_type is 'admin'
                "guest": "nullable",         # If user_type is 'guest'
                "*": "string"               # Wildcard: any other value
            }
        })
    ]
}

v = Validator(data, rules)
if v.fails():
    print(v.errors()) # {'access_level': ['The access level must be an integer.']}

๐Ÿ” Complete Rule Reference

This section provides a detailed breakdown of every rule available in Safe Shield. Each rule is described in a narrative paragraph that covers its function, syntax (string and class), and implementation notes.

๐Ÿ“ Basic & Requirement Rules

๐Ÿ”น required

The required rule is the most fundamental requirement check. It ensures that the field is present in the input dictionary and is not considerd "empty". In this context, empty means the value cannot be None, an empty string (""), an empty list ([]), or an empty dictionary ({}). You can implement this by using the string "required" or the Required() class. It is the core rule for mandatory fields in any form.

๐Ÿ”น nullable

The nullable rule allows a field to contain a None (null) value without failing validation. Most importantly, if the value is None, the validator will skip all other rules assigned to that field, preventing errors like "must be a string" for a null value. It is defined as "nullable" or Nullable(). This is ideal for optional database fields that can remain empty.

๐Ÿ”น sometimes

The sometimes rule provides conditional execution based on field presence. Validation rules for the field will only be run if the key actually exists in the input data. If the key is missing, validation is skipped entirely. Use this via the "sometimes" string or Sometimes() class. This is perfect for "PATCH" API requests where you only send the fields you want to update.

๐Ÿ”น bail

The bail rule is a performance and user experience optimizer. Once the first validation rule for a field fails, bail instructs the validator to stop checking any subsequent rules for that same field. This prevents a single field from returning a long list of redundant error messages. It is defined as "bail" or Bail().

๐Ÿ”น accepted

The accepted rule validates that the field's value is a "truthy" confirmation. It specifically checks if the value is True, 1, "yes", or "on". This is most commonly used for mandatory "Terms of Service" checkboxes in registration forms. You can use the string "accepted" or the Accepted() class.

๐Ÿ”น declined

The declined rule is the logical opposite of accepted. It validates that the field's value is a "falsy" rejection. It checks if the value is False, 0, "no", or "off". It is defined as "declined" or Declined(). Use this when you need a user to explicitly opt-out of a selection.

๐Ÿ”น filled

The filled rule ensures that if a field is present in the input, it must not be empty (not None, "", etc.). Unlike required, if the field is missing from the input entirely, it will still pass. It is essentially a "not empty if present" check. Define it as "filled" or Filled().

๐Ÿ”น present

The present rule validates that the field key exists in the input data, regardless of its value. Even if the value is None or an empty string, it will pass as long as the key is there. Use this to ensure a specific data structure is maintained. Define it as "present" or Present().

๐Ÿ”น missing

The missing rule ensures that the field is NOT part of the input data. If the key is found in the dictionary, validation fails. This is a security feature to prevent users from submitting fields that should only be handled internally. Define it as "missing" or Missing().

๐Ÿ”น prohibited

The prohibited rule validates that the field is either missing from the input or contains an "empty" value (like None or ""). It effectively forbids a field from having actual data. Define it as "prohibited" or Prohibited().

๐Ÿ”น exclude

The exclude rule is a utility rule that always passes but has a side effect: it removes the field from the final dictionary returned by v.validated(). This is useful for data you need for validation (like a password confirmation) but don't want to include in a final database save. Define it as "exclude" or Exclude().


๐Ÿ”ค String Rules

๐Ÿ”น string

The string rule validates that the input is a valid Python str type. It is the standard type-check rule for any text input. It is defined as "string" or String().

๐Ÿ”น alpha

The alpha rule ensures the string contains only alphabetic characters (A-Z, a-z). It will fail if the string contains numbers, spaces, or any symbols. Use it for fields like "First Name" where only letters are allowed. Define it as "alpha" or Alpha().

๐Ÿ”น alpha_num

The alpha_num rule validates that the string contains only alphanumeric characters (letters and numbers). Spaces and special symbols are prohibited. It is frequently used for IDs, usernames, or SKU codes. Define it as "alpha_num" or AlphaNum().

๐Ÿ”น alpha_dash

The alpha_dash rule allows for alphanumeric characters, dashes (-), and underscores (_). This is the industry standard for validating "slugs" used in URLs. It is defined as "alpha_dash" or AlphaDash().

๐Ÿ”น email

The email rule provides exhaustive validation for email addresses. By default, it uses standard RFC validation. However, it supports several advanced modes that can be combined (e.g., "email:rfc,dns"):

  • rfc: Strict RFC-compliant validation (Default).
  • strict: RFC validation without any common warnings or edge-case allowances.
  • dns: Checks if the domain in the email address has valid MX records (requires dnspython).
  • spoof: Detects homograph/spoofing attacks (requires idna).
  • filter: Compatible with PHP's filter_var email validation logic.
  • filter_unicode: PHP-style filter that allows Unicode characters in the local/domain parts. You can define it as "email" or using the Email() class with specific params.

๐Ÿ”น url

The url rule validates that the input is a correctly formatted URL. It checks for the presence of a protocol (http/https), a valid domain structure, and optional paths or query parameters. Define it as "url" or Url().

๐Ÿ”น uuid

The uuid rule ensures the string is a valid Universally Unique Identifier (UUID). It supports standard 36-character formats (e.g., 550e8400-e29b-41d4-a716-446655440000). Define it as "uuid" or Uuid().

๐Ÿ”น ulid

The ulid rule validates a Universally Unique Lexicographically Sortable Identifier. This is a 26-character sortable alternative to UUID. Define it as "ulid" or Ulid().

๐Ÿ”น ip

The ip rule validates that the input is a valid IP address. By default, it allows both IPv4 and IPv6. You can restrict it using "ip:v4" or "ip:v6". It uses Python's ipaddress module for robust checking. Define it as "ip" or Ip().

๐Ÿ”น hex

The hex rule validates that the string is a valid hexadecimal color code. It supports both 3-digit and 6-digit formats (e.g., #FFF or #FFFFFF). The hash # prefix is optional. Define it as "hex" or Hex().

๐Ÿ”น json

The json rule ensures the string is valid JSON-encoded data. It attempts to parse the string using Python's json.loads() and fails if a JSONDecodeError is raised. Define it as "json" or Json().

๐Ÿ”น regex

The regex rule allows for powerful custom validation using Regular Expressions. It checks if the input matches a given pattern. Note that patterns should not be enclosed in delimiters (like /.../) when using string syntax. Define it as "regex:pattern" or Regex("pattern").

๐Ÿ”น not_regex

The not_regex rule is the inverse of regex. It ensures the input does NOT match the specified pattern. This is useful for blacklisting certain keywords or characters. Define it as "not_regex:pattern" or NotRegex("pattern").

๐Ÿ”น starts_with

The starts_with rule ensures the string begins with one of the provided values. It can take multiple parameters (e.g., "starts_with:http://,https://"). The check is case-sensitive. Define it as "starts_with:val1,val2" or StartsWith("val1", "val2").

๐Ÿ”น doesnt_start_with

The doesnt_start_with rule ensures the string does NOT begin with any of the specified values. This is useful for preventing certain prefixes (e.g., test_). Define it as "doesnt_start_with:val1" or DoesntStartWith("val1").

๐Ÿ”น ends_with

The ends_with rule validates that the string ends with one of the provided values (e.g., "ends_with:.com,.net"). It is case-sensitive. Define it as "ends_with:val1,val2" or EndsWith("val1", "val2").

๐Ÿ”น doesnt_end_with

The doesnt_end_with rule ensures the string does NOT end with any of the specified suffixes. Define it as "doesnt_end_with:val1" or DoesntEndWith("val1").

๐Ÿ”น uppercase

The uppercase rule ensures that every alphabetic character in the string is in its uppercase form. Non-alphabetic characters (numbers, symbols) are ignored. Define it as "uppercase" or Uppercase().

๐Ÿ”น lowercase

The lowercase rule ensures that every alphabetic character in the string is in its lowercase form. This is commonly used for normalizing data like email addresses. Define it as "lowercase" or Lowercase().

๐Ÿ”น ascii

The ascii rule validates that the string contains only 7-bit ASCII characters. It will fail if any multibyte or Unicode characters are detected. Define it as "ascii" or Ascii().

๐Ÿ”น confirmed

The confirmed rule is a specialized security and UI rule. It validates that the current field matches another field named {field}_confirmation. For example, if the field is password, it will check if it matches password_confirmation. This is a quick way to handle "Confirm Password" logic without extra configuration. Define it as "confirmed" or Confirmed().



๐Ÿ”ข Numeric & Digits Rules

๐Ÿ”น numeric

The numeric rule ensures that the input value is a valid number. This includes Python int, float, and even strings that represent numbers (e.g., "123.45"). It is the most flexible numeric check. Define it as "numeric" or Numeric().

๐Ÿ”น integer

The integer rule validates that the input is a whole number. It accepts Python int types and numeric strings that do not contain a decimal point. Characters like ., ,, or letters will cause validation to fail. Define it as "integer" or Integer().

๐Ÿ”น decimal

The decimal rule ensures the input is a decimal/float number. It uses Python's decimal.Decimal for high-precision validation, making it perfect for financial data. It will fail for non-numeric strings or incorrectly formatted decimals. Define it as "decimal" or Decimal().

๐Ÿ”น digits

The digits rule ensures the input is numeric and has an exact number of digits. For example, "digits:5" ensures the value is exactly 5 digits long (e.g., "12345"). It is often used for PIN codes or fixed-length IDs. Define it as "digits:value" or Digits(value).

๐Ÿ”น digits_between

The digits_between rule validates that the field is numeric and its total digit count falls within a specified range $[min, max]$. This is useful for variable-length numeric identifiers like phone extension numbers. Define it as "digits_between:min,max" or DigitsBetween(min, max).

๐Ÿ”น min

The min rule is powerful and context-aware:

  • Numbers: It validates that the value is greater than or equal to the minimum.
  • Strings/Collections: It validates that the length (number of characters or elements) is at least the minimum. Define it as "min:value" or Min(value).

๐Ÿ”น max

The max rule is the counterpart to min and is also context-aware:

  • Numbers: It validates that the value is less than or equal to the maximum.
  • Strings/Collections: It validates that the length does not exceed the maximum.
  • Files: It can also be used to limit file size in bytes (though size or mimes are often preferred for clarity). Define it as "max:value" or Max(value).

๐Ÿ”น between

The between rule validates that a value or length falls within an inclusive range $[min, max]$. Like min/max, it works based on value for numbers and length for strings/arrays. Define it as "between:min,max" or Between(min, max).

๐Ÿ”น size

The size rule ensures strict equality for a value or length.

  • Numbers: The value must be exactly equal to the parameter.
  • Strings/Collections: The length must be exactly equal to the parameter.
  • Files: The file size must be exactly the specified number of bytes. Define it as "size:value" or Size(value).

๐Ÿ”น gt / gte / lt / lte

These rules provide explicit mathematical comparisons:

  • gt: Greater Than (>).
  • gte: Greater Than or Equal (>=).
  • lt: Less Than (<).
  • lte: Less Than or Equal (<=). These rules specifically perform numeric comparisons using decimal precision. They are defined as "gt:value", "gte:value", etc.

๐Ÿ”น max_digits / min_digits

The max_digits and min_digits rules specifically limit the number of digits in a numeric value, regardless of decimals or signs. For example, -12.34 has 4 digits. These rules are distinct from min/max as they count symbols rather than evaluating numerical worth. Define as "max_digits:value" or MaxDigits(value).

๐Ÿ”น multiple_of

The multiple_of rule ensures that the input value is a multiple of a given step. For example, "multiple_of:5" would allow 5, 10, 15, etc. It works with both integers and floats. Define it as "multiple_of:value" or MultipleOf(value).


๐Ÿ“… Date & Time Rules

๐Ÿ”น date

The date rule validates that the input is a valid date. It accepts Python date or datetime objects, as well as strings that can be processed by standard date parsers. Use it to ensure a field holds a real calendar date. Define it as "date" or Date().

๐Ÿ”น date_equals

The date_equals rule ensures the input date matches a specific date. You can provide a fixed date string (e.g., 2023-12-25) as the parameter. It compares only the date portion, ignoring time if present. Define it as "date_equals:date" or DateEquals("date").

๐Ÿ”น date_format

The date_format rule enforces a strict pattern for date strings using standard Python strftime placeholders (e.g., %Y-%m-%d). Validation will fail if the input does not match the format exactly. Define it as "date_format:format" or DateFormat("format").

๐Ÿ”น after / after_or_equal

These rules ensure that the input date occurs after (or on/after) a specific point in time. In addition to fixed dates, they support relative keywords:

  • today: Validation against the current date.
  • tomorrow: Validation against the next day.
  • yesterday: Validation against the previous day. Define as "after:today" or After("today").

๐Ÿ”น before / before_or_equal

These rules ensure that the input date occurs before (or on/before) a specific comparison date. They also support relative keywords like today, tomorrow, and yesterday. This is ideal for validating birthdates (must be before today). Define as "before:2030-01-01" or Before("2030-01-01").

๐Ÿ”น timezone

The timezone rule validates that the input string is a valid timezone identifier recognized by the system (e.g., "UTC", "Asia/Jakarta", "America/New_York"). It ensures compatibility with time-sensitive logic. Define it as "timezone" or Timezone().


๐Ÿ“ฆ Array & Collection Rules

๐Ÿ”น array

The array rule validates that the input is a Python dictionary (dict). This is typically used as a base check before validating nested fields within that dictionary. Use it to ensure your data structure matches your expectations. Define it as "array" or Array().

๐Ÿ”น list

The list rule ensures that the input is a Python list/sequence (list, tuple, set). It confirms that you are dealing with a collection of items rather than a single value or a keyed dictionary. Define it as "list" or List().

๐Ÿ”น entries

The entries rule validates the total number of items within an array or collection. For example, "entries:3" ensures the list has exactly 3 elements. This rule works for lists, dictionaries, and strings. Define it as "entries:value" or Entries(value).

๐Ÿ”น distinct

The distinct rule validates that a collection contains only unique values. It will fail if any duplicate items are found within a list or tuple. This is essential for fields like "Selected Tags" where duplicates are not allowed. Define it as "distinct" or Distinct().

๐Ÿ”น in_array

The in_array rule validates that the current field's value exists within another field that contains a list or array. For example, if selected_id must be one of the IDs in the available_ids list, use this. Define it as "in_array:other_field" or InArray("other_field").

๐Ÿ”น in_array_keys

The in_array_keys rule validates that the input value matches one of the keys of a specified dictionary in the input data. Use this when you need to validate if a value is a valid index for a related dynamic object. Define it as "in_array_keys:dict_field" or InArrayKeys("dict_field").


โš–๏ธ Comparison Rules

๐Ÿ”น same

The same rule validates that the value of the current field is exactly equal to the value of another field in the input data. This is essential for cross-field consistency, such as "Confirm Password" or "Repeat Email" fields. Define it as "same:other_field" or Same("other_field").

๐Ÿ”น different

The different rule ensures that the current field's value is not equal to another specified field's value. This is a common security practice to prevent users from using their username as their password. Define it as "different:other_field" or Different("other_field").

๐Ÿ”น in

The in rule validates that the input value exists within a provided list of allowed values. It supports multiple parameters (e.g., "in:admin,editor,viewer"). The check is case-sensitive and handles both string and numeric types. Define it as "in:val1,val2" or In("val1", "val2").

๐Ÿ”น not_in

The not_in rule is the inverse of in. It ensures the input value does NOT exist in the provided list of restricted values. Use this to blacklist specific inputs like reserved system names. Define as "not_in:val1,val2" or NotIn("val1", "val2").

๐Ÿ”น enum

The enum rule is a specialized version of the inclusion check designed for Python's Enum classes. It ensures the value is a valid member of the specified enum. When used in class format, it provides fluent methods like .only() or .exclude() to dynamically restrict choices. Define as "enum:EnumClassName" or Enum(EnumClass).

๐Ÿ”น contains

The contains rule validates that the input contains one or more specified sub-values. It is context-aware:

  • Strings: It checks if the search values are substrings of the input.
  • Lists/Arrays: It checks if the search values are present as elements in the list.
  • Dictionaries: It checks if the values match any of the dictionary's keys. Define it as "contains:val1,val2" or Contains("val1", "val2").

๐Ÿ”น exists

The exists rule is a database-level validation that ensures the input value exists in a specific table and column. This is crucial for foreign key integrity (e.g., verifying a user_id actually exists in the users table). Requires a Database Manager to be configured. Define as "exists:table,column" or Exists("table", "column").

๐Ÿ”น unique

The unique rule ensures that the input value does not already exist in a given database table and column. It is the standard rule for preventing duplicate usernames or emails. It supports an "ignore" parameter to skip checks for a specific record during updates. Requires a Database Manager. Define as "unique:table,column,ignore:id_field" or Unique("table", "column").


๐Ÿ“ File & Image Rules

๐Ÿ”น file

The file rule validates that the input is a valid file upload object. It is compatible with major Python web frameworks (Flask, FastAPI, Django) and checks for standard file attributes like a filename and content length. Use this as a base check before applying specific constraints like size or type. Define it as "file" or File().

๐Ÿ”น image

The image rule is a specialized file check that ensures the uploaded file is a common image format. It verifies the file's MIME type against a list of renderable formats including JPEG, PNG, GIF, BMP, SVG, and WebP. Define it as "image" or Image().

๐Ÿ”น mimes

The mimes rule validates the file's extension against a list of allowed types (e.g., "mimes:pdf,docx"). It checks the file suffix to determine its type, providing a quick way to filter uploads by their intended format. Define it as "mimes:ext1,ext2" or Mimes("ext1", "ext2").

๐Ÿ”น mimetypes

The mimetypes rule provides a more secure way to validate file types by checking the actual MIME content-type of the upload (e.g., "mimetypes:application/pdf,image/jpeg"). This is harder to spoof than a simple extension check. Define it as "mimetypes:type1,type2" or Mimetypes("type1", "type2").

๐Ÿ”น extensions

The extensions rule specifically validates that the file has one of the provided extensions. While similar to mimes, it focuses purely on the filename's characters rather than the underlying media type. Define it as "extensions:jpg,png" or Extensions("jpg", "png").

๐Ÿ”น dimensions

The dimensions rule provides exhaustive validation for image pixel sizes and aspect ratios. It is highly configurable and supports several specific parameters:

  • width: The image must be exactly this many pixels wide.
  • height: The image must be exactly this many pixels high.
  • min_width: The width must be at least this value.
  • max_width: The width cannot exceed this value.
  • min_height: The height must be at least this value.
  • max_height: The height cannot exceed this value.
  • ratio: The aspect ratio of the image (e.g., "3/2" or "1.5" for landscape, "1" for square). You can combine these parameters using the string syntax "dimensions:width=1200,height=800" or the Dimensions() class with named keyword arguments.

โ™Ÿ๏ธ Conditional & Utility Rules

๐Ÿ”น any_of

The any_of rule implements a logical "OR" operation for validation. It takes multiple rule sets as parameters (separated by commas) and passes if the input satisfies at least one of those sets. For example, "any_of:required|email,required|numeric" allows a field to be either a valid email or a valid number. This is powerful for fields with polymorphic data types. Define it as "any_of:rule_set1,rule_set2" or AnyOf(["rule_set1", "rule_set2"]).

๐Ÿ”น when

The when rule is the most sophisticated rule in the library, allowing for complex, dynamic validation logic. It applies a specific set of rules to a field only if a certain condition is met. This condition can be a closure/function that evaluates the entire input dataset or a boolean check against another field. It is the primary tool for building reactive forms where fields depend on each other's values. Define it using the When() class for full flexibility.

๐Ÿ”น prohibits

The prohibits rule creates a relationship of mutual exclusion between fields. If the current field has a value (is not empty), all other fields specified in the parameters must be missing or empty in the input data. Use this for "either-or" scenarios, such as allowing either a phone_number or an email_address, but not both simultaneously. Define it as "prohibits:field1,field2" or Prohibits("field1", "field2").


๐Ÿ”น required_if

The required_if rule makes a field mandatory only when another field matches a specific value. It is one of the most common conditional rules, used for scenarios like "if 'other' is selected in a dropdown, the 'description' field is required". Define it as "required_if:other_field,value" or RequiredIf("other_field", "value").

๐Ÿ”น required_unless

The required_unless rule is the logical opposite of required_if. It makes a field mandatory unless another field matches a specific value. This is useful for fields that should always be provided except in one specific edge case. Define it as "required_unless:other_field,value" or RequiredUnless("other_field", "value").

๐Ÿ”น required_with

The required_with rule makes a field mandatory if any of the other specified fields are present in the input data. Use this when a group of fields must be provided together if at least one of them is sent. Define it as "required_with:field1,field2" or RequiredWith("field1", "field2").

๐Ÿ”น required_with_all

The required_with_all rule is stricter than required_with. It makes a field mandatory only if all of the other specified fields are present in the input data. This ensures that a complete set of related fields must include the current field. Define it as "required_with_all:field1,field2" or RequiredWithAll("field1", "field2").

๐Ÿ”น required_without

The required_without rule makes a field mandatory if any of the other specified fields are missing from the input data. This is useful for ensuring that at least one of a set of alternatives is always provided (e.g., "either phone or email must be provided"). Define it as "required_without:email" or RequiredWithout("email").

๐Ÿ”น required_without_all

The required_without_all rule makes a field mandatory if all of the other specified fields are missing. It acts as a final safety check to ensure that a required input is provided if all other alternatives were omitted. Define it as "required_without_all:field1,field2" or RequiredWithoutAll("field1", "field2").

๐Ÿ”น required_if_accepted

The required_if_accepted rule makes a field mandatory only if another "agreement" field has been accepted (i.e., its value is True, 1, "yes", or "on"). This is common for legal forms where selecting a checkbox necessitates further information. Define it as "required_if_accepted:terms" or RequiredIfAccepted("terms").

๐Ÿ”น required_if_declined

The required_if_declined rule makes a field mandatory only if another field has been declined (i.e., its value is False, 0, "no", or "off"). Use this to prompt for a reason when a user opts out of something. Define it as "required_if_declined:mailing_list" or RequiredIfDeclined("mailing_list").

๐Ÿ”น required_array_keys

The required_array_keys rule is a structure-enforcement rule. It validates that the current input (which must be a dictionary) contains a specific set of keys. If any of the required keys are missing from the dictionary, validation fails. Define it as "required_array_keys:id,name,email" or RequiredArrayKeys("id", "name").

๐Ÿ”น prohibited_if

The prohibited_if rule forbids a field from having any value if another specified field matches a certain value. This is useful for disabling certain options based on a user's role or status. Define it as "prohibited_if:role,guest" or ProhibitedIf("role", "guest").

๐Ÿ”น prohibited_unless

The prohibited_unless rule forbids a field from having a value unless another field matches a specific value. This is a strict constraint for fields that are only allowed in very specific conditions. Define it as "prohibited_unless:state,debug" or ProhibitedUnless("state", "debug").

๐Ÿ”น prohibited_if_accepted

The prohibited_if_accepted rule forbids a field if another field has been accepted. For example, if a user selects "I do not want a receipt", you might prohibit the billing_address field to minimize data collection. Define it as "prohibited_if_accepted:no_receipt".

๐Ÿ”น prohibited_if_declined

The prohibited_if_declined rule forbids a field if another field has been declined. This is the inverse of the accepted variant and helps enforce logical consistency in conditional forms. Define it as "prohibited_if_declined:opt_in".

๐Ÿ”น present_if

The present_if rule requires that a field key must exist in the input dictionary if another field matches a specific value. Note that the value of the field can be empty (like None or ""); the rule only enforces that the key itself is present. Define it as "present_if:type,complex".

๐Ÿ”น present_unless

The present_unless rule requires that a field key must exist unless another field matches a specific value. It ensures structural consistency in your input data for almost all cases except the specified exception. Define it as "present_unless:status,draft".

๐Ÿ”น present_with

The present_with rule requires the current field to be present if any governing fields are present in the input. This is useful for grouping metadata fields that must exist if an optional header field is sent. Define it as "present_with:meta_header".

๐Ÿ”น present_with_all

The present_with_all rule requires the field to be present only if all of the specified other fields are also present. This enforces a complete record structure when a full set of related data is submitted. Define it as "present_with_all:f1,f2".

๐Ÿ”น missing_if

The missing_if rule enforces that a field must not exist in the input if another field matches a specific value. This is a powerful dynamic security constraint to prevent certain dataเธˆเธฒเธ appearing in specific contexts. Define it as "missing_if:state,final".

๐Ÿ”น missing_unless

The missing_unless rule forbids a field from being present unless another field matches a specific value. It is a very strict structure constraint for fields that are only permitted in unique scenarios. Define it as "missing_unless:auth,admin".

๐Ÿ”น missing_with

The missing_with rule ensures the current field is absent if any of the other specified fields are present. Use this to prevent conflicting or redundant fields from being submitted together. Define it as "missing_with:alternative_id".

๐Ÿ”น missing_with_all

The missing_with_all rule ensures the current field is absent if all of the other specified fields are present. This is the strictest form of absence enforcement for related field groups. Define it as "missing_with_all:f1,f2".

๐Ÿ”น exclude_if

The exclude_if rule dynamically removes the field from the final validated data if another field matches a certain value. This allows you to "clean" the output data based on other input parameters before passing it to your database or service. Define it as "exclude_if:save_meta,false".

๐Ÿ”น exclude_unless

The exclude_unless rule removes the field from the final output unless another field matches a specific value. This ensures only necessary data remains in the final dictionary. Define it as "exclude_unless:keep_temp,true".

๐Ÿ”น exclude_with

The exclude_with rule removes the field from the output if any of the specified other fields are present. This helps in de-duplicating data that might have come from multiple sources in the input. Define it as "exclude_with:primary_id".

๐Ÿ”น exclude_without

The exclude_without rule removes the field from the output if any of the specified other fields are missing. This is useful for cleaning up optional supplementary data that doesn't have its required primary counterparty. Define it as "exclude_without:parent_id".


๐Ÿ›ก๏ธ License

Safe Shield is open-sourced software licensed under the MIT license.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

safeshield-2.0.0.tar.gz (94.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

safeshield-2.0.0-py3-none-any.whl (87.1 kB view details)

Uploaded Python 3

File details

Details for the file safeshield-2.0.0.tar.gz.

File metadata

  • Download URL: safeshield-2.0.0.tar.gz
  • Upload date:
  • Size: 94.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.10.6

File hashes

Hashes for safeshield-2.0.0.tar.gz
Algorithm Hash digest
SHA256 4fafec5bab11151a1bcb97b5cfa8aa040a4a49eef56b0163ae3472e1779920da
MD5 994c28c83cb99603ef2797b0024b5ff5
BLAKE2b-256 caad20d5f0a71c529f44ad87087cda3e1d3637d034672e61e36c8139378e8493

See more details on using hashes here.

File details

Details for the file safeshield-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: safeshield-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 87.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.10.6

File hashes

Hashes for safeshield-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 aaeb787d2a7ca5d8eefe4f15e819995adc49c8c9314594f62970d1aae4c2bf08
MD5 db75c787bf6c12474ce8dafd6d7dfe7d
BLAKE2b-256 303745dca0f5dec6b96a210380b524a200bac47aec840ba65241759d665a3b25

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page