Metadata-Version: 2.1
Name: apischema
Version: 0.2.1
Summary: Another Python API schema handling and JSON (de)serialization through typing annotation; light, simple, powerful.
Home-page: https://github.com/wyfo/apischema
Author: Joseph Perez
Author-email: joperez@hotmail.fr
License: MIT
Description: # APISchema
        
        Another Python API schema handling and JSON (de)serialization through typing annotation; light, simple, powerful.
        
        
        ## Why another library
        Because i'm not satisfied with existing ones. I would like to:
        - stay closest as possible to the standard library (dataclasses, typing, etc.), and as a consequency to have no need of plugin for editor/linter/etc.
        - be able to tune the library and use my own types (or foreign libraries ones), instead of having to do a PR for handling of `bson.ObjectId`
        - have the least possible dynamic thing (like using string for attribute name)
        And I simply want to enjoy myself coding this stuff.
        
        
        ## Getting Started
        
        `pip install apischema` and follow examples (the only *documentation* for now)
        
        
        ## Examples
        Following example can be run 'as is' in Python 3.7 (all examples are valid tests of the library).
        [quickstart.py](examples/quickstart.py)
        ```python
        from dataclasses import dataclass, field
        from enum import Enum
        from typing import List, NewType
        from uuid import UUID, uuid4
        
        from pytest import raises
        
        from apischema import (ValidationError, build_input_schema, build_output_schema,
                               from_data, schema, to_data)
        
        Tag = NewType("Tag", str)
        schema(title="resource tag", max_len=64)(Tag)
        
        
        class ResourceType(Enum):
            RESOURCE_A = "A"
            RESOURCE_B = "B"
        
        
        @dataclass
        class Resource:
            id: UUID
            type: ResourceType
            tags: List[Tag] = field(default_factory=list,
                                    metadata=schema(max_items=5, unique=True))
        
        
        def test_resource():
            uuid = uuid4()
            data = {
                "id":   str(uuid),
                "type": "A",
                "tags": ["tag1"]
            }
            resource = from_data(Resource,data)
            assert resource == Resource(uuid, ResourceType.RESOURCE_A, [Tag("tag1")])
            assert to_data(resource) == data
            json_schema = build_input_schema(Resource)
            assert json_schema == build_output_schema(Resource)
            assert to_data(json_schema) == {
                "type":                 "object",
                "required":             ["id", "type"],
                "additionalProperties": False,
                "properties":           {
                    "id":   {
                        "type":   "string",
                        "format": "uuid",
                    },
                    "type": {
                        "type": "string",
                        "enum": ["A", "B"],
                    },
                    "tags": {
                        "type":        "array",
                        "maxItems":    5,
                        "uniqueItems": True,
                        "items":       {
                            "type":      "string",
                            "title":     "resource tag",
                            "maxLength": 64,
                        },
                    },
                }
            }
        
        
        def test_resource_error():
            with raises(ValidationError) as err:
                from_data(Resource,{"id": "uuid", "type": None, "tags": ["a", "a"]})
            assert err.value == ValidationError(children={
                "id":   ValidationError([
                    "[ValueError]badly formed hexadecimal UUID string"
                ]),
                "type": ValidationError([
                    "None is not a valid ResourceType"
                ]),
                "tags": ValidationError([
                    "duplicates items in ['a', 'a'] (uniqueItems)"
                ])
            })
        ```
        See other [examples](examples); a suggested order:
        - [properties.py](examples/properties.py)
        - [conversion.py](examples/conversion.py) 
        - [validator.py](examples/validator.py) 
        - [coercion.py](examples/coercion.py) 
        - [generic.py](examples/generic.py) 
        - [properties2.py](examples/properties2.py)
        - [conversion2.py](examples/conversion2.py) 
        - [validator2.py](examples/validator2.py) 
        - [recursivity_and_pep563.py](examples/recursivity_and_pep563.py) 
        - [generic_conversion.py](examples/generic_conversion.py)
        - [raw_conversion.py](examples/raw_conversion.py)
        
        
        ## Benchmark
        Using [Pydantic benchmark](https://pydantic-docs.helpmanual.io/benchmarks/), **using only CPython**, *apischema* is faster than others libraries, including *Pydantic*, present in the benchmark.
        
        Concerning Cython, *apischema* is blocked for now by this [Cython issue](https://github.com/cython/cython/issues/3537)
        
        
        ## Todo
        - documentation (obviously)
        - tests (coverage is not enough, and edge cases)
        - make it work in Python 3.6 (adds dataclass dependency in packaging, checks, etc.)
        
        About formatting and packaging, I'm honestly not interested by the mess of Python regarding theses 20th century issues so I did the minimum. But I know that if the library gains popularity, it will be a mandatory step to dig in it.
        
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Requires-Python: >=3.7
Description-Content-Type: text/markdown
