Metadata-Version: 2.1
Name: marshmallow_api_utils
Version: 0.2.0
Summary: Marshmallow API Utilities
Project-URL: Homepage, https://github.com/mvanderlee/marshmallow_api_utils
Author-email: Michiel Vanderlee <jmt.vanderlee@gmail.com>
License-Expression: MIT
License-File: LICENSE.md
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Web Environment
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Internet
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Classifier: Topic :: Software Development
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: apispec[marshmallow]<7,>=6
Requires-Dist: dpath<3,>=2.1.0
Requires-Dist: marshmallow-dataclass<9,>=8.5.1
Requires-Dist: marshmallow<4,>=3.18.0
Requires-Dist: python-multipart<0.0.7,>=0.0.5
Requires-Dist: pyyaml>=5.4.1
Requires-Dist: sqlalchemy<3,>=2.0.0
Provides-Extra: dev
Requires-Dist: hatch; extra == 'dev'
Requires-Dist: isort<6.0.0,>=5.0.6; extra == 'dev'
Requires-Dist: pre-commit<4,>=3.2.0; extra == 'dev'
Requires-Dist: ruff==0.0.260; extra == 'dev'
Provides-Extra: flask
Requires-Dist: flask-log-request-id<1.0.0,>=0.10.0; extra == 'flask'
Requires-Dist: flask-smorest<1,>=0.40.0; extra == 'flask'
Requires-Dist: flask<3,>=2; extra == 'flask'
Provides-Extra: test
Requires-Dist: coverage[toml]<8.0,>=6.5.0; extra == 'test'
Requires-Dist: isort<6.0.0,>=5.0.6; extra == 'test'
Requires-Dist: mypy<2,>=1.1.1; extra == 'test'
Requires-Dist: pytest<8.0.0,>=7.1.3; extra == 'test'
Requires-Dist: ruff==0.0.260; extra == 'test'
Description-Content-Type: text/markdown

# Marshmallow API Utilities

A collection of tools for REST API development with Marshmallow.

| | |
| --- | --- |
| Package | [![PyPI - Version](https://img.shields.io/pypi/v/marshmallow_api_utils.svg?logo=pypi&label=PyPI&logoColor=gold)](https://pypi.org/project/marshmallow_api_utils/) [![PyPI - Downloads](https://img.shields.io/pypi/dm/marshmallow_api_utils.svg?color=blue&label=Downloads&logo=pypi&logoColor=gold)](https://pypi.org/project/marshmallow_api_utils/) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/marshmallow_api_utils.svg?logo=python&label=Python&logoColor=gold)](https://pypi.org/project/marshmallow_api_utils/) |
| Meta | [![linting - Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v0.json)](https://github.com/charliermarsh/ruff) [![License - MIT](https://img.shields.io/badge/license-MIT-9400d3.svg)](https://spdx.org/licenses/) |

## Basic usage

```python
from datetime import date
from flask import Flask
from flask_smorest import Api
from marshmallow_dataclass import dataclass as ma_dataclass
from sqlalchemy import Column, Select, select
from sqlalchemy.orm import DeclarativeBase

from marshmallow_api_utils.fields import dump_only_field, optional_field, required_field
from marshmallow_api_utils.ma_dataclass import MaDataclass
from marshmallow_api_utils.models.sortable import Sortable


class Base(DeclarativeBase):
    pass


class Pet(Base):
    __tablename__ = 'pets'

    id = Column(st.Integer, primary_key=True)
    name = Column(st.String)
    birthdate = Column(st.Date)


@ma_dataclass
class PetDTO(MaDataclass):
    id: int = dump_only_field()
    name: str = required_field(help='This will show up in the OpenAPI docs.')
    birthdate: dt.date = optional_field()
    age: int = dump_only_field(sortable=False)

    @ma.pre_dump
    def add_age(self, data, many, **kwargs):
      data['age'] = int((date.today() - data.birthdate) / 365.25)
      return data


@ma_dataclass
class PetQueryParams(Sortable, MaDataclass):
    class Meta:
        dto_schema = PetDTO.Schema()


flask = Flask(__name__)
app.config["API_TITLE"] = "My API"
app.config["API_VERSION"] = "v1"
app.config["OPENAPI_VERSION"] = "3.0.2"
api = Api(app)

blp = Blueprint("pets", "pets", url_prefix="/pets", description="Operations on pets")

@blp.route("/")
class Pets(MethodView):

    @blp.arguments(PetQueryParams.Schema, location="query")
    @blp.response(200, Pet.Schema(many=True))
    def get(self, query_params: PetQueryParams):
        """List pets"""
        stmt = select(Pet)
        stmt = query_params.apply_sort(stmt)

        return stmt.all()
```

## License

Marshmallow API Utilities is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
