{"id":28737317,"url":"https://github.com/mkrd/statica","last_synced_at":"2025-06-16T02:09:53.643Z","repository":{"id":297939218,"uuid":"998365133","full_name":"mkrd/statica","owner":"mkrd","description":"A minimalistic data validation library","archived":false,"fork":false,"pushed_at":"2025-06-15T17:15:48.000Z","size":79,"stargazers_count":1,"open_issues_count":6,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-15T18:36:54.086Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mkrd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-08T13:08:20.000Z","updated_at":"2025-06-15T17:16:06.000Z","dependencies_parsed_at":"2025-06-08T13:48:25.768Z","dependency_job_id":null,"html_url":"https://github.com/mkrd/statica","commit_stats":null,"previous_names":["mkrd/statica"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mkrd/statica","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkrd%2Fstatica","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkrd%2Fstatica/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkrd%2Fstatica/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkrd%2Fstatica/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mkrd","download_url":"https://codeload.github.com/mkrd/statica/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkrd%2Fstatica/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260033523,"owners_count":22948906,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-16T02:09:53.064Z","updated_at":"2025-06-16T02:09:53.622Z","avatar_url":"https://github.com/mkrd.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"Statica\n========================================================================================\n\n![Tests](https://github.com/mkrd/statica/actions/workflows/test.yml/badge.svg)\n![Coverage](https://github.com/mkrd/statica/blob/main/assets/coverage.svg?raw=true)\n\n\nStatica is a Python library for defining and validating structured data with type annotations and constraints. It provides an easy-to-use framework for creating type-safe models with comprehensive validation for both types and constraints.\n\n\nWhy Statica?\n----------------------------------------------------------------------------------------\n\nStatica was created to address the need for a lightweight, flexible, and dependency-free alternative to libraries like Pydantic.\nWhile pydantic is a powerful tool for data validation and parsing, Statica offers some distinct advantages in specific situations:\n\n1. **Lightweight**: Statica has zero dependencies, making it ideal for projects where minimizing external dependencies is a priority.\n2. **Performance**: For use cases where performance is critical. Pydantic needs `3x` more memory than Statica for the same models.\n3. **Ease of Use**: With its simple, Pythonic design, Statica is intuitive for developers already familiar with Python's `dataclasses` and type hinting. It avoids much of the magic and complexity of Pydantic.\n4. **Customizable**: Statica allows fine-grained control over type and constraint validation through customizable fields and error classes.\n\n\nFeatures\n----------------------------------------------------------------------------------------\n\n- **Type Validation**: Automatically validates types for attributes based on type hints.\n- **Constraint Validation**: Define constraints like minimum/maximum length, value ranges, and more.\n- **Customizable Error Handling**: Use custom exception classes for type and constraint errors.\n- **Flexible Field Descriptors**: Add constraints, casting, and other behaviors to your fields.\n- **Optional Fields**: Support for optional fields with default values.\n- **Automatic Initialization**: Automatically generate constructors (`__init__`) for your models.\n- **String Manipulation**: Strip whitespace from string fields if needed.\n- **Casting**: Automatically cast values to the desired type.\n- **Field Aliasing**: Support for field aliases for parsing and serialization.\n\n\nInstallation\n----------------------------------------------------------------------------------------\n\nYou can install Statica via pip:\n\n```bash\npip install statica\n```\n\n\nGetting Started\n----------------------------------------------------------------------------------------\n\n### Basic Usage\n\nDefine a model with type annotations and constraints:\n\n```python\nfrom statica.core import Statica, Field\n\nclass Payload(Statica):\n    name: str = Field(min_length=3, max_length=50, strip_whitespace=True)\n    description: str | None = Field(max_length=200)\n    num: int | float\n    float_num: float | None\n```\n\nInstantiate the model using a dictionary:\n\n```python\ndata = {\n    \"name\": \"Test Payload\",\n    \"description\": \"A short description.\",\n    \"num\": 42,\n    \"float_num\": 3.14,\n}\n\npayload = Payload.from_map(data)\nprint(payload.name)  # Output: \"Test Payload\"\n```\n\nOr instantiate directly:\n\n```python\npayload = Payload(\n    name=\"Test\",\n    description=\"This is a test description.\",\n    num=42,\n    float_num=3.14,\n)\n```\n\n### Validation\n\nStatica automatically validates attributes based on type annotations and constraints:\n\n```python\nfrom statica.core import ConstraintValidationError, TypeValidationError\n\ntry:\n    payload = Payload(name=\"Te\", description=\"Valid\", num=42)\nexcept ConstraintValidationError as e:\n    print(e)  # Output: \"name: length must be at least 3\"\n\ntry:\n    payload = Payload(name=\"Test\", description=\"Valid\", num=\"Invalid\")\nexcept TypeValidationError as e:\n    print(e)  # Output: \"num: expected type 'int | float', got 'str'\"\n```\n\n### Optional Fields\n\nFields annotated with `| None` are optional and default to `None`:\n\n```python\nclass OptionalPayload(Statica):\n    name: str | None\n\npayload = OptionalPayload()\nprint(payload.name)  # Output: None\n```\n\n### Field Constraints\n\nYou can specify constraints on fields:\n\n- **String Constraints**: `min_length`, `max_length`, `strip_whitespace`\n- **Numeric Constraints**: `min_value`, `max_value`\n- **Casting**: `cast_to`\n\n```python\nclass StringTest(Statica):\n    name: str = Field(min_length=3, max_length=5, strip_whitespace=True)\n\nclass IntTest(Statica):\n    num: int = Field(min_value=1, max_value=10, cast_to=int)\n```\n\n### Custom Error Classes\n\nYou can define custom error classes for type and constraint validation:\n\n```python\nclass CustomError(Exception):\n    pass\n\nclass CustomPayload(Statica):\n    constraint_error_class = CustomError\n\n    num: int = Field(min_value=1, max_value=10)\n\ntry:\n    payload = CustomPayload(num=0)\nexcept CustomError as e:\n    print(e)  # Output: \"num: must be at least 1\"\n```\n\nOr, define a BaseClass which configures the error classes globally:\n\n```python\nfrom statica.core import Statica, ConstraintValidationError, TypeValidationError\n\nclass BaseClass(Statica):\n    constraint_error_class = ConstraintValidationError\n    type_error_class = TypeValidationError\n\nclass CustomPayload(BaseClass):\n    num: int = Field(min_value=1, max_value=10)\n\ntry:\n    payload = CustomPayload(num=0)\nexcept ConstraintValidationError as e:\n    print(e)  # Output: \"num: must be at least 1\"\n```\n\n\nAliasing\n----------------------------------------------------------------------------------------\n\nStatica supports field aliasing, allowing you to map different field names for parsing and serialization.\nThis is particularly useful when working with external APIs that use different naming conventions.\n\nUse the `alias` parameter to define an alternative name for both parsing and serialization:\n\n```python\nclass User(Statica):\n    full_name: str = Field(alias=\"fullName\")\n    age: int = Field(alias=\"userAge\")\n\n# Parse data with aliases\ndata = {\"fullName\": \"John Doe\", \"userAge\": 30}\nuser = User.from_map(data)\nprint(user.full_name)  # Output: \"John Doe\"\nprint(user.age)        # Output: 30\n\n# Serialize back with aliases (uses the alias for serialization by default)\nresult = user.to_dict()\nprint(result)  # Output: {\"fullName\": \"John Doe\", \"userAge\": 30}\n\n# Serialize without aliases\nresult_no_alias = user.to_dict(with_aliases=False)\nprint(result_no_alias)  # Output: {\"full_name\": \"John Doe\", \"age\": 30}\n\n```\n\nAdvanced Usage\n----------------------------------------------------------------------------------------\n\n### Custom Initialization\n\nStatica automatically generates an `__init__` method based on type annotations, ensuring that all required fields are provided during initialization.\n\n### Casting\n\nYou can automatically cast input values to the desired type:\n\n```python\nclass CastingExample(Statica):\n    num: int = Field(cast_to=int)\n\ninstance = CastingExample(num=\"42\")\nprint(instance.num)  # Output: 42\n```\n\n\nDesign Decisions\n----------------------------------------------------------------------------------------\n\n- [Inheritance over Decorators](docs/decision-inheritance-over-decorators.md)\n\n\nContributing\n----------------------------------------------------------------------------------------\n\nWe welcome contributions to Statica! To contribute:\n\n1. Fork the repository.\n2. Create a new branch for your feature or bug fix.\n3. Write tests for your changes.\n4. Submit a pull request.\n\n\nLicense\n----------------------------------------------------------------------------------------\n\nStatica is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.\n\n\nAcknowledgments\n----------------------------------------------------------------------------------------\n\nStatica was built to simplify data validation and provide a robust and simple framework for type-safe models in Python, inspired by `pydantic` and `dataclasses`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkrd%2Fstatica","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmkrd%2Fstatica","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkrd%2Fstatica/lists"}