Skip to content

Commit

Permalink
Merge pull request #68 from silx-kit/fastapi-doc
Browse files Browse the repository at this point in the history
Update doc with FastAPI implementation
  • Loading branch information
loichuder authored Jun 8, 2022
2 parents 74ae4d7 + bff29af commit dfc418d
Show file tree
Hide file tree
Showing 13 changed files with 90 additions and 23 deletions.
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,22 @@ In addition, some problems arise constantly when designing HDF5 backends. To nam
pip install h5grove
```

You can use **h5grove** low-level utilities whatever the backend implementation you choose. We simply provide additional utilities for [Tornado](https://www.tornadoweb.org/en/stable/) and [Flask](https://flask.palletsprojects.com/en/) that can be installed with:
You can use **h5grove** low-level utilities whatever the backend implementation you choose. Additional utilities are provided for several Python web frameworks but require additional packages that can be installed the following way:

- [FastAPI](https://fastapi.tiangolo.com/)

```bash
pip install h5grove[fastapi]
```

- [Flask](https://flask.palletsprojects.com/en/)

```bash
pip install h5grove[flask]
```

- [Tornado](https://www.tornadoweb.org/en/stable/)

```bash
pip install h5grove[flask] # For Flask
pip install h5grove[tornado] # For Tornado
pip install h5grove[tornado]
```
11 changes: 10 additions & 1 deletion docs/example.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
# Example implementations

Example implementations using Flask and Tornado are given in the `example` folder. These are functional backends that make use of the utilities provided by the `h5grove` package.
Example implementations using FastAPI, Flask and Tornado are given in the `example` folder. These are functional backends that make use of the utilities provided by the `h5grove` package.

The endpoints API is described [here](api.md).

## FastAPI

```{eval-rst}
.. argparse::
:filename: example/fastapi_app.py
:func: parser_fn
:prog: fastapi_app.py
```

## Flask

```{eval-rst}
Expand Down
43 changes: 34 additions & 9 deletions docs/integration.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
# Integration in an existing application

h5grove endpoints (see [API here](api.md)) can be added to existing Flask/Tornado applications.
h5grove endpoints (see [API here](api.md)) can be added to existing FastAPI, Flask or Tornado applications.

## FastAPI

The module `fastapi_utils` contains utilities dedicated to FastAPI backends. It provides a [APIRouter](https://fastapi.tiangolo.com/tutorial/bigger-applications/#apirouter) that can be included in an existing FastAPI application:

```python
from fastapi import FastAPI
from h5grove.fastapi_utils import router, settings

app = FastAPI()

...

# Configure base directory from which the HDF5 files will be served
settings.base_dir = os.path.abspath(options.basedir)

app.include_router(router)
```

### fastapi_utils reference

```{eval-rst}
.. automodule:: h5grove.fastapi_utils
:members:
```

## Flask

The module `flaskutils` contains utilities dedicated to Flask backends. It provides a [Blueprint](https://flask.palletsprojects.com/en/2.0.x/blueprints/) that can be registered to an existing Flask application:
The module `flask_utils` contains utilities dedicated to Flask backends. It provides a [Blueprint](https://flask.palletsprojects.com/en/2.0.x/blueprints/) that can be registered to an existing Flask application:

```python
from flask import Flask
from h5grove.flaskutils import BLUEPRINT
from h5grove.flask_utils import BLUEPRINT

app = Flask(__name__)

Expand All @@ -20,20 +45,20 @@ app.config["H5_BASE_DIR"] = os.path.abspath(options.basedir)
app.register_blueprint(BLUEPRINT)
```

### flaskutils reference
### flask_utils reference

```{eval-rst}
.. automodule:: h5grove.flaskutils
.. automodule:: h5grove.flask_utils
:members:
```

## Tornado

The module `tornadoutils` contains utilities dedicated to Flask backends. It provides a `get_handlers` function to construct handlers that can be passed directly to a Tornado application:
The module `tornado_utils` contains utilities dedicated to Tornado backends. It provides a `get_handlers` function to construct handlers that can be passed directly to a Tornado application:

```python
import tornado.web
from h5grove.tornadoutils import get_handlers
from h5grove.tornado_utils import get_handlers

# The base directory from which the HDF5 files will be served is passed as argument of the function
h5grove_handlers = get_handlers(base_dir, allow_origin="*")
Expand All @@ -45,9 +70,9 @@ app = tornado.web.Application(h5grove_handlers)
app.add_handlers(h5grove_handlers)
```

### tornadoutils reference
### tornado_utils reference

```{eval-rst}
.. automodule:: h5grove.tornadoutils
.. automodule:: h5grove.tornado_utils
:members:
```
2 changes: 1 addition & 1 deletion example/fastapi_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# This needs to be done before any import of h5py, so before h5grove import
os.environ["HDF5_USE_FILE_LOCKING"] = "FALSE"

from h5grove.fastapi_router import router, settings # noqa
from h5grove.fastapi_utils import router, settings # noqa


def parser_fn():
Expand Down
2 changes: 1 addition & 1 deletion example/flask_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# This needs to be done before any import of h5py, so before h5grove import
os.environ["HDF5_USE_FILE_LOCKING"] = "FALSE"

from h5grove.flaskutils import BLUEPRINT as h5grove_blueprint # noqa
from h5grove.flask_utils import BLUEPRINT as h5grove_blueprint # noqa


def parser_fn():
Expand Down
2 changes: 1 addition & 1 deletion example/tornado_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# This needs to be done before any import of h5py, so before h5grove import
os.environ["HDF5_USE_FILE_LOCKING"] = "FALSE"

from h5grove.tornadoutils import get_handlers # noqa
from h5grove.tornado_utils import get_handlers # noqa


def parser_fn():
Expand Down
20 changes: 20 additions & 0 deletions h5grove/fastapi_router.py → h5grove/fastapi_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Helpers for usage with `FastAPI <https://fastapi.tiangolo.com/>`_"""
from fastapi import APIRouter, Depends, Response, Query, HTTPException
from pydantic import BaseSettings
import h5py
Expand All @@ -9,14 +10,29 @@
from .models import LinkResolution
from .utils import NotFoundError, parse_link_resolution_arg

__all__ = [
"router",
"settings",
"get_attr",
"get_data",
"get_meta",
"get_stats",
]

router = APIRouter()
"""
FastAPI router with h5grove endpoints.
The directory from which files are served can be defined in `settings`.
"""


class Settings(BaseSettings):
base_dir: Union[str, None] = None


settings = Settings()
""" Settings where base_dir can be defined """


def get_content(
Expand Down Expand Up @@ -44,6 +60,7 @@ async def get_attr(
path: str = "/",
attr_keys: Optional[List[str]] = Query(default=None),
):
"""`/attr/` endpoint handler"""
with h5py.File(file, "r") as h5file:
content = get_content(h5file, path)
assert isinstance(content, ResolvedEntityContent)
Expand All @@ -62,6 +79,7 @@ async def get_data(
flatten: bool = False,
selection=None,
):
"""`/data/` endpoint handler"""
with h5py.File(file, "r") as h5file:
content = get_content(h5file, path)
assert isinstance(content, DatasetContent)
Expand All @@ -78,6 +96,7 @@ async def get_meta(
path: str = "/",
resolve_links: str = "only_valid",
):
"""`/meta/` endpoint handler"""
resolve_links = parse_link_resolution_arg(
resolve_links,
fallback=LinkResolution.ONLY_VALID,
Expand All @@ -94,6 +113,7 @@ async def get_meta(
async def get_stats(
file: str = Depends(add_base_path), path: str = "/", selection=None
):
"""`/stats/` endpoint handler"""
with h5py.File(file, "r") as h5file:
content = get_content(h5file, path)
assert isinstance(content, DatasetContent)
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,4 @@ ignore_missing_imports = True
ignore_missing_imports = True

[mypy-uvicorn.*]
ignore_missing_imports = True
ignore_missing_imports = True
4 changes: 2 additions & 2 deletions test/test_fastapi.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Test fastapi router with fatapi testing"""
"""Test fastapi_utils with fastapi testing"""
import pathlib
from typing import Callable
from fastapi import FastAPI
Expand All @@ -8,7 +8,7 @@
from conftest import BaseServer
import base_test

from h5grove.fastapi_router import router, settings
from h5grove.fastapi_utils import router, settings

# Fixtures ###

Expand Down
4 changes: 2 additions & 2 deletions test/test_flask.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Test flaskutils blueprint with Flask testing"""
"""Test flask_utils blueprint with Flask testing"""
import pathlib
from typing import Callable
from flask import Flask
Expand All @@ -7,7 +7,7 @@
from conftest import BaseServer
import base_test

from h5grove.flaskutils import BLUEPRINT
from h5grove.flask_utils import BLUEPRINT

# Fixtures ###

Expand Down
4 changes: 2 additions & 2 deletions test/test_tornado.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Test tornadoutils using pytest-tornado"""
"""Test tornado_utils using pytest-tornado"""
import pathlib
from typing import Callable
import pytest
Expand All @@ -8,7 +8,7 @@
from conftest import BaseServer
import base_test

from h5grove.tornadoutils import get_handlers
from h5grove.tornado_utils import get_handlers

# Fixtures ###

Expand Down

0 comments on commit dfc418d

Please sign in to comment.