From c6b520db389e748046a85d1cafd9e6482c41426d Mon Sep 17 00:00:00 2001 From: Mohammed Saajid S <141727149+Mohammed-Saajid@users.noreply.github.com> Date: Tue, 11 Nov 2025 10:13:39 +0530 Subject: [PATCH 1/3] Documentation Updated --- docs/CODE_OF_CONDUCT.md | 45 +++ docs/CONTRIBUTING.md | 124 +++++++ docs/api-reference.md | 270 +++++++++++++++- docs/custom_validators.md | 66 ++++ docs/examples.md | 666 +++++++++++++++++++++++++++++++++++++- docs/getting-started.md | 404 ++++++++++++++++++++++- docs/index.md | 122 ++++++- mkdocs.yml | 3 + 8 files changed, 1682 insertions(+), 18 deletions(-) create mode 100644 docs/CODE_OF_CONDUCT.md create mode 100644 docs/CONTRIBUTING.md create mode 100644 docs/custom_validators.md diff --git a/docs/CODE_OF_CONDUCT.md b/docs/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..7442438 --- /dev/null +++ b/docs/CODE_OF_CONDUCT.md @@ -0,0 +1,45 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies within all project spaces, and it also applies when an individual is representing the project or its community in public spaces. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project maintainer using any of the [private contact addresses](https://github.com/dec0dOS/amazing-github-template#support). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, available at + +For answers to common questions about this code of conduct, see diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 100644 index 0000000..ec3a53c --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1,124 @@ +# Contributing to FastAPI Assets +Thank you for your interest in contributing to FastAPI Assets! We welcome contributions from the community to help improve and expand this project. Whether you're fixing bugs, adding new features, or improving documentation, your contributions are valuable. + +## Reporting Bugs + +Before creating bug reports, check the issue list. When creating a bug report, include: + +- **Use a clear descriptive title** +- **Describe the exact steps to reproduce the problem** +- **Provide specific examples to demonstrate the steps** +- **Describe the behavior you observed and what the problem is** +- **Explain which behavior you expected to see instead** +- **Include Python version, FastAPI Assets version, and OS information** +- **Include relevant error messages and stack traces** + +## Suggesting Enhancements + +Enhancement suggestions are tracked as GitHub issues. When creating an enhancement suggestion, include: + +- **Use a clear descriptive title** +- **Provide a step-by-step description of the suggested enhancement** +- **Provide specific examples to demonstrate the steps** +- **Describe the current behavior and expected behavior** +- **Explain why this enhancement would be useful** + +## Pull Requests + +- Fill in the required template +- Include appropriate test cases +- Update documentation and examples +- End all files with a newline + +## Development Setup + +### Prerequisites + +- Python 3.12 or higher +- Git +- pip + +### Setting Up Development Environment + +1. **Fork the repository** + +```bash +# Go to the GitHub repository and click "Fork" +``` + +2. **Clone your fork** + +```bash +git clone https://github.com/YOUR_USERNAME/fastapi-assets.git +cd fastapi-assets +``` + +3. **Create a virtual environment** + +```bash +python -m venv venv + +# Activate virtual environment +# On Windows: +venv\Scripts\activate +# On Unix/macOS: +source venv/bin/activate +``` + +4. **Install dependencies with development extras** + +```bash +pip install -e ".[dev,image,pandas]" +``` + +5. **Create a feature branch** + +```bash +git checkout -b feature/your-feature-name +``` + +## Development Workflow + +### Code Style + +FastAPI Assets uses: +- **Ruff** for linting and formatting +- **MyPy** for type checking +- **Pytest** for testing + +### Running Linting + +```bash +ruff check fastapi_assets tests +ruff format fastapi_assets tests +``` + +### Running Type Checks + +```bash +mypy fastapi_assets +``` + +### Running Tests + +```bash +pytest +pytest --cov=fastapi_assets +pytest tests/test_file_validator.py -v +``` + +## Making Changes + +1. Create a feature branch +2. Make your changes with type hints and docstrings +3. Format your code with ruff +4. Run tests to ensure everything passes +5. Run type checks with mypy +6. Commit with clear messages following conventional commits +7. Push to your fork +8. Create a pull request + +## Code of Conduct + +By participating in this project, you agree to abide by the Contributor Covenant Code of Conduct. + diff --git a/docs/api-reference.md b/docs/api-reference.md index cb57ed9..0aa33a6 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -1,17 +1,271 @@ # API Reference -This section provides a comprehensive reference for all the classes, functions, and methods available in the FastAPI Assets library. Use this guide to understand the capabilities of each component and how to utilize them effectively in your FastAPI applications. -## Table of Contents -- [Validators](#validators) -- [Utilities](#utilities) -- [Exceptions](#exceptions) +Complete API documentation for FastAPI Assets validators and utilities. -## Validators +## Core Module ### BaseValidator -The `BaseValidator` class serves as the foundational validator from which all other validators inherit. It provides common functionality for validating file uploads and request metadata. -## Utilities +**Module**: `fastapi_assets.core.base_validator` + +Abstract base class for all validators in FastAPI Assets. Provides standardized error handling and HTTP exception raising. + +#### Class Definition + +```python +class BaseValidator(abc.ABC): + """Abstract base class for creating reusable FastAPI validation dependencies.""" +``` + +#### Parameters + +- **status_code** (int, default: 400): HTTP status code to return on validation failure +- **error_detail** (Union[str, Callable], default: "Validation failed."): Error message or callable that generates error messages +- **validators** (Optional[List[Callable]], default: None): List of custom validation functions + +#### Methods + +##### `_raise_error()` + +Raises a standardized HTTPException with resolved error detail. + +```python +def _raise_error( + self, + value: Optional[Any] = None, + status_code: Optional[int] = None, + detail: Optional[Union[str, Callable[[Any], str]]] = None, +) -> None: + """Raises HTTPException with validated error message.""" +``` + +**Parameters**: +- `value`: The value that failed validation +- `status_code`: Override default status code +- `detail`: Override default error detail + +**Raises**: `HTTPException` with resolved status code and detail + +--- + +### ValidationError + +**Module**: `fastapi_assets.core.exceptions` + +Custom exception raised by validators during validation logic. + +```python +class ValidationError(Exception): + """Raised when validation logic fails.""" + + def __init__( + self, + detail: str, + status_code: int = 400 + ): + self.detail = detail + self.status_code = status_code +``` + +--- + +## File Validators + +### FileValidator + +**Module**: `fastapi_assets.validators.file_validator` + +General-purpose validator for file uploads with size, MIME type, and filename validation. + +#### Class Definition + +```python +class FileValidator(BaseValidator): + """Validates UploadFile objects for size, MIME type, and filename patterns.""" +``` + +#### Parameters + +- **max_size** (Optional[Union[str, int]], default: None): Maximum file size (e.g., "10MB", 1024) +- **min_size** (Optional[Union[str, int]], default: None): Minimum file size (e.g., "1KB") +- **content_types** (Optional[List[str]], default: None): Allowed MIME types with wildcard support +- **filename_pattern** (Optional[str], default: None): Regex pattern for filename validation +- **on_size_error_detail** (Optional[Union[str, Callable]], default: None): Custom error message for size validation +- **on_type_error_detail** (Optional[Union[str, Callable]], default: None): Custom error message for content type +- **on_filename_error_detail** (Optional[Union[str, Callable]], default: None): Custom error message for filename +- **status_code** (int, default: 400): HTTP status code on validation failure +- **error_detail** (Union[str, Callable], default: "Validation failed"): Default error message +- **validators** (Optional[List[Callable]], default: None): List of custom validators + +#### Size Format Support + +| Format | Example | Bytes | +|--------|---------|-------| +| Bytes | `"1024"` or `"1024B"` | 1024 | +| Kilobytes | `"5KB"` or `"5 KB"` | 5120 | +| Megabytes | `"10MB"` or `"10 MB"` | 10485760 | +| Gigabytes | `"1GB"` or `"1 GB"` | 1073741824 | +| Terabytes | `"1TB"` or `"1 TB"` | 1099511627776 | + +#### MIME Type Wildcards + +| Pattern | Matches | +|---------|---------| +| `"image/*"` | All image types (jpeg, png, gif, etc.) | +| `"text/*"` | All text types (plain, html, css, etc.) | +| `"application/*"` | All application types | +| `"image/jpeg"` | Specific MIME type only | + +--- + +### ImageValidator + +**Module**: `fastapi_assets.validators.image_validator` + +Specialized validator for image files with format, dimensions, and aspect ratio validation. + +#### Parameters + +Inherits all FileValidator parameters plus: + +- **allowed_formats** (Optional[List[str]], default: None): Allowed image formats (e.g., ["JPEG", "PNG"]) +- **min_resolution** (Optional[Tuple[int, int]], default: None): Minimum image resolution (width, height) +- **max_resolution** (Optional[Tuple[int, int]], default: None): Maximum image resolution (width, height) +- **aspect_ratios** (Optional[List[str]], default: None): Allowed aspect ratios (e.g., ["1:1", "16:9"]) +- **on_format_error_detail** (Optional[Union[str, Callable]], default: None): Custom error for format +- **on_dimension_error_detail** (Optional[Union[str, Callable]], default: None): Custom error for dimensions +- **on_aspect_ratio_error_detail** (Optional[Union[str, Callable]], default: None): Custom error for aspect ratio + +#### Supported Formats + +- JPEG / JPG +- PNG +- GIF +- WebP +- BMP +- TIFF + +--- + +### CSVValidator + +**Module**: `fastapi_assets.validators.csv_validator` + +Specialized validator for CSV files with schema, encoding, and row count validation. + +**Requirements**: Install with `pip install fastapi-assets[pandas]` + +#### Parameters + +Inherits all FileValidator parameters plus: + +- **encoding** (Optional[Union[str, List[str]]], default: None): Allowed encoding(s) for CSV +- **delimiter** (Optional[str], default: None): CSV delimiter character +- **required_columns** (Optional[List[str]], default: None): Columns that must exist +- **disallowed_columns** (Optional[List[str]], default: None): Columns that must not exist +- **min_rows** (Optional[int], default: None): Minimum number of data rows +- **max_rows** (Optional[int], default: None): Maximum number of data rows +- **header_check_only** (bool, default: False): Only validate headers without checking all rows +- **on_encoding_error_detail** (Optional[Union[str, Callable]], default: None): Custom encoding error +- **on_columns_error_detail** (Optional[Union[str, Callable]], default: None): Custom columns error +- **on_rows_error_detail** (Optional[Union[str, Callable]], default: None): Custom rows error + +--- + +## Request Validators + +### QueryValidator + +**Module**: `fastapi_assets.request_validators.query_validator` + +Validator for FastAPI query parameters with support for allowed values and constraints. + +#### Parameters + +- **param_name** (str): Name of the query parameter +- **_type** (type, default: str): Parameter type (int, str, float, bool, etc.) +- **default** (Optional[Any], default: None): Default value if parameter is missing +- **allowed_values** (Optional[List[Any]], default: None): List of allowed values +- **pattern** (Optional[str], default: None): Regex pattern for string validation +- **ge** (Optional[Union[int, float]], default: None): Greater than or equal to +- **le** (Optional[Union[int, float]], default: None): Less than or equal to +- **gt** (Optional[Union[int, float]], default: None): Greater than +- **lt** (Optional[Union[int, float]], default: None): Less than +- **error_detail** (Union[str, Callable], default: "Validation failed"): Error message +- **status_code** (int, default: 400): HTTP status code on validation failure + +--- + +### HeaderValidator + +**Module**: `fastapi_assets.request_validators.header_validator` + +Comprehensive validator for HTTP headers with pattern matching, format validation, allowed values, and custom validators. Extends FastAPI's `Header` dependency with granular error control. + +#### Class Definition + +```python +class HeaderValidator(BaseValidator): + """ + A dependency for validating HTTP headers with extended rules. + + Provides pattern matching, format validation, allowed values, + and custom validators with fine-grained error messages. + """ +``` + +#### Parameters + +- **default** (Any, default: Undefined): Default value if header is missing. If not provided, header is required. +- **alias** (Optional[str], default: None): The actual header name to extract (e.g., "X-API-Key", "Authorization") +- **convert_underscores** (bool, default: True): If True, underscores in parameter name convert to hyphens in header name +- **pattern** (Optional[str], default: None): Regex pattern that header value must match (cannot be used with `format`) +- **format** (Optional[str], default: None): Predefined format name for validation +- **allowed_values** (Optional[List[str]], default: None): List of exact string values allowed for the header +- **validators** (Optional[List[Callable]], default: None): List of custom validation functions (sync or async) +- **title** (Optional[str], default: None): Title for the header in OpenAPI documentation +- **description** (Optional[str], default: None): Description for the header in OpenAPI documentation +- **on_required_error_detail** (str, default: "Required header is missing."): Error message if header is missing +- **on_pattern_error_detail** (str, default: "Header has an invalid format."): Error message if pattern/format fails +- **on_allowed_values_error_detail** (str, default: "Header value is not allowed."): Error message if value not in allowed list +- **on_custom_validator_error_detail** (str, default: "Header failed custom validation."): Error message if custom validator fails +- **status_code** (int, default: 400): HTTP status code for validation errors +- **error_detail** (str, default: "Header Validation Failed"): Generic fallback error message + + +--- + +### CookieValidator + +**Module**: `fastapi_assets.request_validators.cookie_validator` + +Validator for cookie values with pattern matching and constraints. + +#### Parameters + +- **alias** (str): Name of the cookie to validate +- **pattern** (Optional[str], default: None): Regex pattern for cookie value +- **error_detail** (Union[str, Callable], default: "Validation failed"): Error message +- **status_code** (int, default: 400): HTTP status code on validation failure + +--- + +### PathValidator + +**Module**: `fastapi_assets.request_validators.path_validator` + +Validator for path parameters with type conversion and pattern matching. + +#### Parameters + +- **param_name** (str): Name of the path parameter +- **_type** (type, default: str): Parameter type +- **pattern** (Optional[str], default: None): Regex pattern for validation +- **error_detail** (Union[str, Callable], default: "Validation failed"): Error message +- **status_code** (int, default: 400): HTTP status code on validation failure + +--- + ## Exceptions ### ValidationError diff --git a/docs/custom_validators.md b/docs/custom_validators.md new file mode 100644 index 0000000..b44aafd --- /dev/null +++ b/docs/custom_validators.md @@ -0,0 +1,66 @@ +# Custom Validators +FastAPI Assets allows you to create custom validators by extending the base validator classes. This enables you to implement specific validation logic tailored to your application's needs. You can also create custom validation functions to be used with existing validators. Let's explore how to create and use custom validators. + +### Creating a Custom File Validator + +To create a custom file validator, you can subclass the `FileValidator` and override the `validate` method to include your custom logic. Here's an example of a custom file validator that checks for a specific filename pattern: + +```python +import re +from fastapi_assets.validators import FileValidator +class CustomFileValidator(FileValidator): + def __init__(self, filename_pattern: str, **kwargs): + super().__init__(**kwargs) + self.filename_pattern = re.compile(filename_pattern) + + async def validate(self, file): + await super().validate(file) # Perform standard validations + if not self.filename_pattern.match(file.filename): + raise ValueError(f"Filename '{file.filename}' does not match the required pattern.") +``` + +You can then use this custom validator in your FastAPI routes: + +```python +from fastapi import FastAPI, UploadFile, Depends +app = FastAPI() +custom_validator = CustomFileValidator( + filename_pattern=r"^[\w\s-]+\.(jpg|jpeg|png|gif)$", + max_size="5MB", + content_types=["image/jpeg", "image/png", "image/gif"] +) +@app.post("/upload/custom/") +async def upload_custom_file(file: UploadFile = Depends(custom_validator)): + return {"filename": file.filename, "size": file.size} +``` +### Creating a Custom Validation Function +You can also create custom validation functions that can be passed to existing validators. For example, let's create a custom function to validate that a file's size is an exact multiple of 1024 bytes: + +```python +from fastapi_assets.validators import FileValidator +from fastapi_assets.core import ValidationError +def exact_multiple_of_1024(file): + if file.size % 1024 != 0: + raise ValidationError("File size must be an exact multiple of 1024 bytes.") +file_validator = FileValidator( + max_size="10MB", + content_types=["application/octet-stream"], + validators=[exact_multiple_of_1024] +) +``` + +You can then use this validator in your FastAPI routes: + +```python +from fastapi import FastAPI, UploadFile, Depends +app = FastAPI() +@app.post("/upload/exact-multiple/") +async def upload_exact_multiple_file(file: UploadFile = Depends(file_validator)): + return {"filename": file.filename, "size": file.size} +``` + +### Summary +Creating custom validators in FastAPI Assets allows you to implement specific validation logic that suits your application's requirements. By subclassing existing validators or creating custom validation functions, you can enhance the validation capabilities of your FastAPI applications. + +## Contributing to FastAPI Assets +Thank you for your interest in contributing to FastAPI Assets! We welcome contributions from the community to help improve and expand this project. Whether you're fixing bugs, adding new features, or improving documentation, your contributions are valuable. diff --git a/docs/examples.md b/docs/examples.md index 8bdf483..c670f63 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -1,2 +1,664 @@ -# Examples -This document provides several examples to illustrate the usage of the features described in this project. Each example includes a brief description, the code snippet, and the expected output. +# Examples & Use Cases + +This document provides practical examples demonstrating how to use FastAPI Assets in real-world scenarios. + +## Table of Contents + +1. [File Upload Examples](#file-upload-examples) +2. [Image Processing](#image-processing) +3. [CSV Import](#csv-import) +4. [Request Parameter Validation](#request-parameter-validation) +5. [Error Handling](#error-handling) +6. [Advanced Patterns](#advanced-patterns) + +## File Upload Examples + +### Basic File Upload + +Simple file upload with size and type validation: + +```python +from fastapi import FastAPI, UploadFile, Depends +from fastapi_assets.validators import FileValidator + +app = FastAPI() + +# Create a simple file validator +file_validator = FileValidator( + max_size="10MB", + content_types=["application/pdf"] +) + +@app.post("/upload/pdf/") +async def upload_pdf(file: UploadFile = Depends(file_validator)): + """Upload a PDF file.""" + return { + "filename": file.filename, + "content_type": file.content_type, + "size": file.size + } +``` + +### Multiple File Type Support + +Accepting multiple file types with different validators: + +```python +from fastapi import FastAPI, UploadFile, Depends +from fastapi_assets.validators import FileValidator + +app = FastAPI() + +# PDF validator +pdf_validator = FileValidator( + max_size="20MB", + content_types=["application/pdf"] +) + +# Image validator +image_validator = FileValidator( + max_size="5MB", + content_types=["image/jpeg", "image/png", "image/gif"] +) + +# Document validator +doc_validator = FileValidator( + max_size="15MB", + content_types=[ + "application/msword", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document" + ] +) + +@app.post("/upload/document/") +async def upload_document(file: UploadFile = Depends(pdf_validator)): + return {"type": "pdf", "filename": file.filename} + +@app.post("/upload/image/") +async def upload_image(file: UploadFile = Depends(image_validator)): + return {"type": "image", "filename": file.filename} + +@app.post("/upload/document-word/") +async def upload_word_document(file: UploadFile = Depends(doc_validator)): + return {"type": "word", "filename": file.filename} +``` + +### Filename Validation + +Validating filenames with regex patterns: + +```python +from fastapi_assets.validators import FileValidator + +# Only allow alphanumeric filenames with specific extensions +strict_filename_validator = FileValidator( + max_size="5MB", + filename_pattern=r"^[a-zA-Z0-9_\-]+\.(pdf|doc|docx|txt)$", + on_filename_error_detail="Filename must contain only letters, numbers, hyphens, and underscores" +) + +@app.post("/upload/") +async def upload_with_filename_validation( + file: UploadFile = Depends(strict_filename_validator) +): + return {"filename": file.filename} +``` + +--- + +## Image Processing + +### Profile Photo Upload + +Validate profile photos with size and dimension constraints: + +```python +from fastapi_assets.validators import ImageValidator + +# Profile photo validator +profile_validator = ImageValidator( + max_size="2MB", + min_size="100KB", + allowed_formats=["JPEG", "PNG"], + min_resolution=(200, 200), + max_resolution=(4000, 4000), + on_size_error_detail="Profile photo must be between 100KB and 2MB", + on_dimension_error_detail="Image must be at least 200x200 pixels" +) + +@app.post("/profile/photo/") +async def upload_profile_photo( + file: UploadFile = Depends(profile_validator) +): + """Upload and validate a profile photo.""" + return { + "filename": file.filename, + "status": "validated", + "message": "Profile photo updated successfully" + } +``` + +### Avatar Upload + +Strict square image validation for avatars: + +```python +# Avatar validator - strict square format +avatar_validator = ImageValidator( + max_size="512KB", + allowed_formats=["PNG"], + min_resolution=(64, 64), + max_resolution=(256, 256), + aspect_ratios=["1:1"], +) + +@app.post("/avatar/") +async def upload_avatar(file: UploadFile = Depends(avatar_validator)): + """Upload user avatar.""" + return {"filename": file.filename, "type": "avatar"} +``` + +### Banner/Hero Image + +Landscape image validation: + +```python +# Banner validator - landscape format +banner_validator = ImageValidator( + max_size="10MB", + allowed_formats=["JPEG", "PNG", "WebP"], + min_resolution=(1920, 1080), + aspect_ratios=["16:9", "4:3"], +) + +@app.post("/banner/") +async def upload_banner(file: UploadFile = Depends(banner_validator)): + """Upload banner image.""" + return {"filename": file.filename, "type": "banner"} +``` + +### Image Gallery Upload + +Multiple image format support: + +```python +# Gallery validator - flexible dimensions +gallery_validator = ImageValidator( + max_size="8MB", + allowed_formats=["JPEG", "PNG", "WebP", "GIF"], + min_resolution=(800, 600), + max_resolution=(5000, 5000), +) + +@app.post("/gallery/images/") +async def upload_gallery_image(file: UploadFile = Depends(gallery_validator)): + """Upload image to gallery.""" + return {"filename": file.filename, "type": "gallery"} +``` + +--- + +## CSV Import + +### User Data Import + +Import user data from CSV with schema validation: + +```python +from fastapi_assets.validators import CSVValidator + +# User data CSV validator +user_csv_validator = CSVValidator( + max_size="5MB", + encoding="utf-8", + delimiter=",", + required_columns=["id", "name", "email", "phone"], + min_rows=1, + max_rows=10000, + on_columns_error_detail="CSV must contain: id, name, email, phone" +) + +@app.post("/import/users/") +async def import_users(file: UploadFile = Depends(user_csv_validator)): + """Import users from CSV.""" + # In real app, you would parse and import the data + return { + "filename": file.filename, + "status": "imported", + "message": "Users imported successfully" + } +``` + +### Sales Data Import + +CSV with flexible encoding support: + +```python +# Sales data validator +sales_validator = CSVValidator( + max_size="50MB", + encoding=["utf-8", "latin-1"], # Support multiple encodings + delimiter=",", + required_columns=["date", "product_id", "quantity", "price"], + disallowed_columns=["internal_notes", "cost"], + min_rows=1, + max_rows=100000, + header_check_only=True # Don't validate every row for performance +) + +@app.post("/import/sales/") +async def import_sales(file: UploadFile = Depends(sales_validator)): + """Import sales data from CSV.""" + return { + "filename": file.filename, + "status": "imported", + "message": "Sales data imported successfully" + } +``` + +### Student Records Import + +CSV with strict column validation: + +```python +# Student records validator +student_csv_validator = CSVValidator( + max_size="10MB", + encoding="utf-8", + delimiter=",", + required_columns=["student_id", "first_name", "last_name", "email", "grade"], + disallowed_columns=["ssn", "password"], # Never allow sensitive data + min_rows=1, + max_rows=50000 +) + +@app.post("/import/students/") +async def import_student_records(file: UploadFile = Depends(student_csv_validator)): + """Import student records.""" + return { + "filename": file.filename, + "status": "imported" + } +``` + +--- + +## Request Parameter Validation + +### Query Parameter Validation + +Validate pagination and filtering: + +```python +from fastapi_assets.request_validators import QueryValidator + +app = FastAPI() + +# Pagination parameters +page_validator = QueryValidator( + "page", + _type=int, + default=1, + ge=1, + le=1000 +) + +per_page_validator = QueryValidator( + "per_page", + _type=int, + default=20, + ge=1, + le=100 +) + +# Status filter +status_validator = QueryValidator( + "status", + _type=str, + allowed_values=["active", "inactive", "pending"], + default="active" +) + +@app.get("/items/") +async def list_items( + page: int = Depends(page_validator()), + per_page: int = Depends(per_page_validator()), + status: str = Depends(status_validator()) +): + """List items with pagination and filtering.""" + return { + "page": page, + "per_page": per_page, + "status": status, + "total": 1000 + } +``` + +### Header Validation + +Validate authorization and custom headers: + +```python +from fastapi_assets.request_validators import HeaderValidator + +app = FastAPI() + +# Authorization header validator +auth_validator = HeaderValidator( + "authorization", + pattern=r"^Bearer [A-Za-z0-9\-._~\+\/]+=*$" +) + +# API key header validator +api_key_validator = HeaderValidator( + "x-api-key", + pattern=r"^[a-f0-9]{32}$" +) + +@app.get("/protected/") +async def protected_endpoint( + auth: str = Depends(auth_validator()) +): + """Protected endpoint requiring authorization.""" + return {"status": "authorized"} + +@app.post("/api/data/") +async def api_endpoint( + api_key: str = Depends(api_key_validator()) +): + """API endpoint requiring API key.""" + return {"status": "authenticated"} +``` + +### Cookie Validation + +Validate session and preference cookies: + +```python +from fastapi_assets.request_validators import CookieValidator + +app = FastAPI() + +# Session cookie validator +session_validator = CookieValidator( + "session_id", + pattern=r"^[a-f0-9]{32}$" +) + +@app.get("/dashboard/") +async def dashboard( + session_id: str = Depends(session_validator()) +): + """Dashboard requiring valid session.""" + return {"session": session_id, "user": "john_doe"} +``` + +--- + +## Error Handling + +### Custom Error Messages + +Provide user-friendly error messages: + +```python +from fastapi_assets.validators import FileValidator + +# Validator with custom error messages +file_validator = FileValidator( + max_size="5MB", + min_size="100KB", + content_types=["application/pdf"], + on_size_error_detail="File must be between 100KB and 5MB. Please try again.", + on_type_error_detail="Only PDF files are accepted. Please upload a PDF.", + on_filename_error_detail="Filename contains invalid characters." +) + +@app.post("/upload/") +async def upload_file(file: UploadFile = Depends(file_validator)): + return {"filename": file.filename} +``` + +### Dynamic Error Messages + +Generate contextual error messages: + +```python +from fastapi_assets.validators import FileValidator + +def format_size_error(size_bytes): + # Convert bytes to human-readable format + for unit in ['B', 'KB', 'MB', 'GB']: + if size_bytes < 1024: + return f"File is {size_bytes:.1f}{unit}, but maximum is 5MB" + size_bytes /= 1024 + return "File is too large" + +file_validator = FileValidator( + max_size="5MB", + on_size_error_detail=format_size_error +) + +@app.post("/upload/") +async def upload_file(file: UploadFile = Depends(file_validator)): + return {"filename": file.filename} +``` + +### Global Exception Handler + +Custom error response format: + +```python +from fastapi import FastAPI, HTTPException +from fastapi.responses import JSONResponse + +app = FastAPI() + +@app.exception_handler(HTTPException) +async def http_exception_handler(request, exc): + """Custom HTTP exception handler.""" + return JSONResponse( + status_code=exc.status_code, + content={ + "success": False, + "error": exc.detail, + "path": str(request.url.path), + "timestamp": str(datetime.now()) + } + ) +``` + +--- + +## Advanced Patterns + +### Reusable Validator Configuration + +Create a module for centralized validator definitions: + +```python +# validators.py +from fastapi_assets.validators import FileValidator, ImageValidator, CSVValidator + +# Profile validators +profile_photo = ImageValidator( + max_size="2MB", + allowed_formats=["JPEG", "PNG"], + min_resolution=(200, 200) +) + +profile_banner = ImageValidator( + max_size="5MB", + allowed_formats=["JPEG", "PNG", "WebP"], + min_resolution=(1200, 600) +) + +# Document validators +pdf_document = FileValidator( + max_size="20MB", + content_types=["application/pdf"] +) + +resume = FileValidator( + max_size="5MB", + content_types=["application/pdf", "application/msword"], + filename_pattern=r"^[a-zA-Z0-9_\-]+\.(pdf|doc|docx)$" +) + +# Data validators +user_data_csv = CSVValidator( + max_size="10MB", + required_columns=["id", "name", "email"], + max_rows=50000 +) + +# routes.py +from fastapi import FastAPI, UploadFile, Depends +from . import validators + +app = FastAPI() + +@app.post("/profile/photo/") +async def update_profile_photo( + file: UploadFile = Depends(validators.profile_photo) +): + return {"status": "updated"} + +@app.post("/upload/resume/") +async def upload_resume( + file: UploadFile = Depends(validators.resume) +): + return {"status": "uploaded"} + +@app.post("/import/users/") +async def import_users( + file: UploadFile = Depends(validators.user_data_csv) +): + return {"status": "imported"} +``` + +### Conditional Validation + +Validate based on conditions: + +```python +from fastapi import FastAPI, UploadFile, Depends, Query +from fastapi_assets.validators import FileValidator, ImageValidator + +app = FastAPI() + +# Validators for different upload types +image_validator = ImageValidator(max_size="5MB") +document_validator = FileValidator(max_size="20MB") + +@app.post("/upload/") +async def upload_file( + file: UploadFile = Depends(), + upload_type: str = Query(..., regex="^(image|document)$") +): + """Upload file with type-specific validation.""" + if upload_type == "image": + validator = image_validator + else: + validator = document_validator + + # Validate the file + validated_file = await validator(file) + + return { + "type": upload_type, + "filename": validated_file.filename + } +``` + +### Combined Validators + +Use file and request validators together: + +```python +from fastapi_assets.validators import ImageValidator +from fastapi_assets.request_validators import QueryValidator + +app = FastAPI() + +image_validator = ImageValidator( + max_size="5MB", + allowed_formats=["JPEG", "PNG"] +) + +quality_validator = QueryValidator( + "quality", + _type=str, + allowed_values=["low", "medium", "high"], + default="medium" +) + +compression_validator = QueryValidator( + "compress", + _type=bool, + default=False +) + +@app.post("/upload/image/") +async def upload_and_process_image( + file: UploadFile = Depends(image_validator), + quality: str = Depends(quality_validator()), + compress: bool = Depends(compression_validator()) +): + """Upload and process image with options.""" + return { + "filename": file.filename, + "quality": quality, + "compress": compress, + "status": "processed" + } +``` + +### Batch File Upload with Validation + +Handle multiple files with individual validation: + +```python +from typing import List + +@app.post("/upload/images/batch/") +async def upload_images_batch( + files: List[UploadFile] = Depends() +): + """Upload multiple images with validation.""" + results = [] + + for file in files: + try: + # Validate each file + validated_file = await image_validator(file) + results.append({ + "filename": file.filename, + "status": "success", + "size": file.size + }) + except Exception as e: + results.append({ + "filename": file.filename, + "status": "error", + "error": str(e) + }) + + return {"results": results} +``` + +--- + +## Best Practices + +1. **Define validators once** - Create validators in a separate module and reuse them +2. **Use meaningful error messages** - Help users understand what went wrong +3. **Set reasonable limits** - Balance security with user experience +4. **Log validation failures** - Track issues for debugging +5. **Test validators** - Unit test your validators independently +6. **Document requirements** - Clearly document file requirements in API docs +7. **Consider performance** - Use `header_check_only=True` for large CSV files + +--- + + diff --git a/docs/getting-started.md b/docs/getting-started.md index bd24500..8c3ccc6 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -1,9 +1,409 @@ # Getting Started with FastAPI Assets -Welcome to the FastAPI Assets getting started guide! This document will help you set up and integrate FastAPI Assets into your FastAPI application quickly and easily. + +Welcome to FastAPI Assets! This comprehensive guide will help you install, configure, and start using FastAPI Assets in your FastAPI applications. + +## Table of Contents + +1. [Installation](#installation) +2. [Basic Setup](#basic-setup) +3. [Your First Validator](#your-first-validator) +4. [Common Patterns](#common-patterns) +5. [Error Handling](#error-handling) +6. [Next Steps](#next-steps) ## Installation -To install FastAPI Assets, you can use pip. Run the following command in your terminal: + +### Requirements + +- Python 3.12 or higher +- FastAPI 0.119.1 or higher + +### Basic Installation + +To install FastAPI Assets with core functionality: ```bash pip install fastapi-assets ``` + +### Installation with Optional Dependencies + +For image validation support: + +```bash +pip install fastapi-assets[image] +``` + +For CSV validation support: + +```bash +pip install fastapi-assets[pandas] +``` + +For all features: + +```bash +pip install fastapi-assets[image,pandas] +``` + +### Verify Installation + +To verify that FastAPI Assets is installed correctly: + +```python +import fastapi_assets +print(fastapi_assets.__version__) +``` + +## Basic Setup + +### Minimal FastAPI Application + +Here's a minimal FastAPI application with FastAPI Assets: + +```python +from fastapi import FastAPI, UploadFile, Depends +from fastapi_assets.validators import FileValidator + +app = FastAPI() + +# Create a file validator instance +file_validator = FileValidator( + max_size="10MB", + content_types=["image/jpeg", "image/png"] +) + +@app.post("/upload/") +async def upload_file(file: UploadFile = Depends(file_validator)): + """Upload and validate a file.""" + return { + "filename": file.filename, + "content_type": file.content_type + } + +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=8000) +``` + +## Your First Validator + +### File Upload Validation + +FileValidator is the foundation for all file validation in FastAPI Assets. Here's how to use it: + +```python +from fastapi import FastAPI, UploadFile, Depends +from fastapi_assets.validators import FileValidator + +app = FastAPI() + +# Create validators for different use cases +profile_photo_validator = FileValidator( + max_size="2MB", + min_size="10KB", + content_types=["image/jpeg", "image/png", "image/gif"], + filename_pattern=r"^[\w\s-]+\.(jpg|jpeg|png|gif)$" +) + +document_validator = FileValidator( + max_size="20MB", + content_types=["application/pdf", "application/msword"] +) + +@app.post("/upload/profile-photo/") +async def upload_profile_photo( + file: UploadFile = Depends(profile_photo_validator) +): + """Upload a profile photo with validation.""" + return {"filename": file.filename, "size": file.size} + +@app.post("/upload/document/") +async def upload_document( + file: UploadFile = Depends(document_validator) +): + """Upload a document with validation.""" + return {"filename": file.filename} +``` + +### Image Validation + +For specialized image validation with Pillow: + +```python +from fastapi_assets.validators import ImageValidator + +app = FastAPI() + +image_validator = ImageValidator( + max_size="5MB", + allowed_formats=["JPEG", "PNG"], + min_resolution=(800, 600), + max_resolution=(4000, 4000), + aspect_ratios=["1:1", "16:9"] +) + +@app.post("/upload/image/") +async def upload_image(file: UploadFile = Depends(image_validator)): + """Upload and validate an image file.""" + return {"filename": file.filename, "status": "validated"} +``` + +### CSV Validation + +For CSV file validation with schema checking: + +```python +from fastapi_assets.validators import CSVValidator + +app = FastAPI() + +csv_validator = CSVValidator( + encoding="utf-8", + delimiter=",", + required_columns=["id", "name", "email"], + disallowed_columns=["password"], + min_rows=1, + max_rows=10000 +) + +@app.post("/upload/csv/") +async def upload_csv(file: UploadFile = Depends(csv_validator)): + """Upload and validate a CSV file.""" + return {"filename": file.filename, "status": "validated"} +``` + +## Common Patterns + +### Reusable Validators + +It's best practice to define validators once and reuse them: + +```python +# validators.py +from fastapi_assets.validators import FileValidator, ImageValidator + +# Profile images +profile_image_validator = ImageValidator( + max_size="2MB", + allowed_formats=["JPEG", "PNG"], + min_resolution=(200, 200) +) + +# Documents +pdf_validator = FileValidator( + max_size="10MB", + content_types=["application/pdf"] +) + +# Avatars +avatar_validator = ImageValidator( + max_size="512KB", + allowed_formats=["PNG"], + min_resolution=(64, 64), + max_resolution=(256, 256), +) +``` + +Then import and use in your routes: + +```python +# routes.py +from fastapi import FastAPI, UploadFile, Depends +from .validators import profile_image_validator, pdf_validator, avatar_validator + +app = FastAPI() + +@app.post("/profile/photo/") +async def update_profile_photo( + file: UploadFile = Depends(profile_image_validator) +): + return {"status": "uploaded"} + +@app.post("/submit/document/") +async def submit_document( + file: UploadFile = Depends(pdf_validator) +): + return {"status": "submitted"} + +@app.post("/avatar/") +async def upload_avatar( + file: UploadFile = Depends(avatar_validator) +): + return {"status": "updated"} +``` + +### Multiple Validators + +You can combine multiple validators in a single endpoint: + +```python +from fastapi_assets.validators import FileValidator, ImageValidator +from fastapi_assets.request_validators import QueryValidator + +app = FastAPI() + +image_validator = ImageValidator(max_size="5MB") +quality_validator = QueryValidator( + "quality", + _type=str, + allowed_values=["high", "medium", "low"] +) + +@app.post("/process/image/") +async def process_image( + file: UploadFile = Depends(image_validator), + quality: str = Depends(quality_validator()) +): + """Process an image with specified quality.""" + return {"filename": file.filename, "quality": quality} +``` + +### Custom Error Messages + +Customize validation error messages: + +```python +file_validator = FileValidator( + max_size="5MB", + min_size="100KB", + content_types=["image/*"], + on_size_error_detail="File must be between 100KB and 5MB", + on_type_error_detail="Only image files are allowed", + on_filename_error_detail="Filename contains invalid characters" +) +``` + +### Dynamic Error Messages + +Use callables for dynamic error messages: + +```python +def size_error_message(value): + return f"File size {value} bytes exceeds the limit" + +file_validator = FileValidator( + max_size="5MB", + on_size_error_detail=size_error_message +) +``` + +## Error Handling + +### Understanding Validation Errors + +When validation fails, FastAPI Assets raises HTTPException with appropriate status codes: + +```python +# Automatic error handling +@app.post("/upload/") +async def upload_file(file: UploadFile = Depends(file_validator)): + # If validation fails, a 400 error is automatically returned + return {"filename": file.filename} +``` + + +### Common Error Status Codes + +- **400**: Bad Request - Validation failed (default) +- **413**: Payload Too Large - File exceeds max_size +- **415**: Unsupported Media Type - Content type not allowed + +### Custom Status Codes + +```python +file_validator = FileValidator( + max_size="5MB", + status_code=422 # Unprocessable Entity +) +``` + +## Request Parameter Validation + +### Query Parameters + +```python +from fastapi_assets.request_validators import QueryValidator + +app = FastAPI() + +page_validator = QueryValidator( + "page", + _type=int, + default=1, + ge=1, + le=1000 +) + +sort_validator = QueryValidator( + "sort", + _type=str, + allowed_values=["name", "date", "size"], + default="name" +) + +@app.get("/items/") +async def list_items( + page: int = Depends(page_validator()), + sort: str = Depends(sort_validator()) +): + return {"page": page, "sort": sort} +``` + +### Header Validation + +```python +from fastapi_assets.request_validators import HeaderValidator + +app = FastAPI() + +auth_header_validator = HeaderValidator( + "authorization", + pattern=r"^Bearer [A-Za-z0-9\-._~\+\/]+=*$" +) + +@app.get("/protected/") +async def protected_endpoint( + authorization: str = Depends(auth_header_validator()) +): + return {"status": "authorized"} +``` + +### Cookie Validation + +```python +from fastapi_assets.request_validators import CookieValidator + +app = FastAPI() + +session_cookie_validator = CookieValidator( + "session_id", + pattern=r"^[a-f0-9]{32}$" +) + +@app.get("/dashboard/") +async def dashboard( + session_id: str = Depends(session_cookie_validator()) +): + return {"session": session_id} +``` + + +## Next Steps + +- Read the [API Reference](./api-reference.md) for detailed documentation on all validators +- Check out [Examples](./examples.md) for real-world use cases +- Explore [Custom Validators](./custom_validators.md) to create your own validation logic +- Review the [Contributing Guide](./CONTRIBUTING.md) if you want to contribute + +## Additional Resources + +- [FastAPI Documentation](https://fastapi.tiangolo.com/) +- [Pydantic Documentation](https://docs.pydantic.dev/) +- [Starlette Documentation](https://www.starlette.io/) + +--- + +**Need Help?** + +- Open an issue on [GitHub](https://github.com/OpenVerge/fastapi-assets) diff --git a/docs/index.md b/docs/index.md index 9fcd1b6..461fb50 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,10 +1,120 @@ -# Welcome to FastAPI Assets documentation! +# FastAPI Assets Documentation -FastAPI Assets is a powerful validation and assertion toolkit designed specifically for FastAPI applications. It simplifies the process of validating file uploads and request metadata, ensuring that your application handles user input securely and efficiently. -Explore the sections below to learn more about how to integrate FastAPI Assets into your projects and make the most of its features. +**FastAPI Assets** is a powerful, production-ready validation and assertion toolkit designed specifically for FastAPI applications. It simplifies the process of validating file uploads and request metadata, ensuring that your application handles user input securely and efficiently. -- [Getting Started](getting-started.md) +## Overview -- [API Reference](api-reference.md) +FastAPI Assets provides a comprehensive suite of validators that integrate seamlessly with FastAPI's dependency injection system. Whether you're validating file uploads, image files, CSV data, or request parameters, FastAPI Assets provides intuitive, type-safe APIs that make validation simple and robust. -- [Examples](examples.md) +### Why FastAPI Assets? + +- **Security First**: Built with security best practices to prevent common vulnerabilities +- **Performance Optimized**: Efficient streaming validation that doesn't load entire files into memory +- **Type Safe**: Full type hints and modern Python support for better IDE integration +- **Modular Design**: Use only what you need - validators are independent and composable +- **Well Documented**: Comprehensive API documentation and practical examples +- **Thoroughly Tested**: Extensive test coverage ensures reliability +- **Extensible**: Easily add custom validators and extend functionality + +## Key Features + +### File Validation +- Validate file size with flexible size format support (e.g., "10MB", "1KB") +- Check MIME types with wildcard pattern support +- Validate filename patterns with regex +- Efficient streaming for large files + +### Image Validation +- Inherit all file validation capabilities +- Verify image format and integrity using Pillow +- Validate image dimensions (width and height) +- Check aspect ratios +- Support for multiple image formats (JPEG, PNG, GIF, WebP, BMP, TIFF) + +### CSV Validation +- All file validation features +- Schema validation (required/disallowed columns) +- Encoding validation +- Row count constraints +- Delimiter customization +- Header verification +- Efficient header-only checks + +### Request Parameter Validation +- **Query Validators**: Validate query strings with allowed values and constraints +- **Header Validators**: Validate HTTP headers +- **Cookie Validators**: Validate cookie values +- **Path Validators**: Validate path segments with custom rules + +## Quick Start + +### Installation + +```bash +pip install fastapi-assets +``` + +For extended functionality: + +```bash +pip install fastapi-assets[image,pandas] +``` + +### Basic File Upload Validation + +```python +from fastapi import FastAPI, UploadFile, Depends +from fastapi_assets.validators import FileValidator + +app = FastAPI() + +# Create a file validator +file_validator = FileValidator( + max_size="10MB", + min_size="1KB", + content_types=["image/jpeg", "image/png"] +) + +@app.post("/upload/") +async def upload_file(file: UploadFile = Depends(file_validator)): + return { + "filename": file.filename, + "size": file.size, + "content_type": file.content_type + } +``` + +## Documentation + +- [Getting Started](./getting-started.md) - Installation, setup, and basic usage patterns +- [API Reference](./api-reference.md) - Complete API documentation for all validators +- [Examples](./examples.md) - Real-world usage examples and best practices +- [Contributing](./CONTRIBUTING.md) - Guidelines for contributing to the project + +## Project Structure + +``` +fastapi-assets/ +├── fastapi_assets/ +│ ├── core/ # Core validation framework +│ ├── validators/ # File, image, and CSV validators +│ └── request_validators/# Query, header, cookie, path validators +├── tests/ # Comprehensive test suite +├── docs/ # Documentation +└── pyproject.toml # Project configuration +``` + +## Requirements + +- Python 3.12+ +- FastAPI 0.119.1+ + +## Optional Dependencies + +- **image**: Pillow 12.0.0+ for image validation +- **pandas**: Pandas 2.3.3+ for CSV validation + + +## Support + +For issues, questions, or contributions, please visit the [GitHub repository](https://github.com/OpenVerge/fastapi-assets). diff --git a/mkdocs.yml b/mkdocs.yml index 58cac4a..658f048 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -22,6 +22,9 @@ nav: - Getting Started: getting-started.md - API Reference: api-reference.md - Examples: examples.md + - Contributing: CONTRIBUTING.md + - Code of Conduct: CODE_OF_CONDUCT.md + - Custom Validators: custom_validators.md # Extensions and plugins markdown_extensions: From cff8fff292b37150bfdacb6141f669c46fc0ffb2 Mon Sep 17 00:00:00 2001 From: Mohammed Saajid S <141727149+Mohammed-Saajid@users.noreply.github.com> Date: Tue, 11 Nov 2025 10:31:22 +0530 Subject: [PATCH 2/3] Added Readme --- README.md | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 156 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 355b6b6..b69b2de 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,158 @@ # FastAPI Assets -FastAPI Assets is a powerful validation and assertion toolkit designed specifically for FastAPI applications. It simplifies the process of validating file uploads and request metadata, ensuring that your application handles user input securely and efficiently. +
+ +[![Python Version](https://img.shields.io/badge/Python-3.12%2B-blue.svg)](https://www.python.org/downloads/) +[![FastAPI](https://img.shields.io/badge/FastAPI-0.119.1%2B-green.svg)](https://fastapi.tiangolo.com) +[![License](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE.txt) +[![Code Style](https://img.shields.io/badge/Code%20Style-Ruff-black.svg)](https://github.com/astral-sh/ruff) + +A powerful validation and assertion toolkit for FastAPI applications. + +[Documentation](https://openverge.github.io/fastapi-assets/) · [Examples](./docs/examples.md) · [Contributing](./docs/CONTRIBUTING.md) + +
+ +--- + +## Overview + +**FastAPI Assets** is a comprehensive validation toolkit designed specifically for FastAPI applications. It simplifies the process of validating file uploads, request metadata, and HTTP parameters, ensuring that your application handles user input securely and efficiently. + +FastAPI Assets provides: + +- **File Validators** - Validate file uploads with size, MIME type, and filename checks +- **Image Validators** - Specialized validation for image files (format, dimensions, aspect ratio) +- **CSV Validators** - Validate CSV structure, encoding, columns, and row counts +- **Request Validators** - Validate headers, query parameters, path parameters, and cookies +- **Custom Validators** - Create custom validation logic with sync or async support +- **Granular Error Messages** - Fine-grained error control for precise user feedback +- **Type-Safe** - Full type hints and runtime type validation +- **Light Weight** - Minimal dependencies; optional extras for specific features + +## Quick Start + +### Installation + +```bash +# Basic installation +pip install fastapi-assets + +# With image support (includes Pillow) +pip install fastapi-assets[image] + +# With CSV support (includes pandas) +pip install fastapi-assets[pandas] + +# With all optional features +pip install fastapi-assets[image,pandas] +``` + +## Features + +### File Validators + +- **FileValidator** - General-purpose file validation + - File size validation (min/max with human-readable formats) + - MIME type validation with wildcard support + - Filename pattern validation + - Custom validator functions + +- **ImageValidator** - Specialized image validation + - Image format validation (JPEG, PNG, WebP, GIF, BMP, TIFF) + - Image dimension validation + - Aspect ratio validation + - Inherits all FileValidator features + +- **CSVValidator** - CSV file validation (requires pandas) + - CSV encoding validation + - Required/disallowed columns + - Row count validation + - Header-only validation option + +### Request Validators + +- **HeaderValidator** - HTTP header validation + - Pattern matching with regex + - Predefined formats (UUID4, email, Bearer token, etc.) + - Allowed values restriction + - Custom validators + +- **QueryValidator** - Query parameter validation + - Type conversion and validation + - Allowed values restriction + - Numeric range validation + - Pattern matching + +- **PathValidator** - Path parameter validation + - Type conversion + - Pattern matching + - Range validation + +- **CookieValidator** - Cookie value validation + - Pattern matching + - Required value validation + - Custom validators + +### Advanced Features + +- **Granular Error Messages** - Customize error messages for each validation type +- **Custom Validators** - Add custom validation logic (sync or async) +- **HTTP Status Codes** - Customize HTTP response codes per validator +- **Type Safety** - Full type hints for IDE support and type checking + +## Documentation + +Comprehensive documentation is available at [https://openverge.github.io/fastapi-assets/](https://openverge.github.io/fastapi-assets/) + +- [Getting Started](./docs/getting-started.md) - Installation and basic usage +- [API Reference](./docs/api-reference.md) - Complete API documentation +- [Examples](./docs/examples.md) - Practical usage examples +- [Custom Validators](./docs/custom_validators.md) - Creating custom validation logic + + +## Project Structure + +``` +fastapi-assets/ +├── fastapi_assets/ +│ ├── core/ # Core validation framework +│ │ ├── base_validator.py # Abstract base validator +│ │ └── exceptions.py # Custom exceptions +│ ├── validators/ # File validators +│ │ ├── file_validator.py +│ │ ├── image_validator.py +│ │ ├── csv_validator.py +│ │ └── utils.py +│ └── request_validators/ # HTTP request validators +│ ├── header_validator.py +│ ├── query_validator.py +│ ├── path_validator.py +│ └── cookie_validator.py +├── tests/ # Comprehensive test suite +├── docs/ # Documentation +└── pyproject.toml # Project configuration +``` + + +## Contributing + +We welcome contributions! Please see [CONTRIBUTING.md](./docs/CONTRIBUTING.md) for guidelines. + +## Code of Conduct + +Please read [CODE_OF_CONDUCT.md](./docs/CODE_OF_CONDUCT.md) before contributing. + +## License + +This project is licensed under the MIT License - see the [LICENSE.txt](LICENSE.txt) file for details. + + + +--- + +**FastAPI Assets** - Making FastAPI validation simple, secure, and intuitive. + +*Version 0.1.0* | *Last Updated: November 2025* + + From 1c3ef00086f386cc79453d9959629071a60c2274 Mon Sep 17 00:00:00 2001 From: Mohammed Saajid S <141727149+Mohammed-Saajid@users.noreply.github.com> Date: Tue, 11 Nov 2025 10:31:47 +0530 Subject: [PATCH 3/3] Minor Docstring Change --- fastapi_assets/validators/csv_validator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastapi_assets/validators/csv_validator.py b/fastapi_assets/validators/csv_validator.py index c8860ee..2e9adfc 100644 --- a/fastapi_assets/validators/csv_validator.py +++ b/fastapi_assets/validators/csv_validator.py @@ -25,7 +25,7 @@ class CSVValidator(FileValidator): CSV-specific checks for encoding, delimiter, columns, and row counts. This validator requires the 'pandas' library. Install it with: - `pip install fastapi-asserts[csv]` + `pip install fastapi-asserts[pandas]` .. code-block:: python from fastapi import FastAPI, UploadFile, Depends @@ -95,7 +95,7 @@ def __init__( if not pd: raise ImportError( "The 'pandas' library is required for CSVValidator. " - "Install it with 'pip install fastapi-assets[csv]'" + "Install it with 'pip install fastapi-assets[pandas]'" ) kwargs["content_types"] = kwargs.get("content_types", self._DEFAULT_CSV_CONTENT_TYPES)