Skip to content

Commit

Permalink
Renamed add_dependencies -> depends
Browse files Browse the repository at this point in the history
  • Loading branch information
Minibrams committed Oct 3, 2024
1 parent bcdc3dc commit a9abd72
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 53 deletions.
70 changes: 35 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pip install fastapi-decorators
```

# TL;DR
The library supplies the `add_dependencies()` decorator function which effectively allows you to add argument dependencies to your FastAPI endpoints.
The library supplies the `depends()` decorator function which effectively allows you to add argument dependencies to your FastAPI endpoints.

For example, the following three endpoints have the same signature:
```python
Expand All @@ -23,15 +23,15 @@ def read_item(item_id: int, _ = Depends(get_current_user)):

# Using add_dependency directly
@app.get("/items/{item_id}")
@add_dependencies(Depends(get_current_user))
@depends(Depends(get_current_user))
def read_item(item_id: int):
...

# Using a custom decorator
def authorize():
def dependency(user = Depends(get_current_user)):
return user
return add_dependencies(Depends(dependency))
return depends(Depends(dependency))

@app.get("/items/{item_id}")
@authorize()
Expand All @@ -41,27 +41,45 @@ def read_item(item_id: int):

# Usage examples

- [Using `depends()` directly](#using-depends-directly)
- [Logging decorator](#logging-decorator)
- [Authorization decorator](#authorization-decorator)
- [Custom Response Header decorator](#custom-response-header-decorator)
- [Rate Limiting decorator](#rate-limiting-decorator)
- [Caching decorator](#caching-decorator)
- [Error Handling decorator](#error-handling-decorator)
- [Combining Multiple decorators](#combining-multiple-decorators)
- [Using `add_dependencies()` directly](#using-add_dependencies-directly)
- [Dependency injection with parameters](#dependency-injection-with-parameters)

## Using `depends()` directly
If you prefer, you can use depends directly without creating a custom decorator:

```python
from fastapi_decorators import depends
from fastapi import Depends, Header

async def verify_api_key(x_api_key: str = Header(...)):
if x_api_key != "expected-api-key":
raise HTTPException(status_code=403, detail="Forbidden")

@app.get("/secure-data")
@depends(Depends(verify_api_key))
def get_secure_data():
...

```

## Logging decorator
Add a decorator to log incoming requests:

```python
from fastapi_decorators import add_dependencies
from fastapi_decorators import depends
from fastapi import Request, Depends

def log_request():
def dependency(request: Request):
print(f"Received request: {request.method} {request.url}")
return add_dependencies(Depends(dependency))
return depends(Depends(dependency))

@app.get("/items/{item_id}")
@log_request()
Expand All @@ -76,7 +94,7 @@ Create a simple decorator that rejects unauthorized requests:
> because of the added OAuth2 dependency.
```python
from fastapi_decorators import add_dependencies
from fastapi_decorators import depends
from fastapi import Depends, HTTPException, Header
from fastapi.security import OAuth2PasswordBearer
from sqlalchemy.orm import Session
Expand All @@ -91,7 +109,7 @@ def authorize(*required_scopes: str):

# Check scopes and permissions
pass
return add_dependencies(Depends(dependency))
return depends(Depends(dependency))


@app.put("/users/{user_id}")
Expand All @@ -105,13 +123,13 @@ def update_user(*, user_id: int, user_update: UserUpdate):
Create a decorator to add custom headers to responses:

```python
from fastapi_decorators import add_dependencies
from fastapi_decorators import depends
from fastapi import Response, Depends

def add_custom_header(name: str, value: str):
def dependency(response: Response):
response.headers[name] = value
return add_dependencies(Depends(dependency))
return depends(Depends(dependency))

@app.get("/data")
@add_custom_header("X-Custom-Header", "MyValue")
Expand All @@ -124,7 +142,7 @@ def get_data():
Add rate limiting to your endpoints:

```python
from fastapi_decorators import add_dependencies
from fastapi_decorators import depends
from fastapi import Depends, HTTPException, Request
from time import time

Expand All @@ -143,7 +161,7 @@ def rate_limit(max_calls: int, period: int):
raise HTTPException(status_code=429, detail="Too Many Requests")
calls += 1
rate_limit_store[ip_address] = (calls, last_reset)
return add_dependencies(Depends(dependency))
return depends(Depends(dependency))

def get_ip_address(request: Request):
return request.client.host
Expand All @@ -166,7 +184,7 @@ def cache_response(max_age: int = 5):
def decorator(func):

# Wrap the endpoint after adding the get_cache dependency
@add_dependencies(cache=Depends(get_cache))
@depends(cache=Depends(get_cache))
@wraps(func)
def wrapper(*args, cache: dict, **kwargs):
key = func.__name__
Expand Down Expand Up @@ -197,7 +215,7 @@ def get_cached_data():
Create a decorator to handle exceptions and return custom responses:

```python
from fastapi_decorators import add_dependencies
from fastapi_decorators import depends
from fastapi import Depends, Response

def get_crash_log_storage() -> list:
Expand All @@ -207,7 +225,7 @@ def handle_errors():
def decorator(func):

# Wrap the endpoint after adding the crash_logs dependency
@add_dependencies(crash_logs = Depends(get_crash_log_storage))
@depends(crash_logs = Depends(get_crash_log_storage))
@wraps(func)
def wrapper(*args, crash_logs: list, **kwargs):
try:
Expand Down Expand Up @@ -240,29 +258,11 @@ def submit_data(data: DataModel):

```

## Using `add_dependencies()` directly
If you prefer, you can use add_dependencies directly without creating a custom decorator:

```python
from fastapi_decorators import add_dependencies
from fastapi import Depends, Header

async def verify_api_key(x_api_key: str = Header(...)):
if x_api_key != "expected-api-key":
raise HTTPException(status_code=403, detail="Forbidden")

@app.get("/secure-data")
@add_dependencies(Depends(verify_api_key))
def get_secure_data():
...

```

## Dependency injection with parameters
You can pass parameters to your dependencies through closures:

```python
from fastapi_decorators import add_dependencies
from fastapi_decorators import depends
from fastapi import Depends, HTTPException

def verify_role(required_role: str):
Expand All @@ -272,7 +272,7 @@ def verify_role(required_role: str):
return dependency

@app.get("/admin-area")
@add_dependencies(Depends(verify_role("admin")))
@depends(Depends(verify_role("admin")))
def admin_area():
...

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name="fastapi-decorators",
version="1.0.3",
version="1.0.4",
author="Anders Brams",
author_email="[email protected]",
description="Create decorators that leverage FastAPI's `Depends()` and built-in dependencies, enabling you to inject dependencies directly into your decorators.",
Expand Down
4 changes: 2 additions & 2 deletions src/fastapi_decorators/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from .decorators import add_dependencies
from .decorators import depends

__all__ = ["add_dependencies"]
__all__ = ["depends"]
6 changes: 3 additions & 3 deletions src/fastapi_decorators/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

F = TypeVar('F', bound=Callable[..., Any])

def add_dependencies(*args: Any, **kwargs: Any) -> Callable[[F], F]:
def depends(*args: Any, **kwargs: Any) -> Callable[[F], F]:
"""
Decorator to add dependencies to a function without exposing them as arguments.
Expand All @@ -18,7 +18,7 @@ def add_dependencies(*args: Any, **kwargs: Any) -> Callable[[F], F]:
```python
@app.put("/users/{user_id}")
@add_dependencies(Depends(get_admin_roles))
@depends(Depends(get_admin_roles))
def update_user(*, user_id: int, user_update: UserUpdate):
...
```
Expand All @@ -33,7 +33,7 @@ async def dependency(
):
# Authorization logic here
...
return add_dependencies(Depends(dependency))(func)
return depends(Depends(dependency))(func)
```
**Using the Custom Decorator:**
Expand Down
24 changes: 12 additions & 12 deletions tests/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from fastapi.responses import JSONResponse
from pydantic import BaseModel

from fastapi_decorators import add_dependencies
from fastapi_decorators import depends

logging.basicConfig(level=logging.INFO)

Expand Down Expand Up @@ -75,19 +75,19 @@ async def dependency(
if not token or token != db["access_token"]:
raise HTTPException(status_code=401, detail="Unauthorized")

return add_dependencies(Depends(dependency))
return depends(Depends(dependency))

def custom_header():
def dependency(response: Response):
response.headers["X-Custom-Header"] = "CustomValue"
return response
return add_dependencies(Depends(dependency))
return depends(Depends(dependency))

def log():
async def dependency(request: Request):
logging.info(f"Request: {request.method} {request.url}")
return request
return add_dependencies(Depends(dependency))
return depends(Depends(dependency))

def rate_limit(max_calls: int, period: int):
async def dependency(
Expand All @@ -103,13 +103,13 @@ async def dependency(
raise HTTPException(status_code=429, detail="Too Many Requests")
calls_info['calls'] += 1
rate_limit_store[request_id] = calls_info
return add_dependencies(Depends(dependency))
return depends(Depends(dependency))

def cache_response(max_age: int = 5):
def decorator(func):

# Wrap the endpoint after adding the get_cache dependency
@add_dependencies(cache=Depends(get_cache))
@depends(cache=Depends(get_cache))
@wraps(func)
def wrapper(*args, cache: dict, **kwargs):
key = func.__name__
Expand All @@ -132,7 +132,7 @@ def wrapper(*args, cache: dict, **kwargs):

def handle_errors():
def decorator(func):
@add_dependencies(crash_logs = Depends(get_crash_log_storage))
@depends(crash_logs = Depends(get_crash_log_storage))
@wraps(func)
def wrapper(*args, crash_logs: list, **kwargs):
try:
Expand All @@ -146,16 +146,16 @@ def wrapper(*args, crash_logs: list, **kwargs):

app = FastAPI()
@app.get("/items/")
@add_dependencies(Depends(get_db), Depends(log_request))
@depends(Depends(get_db), Depends(log_request))
def read_items(db: dict = Depends(get_db)):
"""
Endpoint to read items, using direct @add_dependencies() notation.
Endpoint to read items, using direct @depends() notation.
"""
items = db["items"]
return {"items": items}

@app.post("/items/")
@add_dependencies(Depends(add_custom_header))
@depends(Depends(add_custom_header))
def create_item(item: dict, response: Response, db: dict = Depends(get_db)):
"""
Endpoint to create an item, adding a custom header to the response.
Expand Down Expand Up @@ -184,10 +184,10 @@ def generate_report(response: Response):
return report

@app.put("/users/{user_id}")
@add_dependencies(Depends(get_db))
@depends(Depends(get_db))
def update_user(user_id: int, user_data: UserUpdate, db: dict = Depends(get_db)):
"""
Endpoint to update a user, using direct @add_dependencies() notation.
Endpoint to update a user, using direct @depends() notation.
"""
if user_id in db["users"]:
db["users"][user_id].update(user_data.dict())
Expand Down

0 comments on commit a9abd72

Please sign in to comment.