CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-apischema

JSON (de)serialization, GraphQL and JSON schema generation using Python typing.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

schema-generation.mddocs/

Schema Generation

Generate JSON Schema and GraphQL schemas directly from Python types. Supports all JSON Schema versions and provides comprehensive GraphQL schema generation with built-in types, decorators, and Relay patterns.

Capabilities

JSON Schema Generation

Generate JSON schemas for deserialization and serialization with support for all major JSON Schema versions and comprehensive constraint handling.

def deserialization_schema(
    tp: AnyType,
    *,
    all_refs: bool = True,
    version: Optional[JsonSchemaVersion] = None,
    aliaser: Optional[Aliaser] = None,
    additional_properties: Optional[bool] = None,
    refs_set: Optional[RefsSet] = None,
    with_definitions_schema: bool = False,
) -> Dict[str, Any]:
    """
    Generate JSON schema for deserializing into the given type.
    
    Parameters:
    - tp: Type to generate schema for
    - all_refs: Include all referenced type definitions
    - version: JSON Schema version to use
    - aliaser: Function to transform field names
    - additional_properties: Allow additional properties in objects  
    - refs_set: Set to track references for circular handling
    - with_definitions_schema: Include full definitions schema
    
    Returns:
    JSON Schema as dictionary
    """

def serialization_schema(
    tp: AnyType,
    *,
    all_refs: bool = True, 
    version: Optional[JsonSchemaVersion] = None,
    aliaser: Optional[Aliaser] = None,
    additional_properties: Optional[bool] = None,
    refs_set: Optional[RefsSet] = None,
    with_definitions_schema: bool = False,
) -> Dict[str, Any]:
    """
    Generate JSON schema for serializing the given type.
    
    Parameters:
    - tp: Type to generate schema for
    - all_refs: Include all referenced type definitions
    - version: JSON Schema version to use
    - aliaser: Function to transform field names
    - additional_properties: Allow additional properties in objects
    - refs_set: Set to track references for circular handling
    - with_definitions_schema: Include full definitions schema
    
    Returns:
    JSON Schema as dictionary
    """

def definitions_schema(
    types: Iterable[AnyType],
    *,
    version: Optional[JsonSchemaVersion] = None,
    aliaser: Optional[Aliaser] = None,
    additional_properties: Optional[bool] = None,
) -> Dict[str, Any]:
    """
    Generate schema definitions for multiple types.
    
    Parameters:
    - types: Iterable of types to generate definitions for
    - version: JSON Schema version to use
    - aliaser: Function to transform field names
    - additional_properties: Allow additional properties in objects
    
    Returns:
    Schema definitions dictionary
    """

JSON Schema Versions

Support for all major JSON Schema versions with automatic schema formatting.

class JsonSchemaVersion(Enum):
    """Supported JSON Schema versions."""
    DRAFT_4 = "http://json-schema.org/draft-04/schema#"
    DRAFT_6 = "http://json-schema.org/draft-06/schema#"
    DRAFT_7 = "http://json-schema.org/draft-07/schema#"
    DRAFT_2019_09 = "https://json-schema.org/draft/2019-09/schema"
    DRAFT_2020_12 = "https://json-schema.org/draft/2020-12/schema"

GraphQL Schema Generation

Generate complete GraphQL schemas from Python types with support for queries, mutations, subscriptions, and advanced features.

def graphql_schema(
    query: Optional[Collection[Callable]] = None,
    mutation: Optional[Collection[Callable]] = None,
    subscription: Optional[Collection[Callable]] = None,
    *,
    types: Iterable[AnyType] = (),
    directives: Optional[Collection[GraphQLDirective]] = None,
    id_types: Optional[AbstractSet[AnyType]] = None,
    scalar_serializers: Optional[Mapping[AnyType, ScalarSerializer]] = None,
) -> GraphQLSchema:
    """
    Generate GraphQL schema from Python types and functions.
    
    Parameters:
    - query: Query operation functions or Query class
    - mutation: Mutation operation functions or Mutation class  
    - subscription: Subscription operation functions or Subscription class
    - types: Additional types to include in schema
    - directives: Custom GraphQL directives
    - id_types: Types to treat as GraphQL ID type
    - scalar_serializers: Custom scalar serialization functions
    
    Returns:
    GraphQLSchema object from graphql-core
    """

GraphQL Built-in Types and Classes

Built-in types and base classes for GraphQL schema definition.

class Query:
    """Base class for GraphQL query operations."""
    pass

class Mutation:
    """Base class for GraphQL mutation operations."""  
    pass

class Subscription:
    """Base class for GraphQL subscription operations."""
    pass

ID = NewType("ID", str)  # GraphQL ID type

GraphQL Decorators

Decorators for enhanced GraphQL functionality and type definitions.

def resolver(func: Func) -> Func:
    """
    Mark function as GraphQL resolver.
    
    Parameters:
    - func: Function to mark as resolver
    
    Returns:
    Decorated function
    """

def interface(cls: Cls) -> Cls:
    """
    Mark class as GraphQL interface.
    
    Parameters:
    - cls: Class to mark as interface
    
    Returns:
    Decorated class
    """

Usage Examples

JSON Schema Generation

from dataclasses import dataclass
from typing import List, Optional
from apischema.json_schema import deserialization_schema, JsonSchemaVersion

@dataclass
class User:
    id: int
    name: str
    email: Optional[str] = None
    tags: List[str] = field(default_factory=list)

# Generate deserialization schema
schema = deserialization_schema(User)
print(schema)
# {
#   "$schema": "https://json-schema.org/draft/2020-12/schema",
#   "type": "object", 
#   "properties": {
#     "id": {"type": "integer"},
#     "name": {"type": "string"},
#     "email": {"type": "string"},
#     "tags": {"type": "array", "items": {"type": "string"}, "default": []}
#   },
#   "required": ["id", "name"],
#   "additionalProperties": false
# }

# Use specific JSON Schema version
schema = deserialization_schema(User, version=JsonSchemaVersion.DRAFT_7)
print(schema["$schema"])  # "http://json-schema.org/draft-07/schema#"

Schema with Constraints

from apischema import schema

@dataclass
class Product:
    name: str = field(metadata=schema(min_len=1, max_len=100))
    price: float = field(metadata=schema(min=0, exc_max=10000))
    category: str = field(metadata=schema(pattern=r"^[a-z]+$"))

schema_def = deserialization_schema(Product)
print(schema_def["properties"]["name"])
# {"type": "string", "minLength": 1, "maxLength": 100}
print(schema_def["properties"]["price"]) 
# {"type": "number", "minimum": 0, "exclusiveMaximum": 10000}
print(schema_def["properties"]["category"])
# {"type": "string", "pattern": "^[a-z]+$"}

GraphQL Schema from Functions

from typing import List
from apischema.graphql import graphql_schema, ID
from graphql import print_schema

@dataclass
class User:
    id: ID
    name: str
    email: str

# Define GraphQL operations as functions
def get_user(id: ID) -> Optional[User]:
    """Get user by ID."""
    pass

def list_users(limit: int = 10) -> List[User]:
    """List users with pagination."""
    pass

def create_user(name: str, email: str) -> User:
    """Create a new user.""" 
    pass

def update_user(id: ID, name: Optional[str] = None) -> User:
    """Update user information."""
    pass

# Generate GraphQL schema
schema = graphql_schema(
    query=[get_user, list_users],
    mutation=[create_user, update_user],
    id_types={UUID}  # Treat UUID as GraphQL ID
)

# Print GraphQL SDL
print(print_schema(schema))
# type Query {
#   getUser(id: ID!): User
#   listUsers(limit: Int = 10): [User!]!
# }
#
# type Mutation {
#   createUser(name: String!, email: String!): User!
#   updateUser(id: ID!, name: String): User!
# }
# 
# type User {
#   id: ID!
#   name: String!
#   email: String!
# }

GraphQL Schema from Classes

class Query:
    def user(self, id: ID) -> Optional[User]:
        pass
    
    def users(self, limit: int = 10) -> List[User]:
        pass

class Mutation:
    def create_user(self, name: str, email: str) -> User:
        pass

# Generate schema from classes
schema = graphql_schema(query=Query, mutation=Mutation)

GraphQL with Interfaces

from apischema.graphql import interface

@interface
@dataclass  
class Node:
    id: ID

@dataclass
class User(Node):
    name: str
    email: str

@dataclass
class Post(Node):
    title: str
    content: str
    author_id: ID

def node(id: ID) -> Optional[Node]:
    """Get any node by ID."""
    pass

schema = graphql_schema(query=[node])
print(print_schema(schema))
# interface Node {
#   id: ID!
# }
# 
# type User implements Node {
#   id: ID!
#   name: String!
#   email: String!
# }

Multiple Type Definitions

@dataclass
class Address:
    street: str
    city: str
    country: str

@dataclass
class Company:
    name: str
    address: Address

@dataclass
class Employee:
    name: str
    company: Company
    
# Generate schema with all referenced types
schema = definitions_schema([Employee, Company, Address])
print(schema.keys())  # dict_keys(['$defs', '$schema'])
print(schema['$defs'].keys())  # dict_keys(['Employee', 'Company', 'Address'])

Type Aliases

RefsSet = Set[str]  # Set for tracking schema references
ScalarSerializer = Callable[[Any], Any]  # Function for custom scalar serialization

Install with Tessl CLI

npx tessl i tessl/pypi-apischema

docs

advanced.md

conversions.md

index.md

metadata.md

schema-generation.md

serialization.md

validation.md

tile.json