This repository has been archived by the owner on Feb 5, 2024. It is now read-only.
forked from tjb9dc/fern-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from sayari-analytics/update-fork
Update fork
- Loading branch information
Showing
67 changed files
with
1,988 additions
and
151 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# This file was auto-generated by Fern from our API Definition. | ||
|
||
from .resources import MyEnum, svc | ||
from .security import ApiAuth | ||
|
||
__all__ = ["ApiAuth", "MyEnum", "svc"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# This file was auto-generated by Fern from our API Definition. | ||
|
||
from .datetime_utils import serialize_datetime | ||
from .exceptions import ( | ||
FernHTTPException, | ||
UnauthorizedException, | ||
default_exception_handler, | ||
fern_http_exception_handler, | ||
http_exception_handler, | ||
) | ||
from .route_args import route_args | ||
from .security import BearerToken | ||
|
||
__all__ = [ | ||
"BearerToken", | ||
"FernHTTPException", | ||
"UnauthorizedException", | ||
"default_exception_handler", | ||
"fern_http_exception_handler", | ||
"http_exception_handler", | ||
"route_args", | ||
"serialize_datetime", | ||
] |
11 changes: 11 additions & 0 deletions
11
seed/fastapi/enum-query-params/core/abstract_fern_service.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# This file was auto-generated by Fern from our API Definition. | ||
|
||
import abc | ||
|
||
import fastapi | ||
|
||
|
||
class AbstractFernService(abc.ABC): | ||
@classmethod | ||
def _init_fern(cls, router: fastapi.APIRouter) -> None: | ||
... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# This file was auto-generated by Fern from our API Definition. | ||
|
||
import datetime as dt | ||
|
||
|
||
def serialize_datetime(v: dt.datetime) -> str: | ||
""" | ||
Serialize a datetime including timezone info. | ||
Uses the timezone info provided if present, otherwise uses the current runtime's timezone info. | ||
UTC datetimes end in "Z" while all other timezones are represented as offset from UTC, e.g. +05:00. | ||
""" | ||
|
||
def _serialize_zoned_datetime(v: dt.datetime) -> str: | ||
if v.tzinfo is not None and v.tzinfo.tzname(None) == dt.timezone.utc.tzname(None): | ||
# UTC is a special case where we use "Z" at the end instead of "+00:00" | ||
return v.isoformat().replace("+00:00", "Z") | ||
else: | ||
# Delegate to the typical +/- offset format | ||
return v.isoformat() | ||
|
||
if v.tzinfo is not None: | ||
return _serialize_zoned_datetime(v) | ||
else: | ||
local_tz = dt.datetime.now().astimezone().tzinfo | ||
localized_dt = v.replace(tzinfo=local_tz) | ||
return _serialize_zoned_datetime(localized_dt) |
13 changes: 13 additions & 0 deletions
13
seed/fastapi/enum-query-params/core/exceptions/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# This file was auto-generated by Fern from our API Definition. | ||
|
||
from .fern_http_exception import FernHTTPException | ||
from .handlers import default_exception_handler, fern_http_exception_handler, http_exception_handler | ||
from .unauthorized import UnauthorizedException | ||
|
||
__all__ = [ | ||
"FernHTTPException", | ||
"UnauthorizedException", | ||
"default_exception_handler", | ||
"fern_http_exception_handler", | ||
"http_exception_handler", | ||
] |
20 changes: 20 additions & 0 deletions
20
seed/fastapi/enum-query-params/core/exceptions/fern_http_exception.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# This file was auto-generated by Fern from our API Definition. | ||
|
||
import abc | ||
import typing | ||
|
||
import fastapi | ||
|
||
|
||
class FernHTTPException(abc.ABC, fastapi.HTTPException): | ||
def __init__( | ||
self, status_code: int, name: typing.Optional[str] = None, content: typing.Optional[typing.Any] = None | ||
): | ||
super().__init__(status_code=status_code) | ||
self.name = name | ||
self.status_code = status_code | ||
self.content = content | ||
|
||
def to_json_response(self) -> fastapi.responses.JSONResponse: | ||
content = fastapi.encoders.jsonable_encoder(self.content, exclude_none=True) | ||
return fastapi.responses.JSONResponse(content=content, status_code=self.status_code) |
32 changes: 32 additions & 0 deletions
32
seed/fastapi/enum-query-params/core/exceptions/handlers.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# This file was auto-generated by Fern from our API Definition. | ||
|
||
import logging | ||
|
||
import fastapi | ||
import starlette | ||
|
||
from .fern_http_exception import FernHTTPException | ||
|
||
|
||
def fern_http_exception_handler( | ||
request: fastapi.requests.Request, exc: FernHTTPException, skip_log: bool = False | ||
) -> fastapi.responses.JSONResponse: | ||
if not skip_log: | ||
logging.getLogger(__name__).error(f"{exc.__class__.__name__} in {request.url.path}", exc_info=exc) | ||
return exc.to_json_response() | ||
|
||
|
||
def http_exception_handler( | ||
request: fastapi.requests.Request, exc: starlette.exceptions.HTTPException, skip_log: bool = False | ||
) -> fastapi.responses.JSONResponse: | ||
if not skip_log: | ||
logging.getLogger(__name__).error(f"{exc.__class__.__name__} in {request.url.path}", exc_info=exc) | ||
return FernHTTPException(status_code=exc.status_code, content=exc.detail).to_json_response() | ||
|
||
|
||
def default_exception_handler( | ||
request: fastapi.requests.Request, exc: Exception, skip_log: bool = False | ||
) -> fastapi.responses.JSONResponse: | ||
if not skip_log: | ||
logging.getLogger(__name__).error(f"{exc.__class__.__name__} in {request.url.path}", exc_info=exc) | ||
return FernHTTPException(status_code=500, content="Internal Server Error").to_json_response() |
15 changes: 15 additions & 0 deletions
15
seed/fastapi/enum-query-params/core/exceptions/unauthorized.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# This file was auto-generated by Fern from our API Definition. | ||
|
||
import typing | ||
|
||
from .fern_http_exception import FernHTTPException | ||
|
||
|
||
class UnauthorizedException(FernHTTPException): | ||
""" | ||
This is the exception that is thrown by Fern when auth is not present on a | ||
request. | ||
""" | ||
|
||
def __init__(self, content: typing.Optional[str] = None) -> None: | ||
super().__init__(status_code=401, content=content) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# This file was auto-generated by Fern from our API Definition. | ||
|
||
import enum | ||
import inspect | ||
import typing | ||
|
||
import typing_extensions | ||
|
||
T = typing.TypeVar("T", bound=typing.Callable[..., typing.Any]) | ||
|
||
FERN_CONFIG_KEY = "__fern" | ||
|
||
|
||
class RouteArgs(typing_extensions.TypedDict): | ||
openapi_extra: typing.Optional[typing.Dict[str, typing.Any]] | ||
tags: typing.Optional[typing.List[typing.Union[str, enum.Enum]]] | ||
include_in_schema: bool | ||
|
||
|
||
DEFAULT_ROUTE_ARGS = RouteArgs(openapi_extra=None, tags=None, include_in_schema=True) | ||
|
||
|
||
def get_route_args(endpoint_function: typing.Callable[..., typing.Any], *, default_tag: str) -> RouteArgs: | ||
unwrapped = inspect.unwrap(endpoint_function, stop=(lambda f: hasattr(f, FERN_CONFIG_KEY))) | ||
route_args = typing.cast(RouteArgs, getattr(unwrapped, FERN_CONFIG_KEY, DEFAULT_ROUTE_ARGS)) | ||
if route_args["tags"] is None: | ||
return RouteArgs( | ||
openapi_extra=route_args["openapi_extra"], | ||
tags=[default_tag], | ||
include_in_schema=route_args["include_in_schema"], | ||
) | ||
return route_args | ||
|
||
|
||
def route_args( | ||
openapi_extra: typing.Optional[typing.Dict[str, typing.Any]] = None, | ||
tags: typing.Optional[typing.List[typing.Union[str, enum.Enum]]] = None, | ||
include_in_schema: bool = True, | ||
) -> typing.Callable[[T], T]: | ||
""" | ||
this decorator allows you to forward certain args to the FastAPI route decorator. | ||
usage: | ||
@route_args(openapi_extra=...) | ||
def your_endpoint_method(... | ||
currently supported args: | ||
- openapi_extra | ||
- tags | ||
if there's another FastAPI route arg you need to pass through, please | ||
contact the Fern team! | ||
""" | ||
|
||
def decorator(endpoint_function: T) -> T: | ||
setattr( | ||
endpoint_function, | ||
FERN_CONFIG_KEY, | ||
RouteArgs(openapi_extra=openapi_extra, tags=tags, include_in_schema=include_in_schema), | ||
) | ||
return endpoint_function | ||
|
||
return decorator |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# This file was auto-generated by Fern from our API Definition. | ||
|
||
from .bearer import BearerToken | ||
|
||
__all__ = ["BearerToken"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# This file was auto-generated by Fern from our API Definition. | ||
|
||
import fastapi | ||
|
||
from ..exceptions import UnauthorizedException | ||
|
||
|
||
class BearerToken: | ||
def __init__(self, token: str): | ||
self.token = token | ||
|
||
|
||
def HTTPBearer(request: fastapi.requests.Request) -> BearerToken: | ||
authorization_header_value = request.headers.get("Authorization") | ||
if not authorization_header_value: | ||
raise UnauthorizedException("Missing Authorization header") | ||
scheme, _, token = authorization_header_value.partition(" ") | ||
if scheme.lower() != "bearer": | ||
raise UnauthorizedException("Authorization header scheme is not bearer") | ||
if not token: | ||
raise UnauthorizedException("Authorization header is missing a token") | ||
return BearerToken(token) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# This file was auto-generated by Fern from our API Definition. | ||
|
||
import glob | ||
import importlib | ||
import os | ||
import types | ||
import typing | ||
|
||
import fastapi | ||
import starlette | ||
from fastapi import params | ||
|
||
from .core.abstract_fern_service import AbstractFernService | ||
from .core.exceptions import default_exception_handler, fern_http_exception_handler, http_exception_handler | ||
from .core.exceptions.fern_http_exception import FernHTTPException | ||
from .resources.svc.service.service import AbstractSvcService | ||
|
||
|
||
def register( | ||
_app: fastapi.FastAPI, | ||
*, | ||
svc: AbstractSvcService, | ||
dependencies: typing.Optional[typing.Sequence[params.Depends]] = None | ||
) -> None: | ||
_app.include_router(__register_service(svc), dependencies=dependencies) | ||
|
||
_app.add_exception_handler(FernHTTPException, fern_http_exception_handler) | ||
_app.add_exception_handler(starlette.exceptions.HTTPException, http_exception_handler) | ||
_app.add_exception_handler(Exception, default_exception_handler) | ||
|
||
|
||
def __register_service(service: AbstractFernService) -> fastapi.APIRouter: | ||
router = fastapi.APIRouter() | ||
type(service)._init_fern(router) | ||
return router | ||
|
||
|
||
def register_validators(module: types.ModuleType) -> None: | ||
validators_directory: str = os.path.dirname(module.__file__) # type: ignore | ||
for path in glob.glob(os.path.join(validators_directory, "**/*.py"), recursive=True): | ||
if os.path.isfile(path): | ||
relative_path = os.path.relpath(path, start=validators_directory) | ||
module_path = ".".join([module.__name__] + relative_path[:-3].split("/")) | ||
importlib.import_module(module_path) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# This file was auto-generated by Fern from our API Definition. | ||
|
||
from . import svc | ||
from .svc import MyEnum | ||
|
||
__all__ = ["MyEnum", "svc"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# This file was auto-generated by Fern from our API Definition. | ||
|
||
from .types import MyEnum | ||
|
||
__all__ = ["MyEnum"] |
5 changes: 5 additions & 0 deletions
5
seed/fastapi/enum-query-params/resources/svc/service/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# This file was auto-generated by Fern from our API Definition. | ||
|
||
from .service import AbstractSvcService | ||
|
||
__all__ = ["AbstractSvcService"] |
73 changes: 73 additions & 0 deletions
73
seed/fastapi/enum-query-params/resources/svc/service/service.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# This file was auto-generated by Fern from our API Definition. | ||
|
||
import abc | ||
import functools | ||
import inspect | ||
import logging | ||
import typing | ||
|
||
import fastapi | ||
|
||
from ....core.abstract_fern_service import AbstractFernService | ||
from ....core.exceptions.fern_http_exception import FernHTTPException | ||
from ....core.route_args import get_route_args | ||
from ..types.my_enum import MyEnum | ||
|
||
|
||
class AbstractSvcService(AbstractFernService): | ||
""" | ||
AbstractSvcService is an abstract class containing the methods that you should implement. | ||
Each method is associated with an API route, which will be registered | ||
with FastAPI when you register your implementation using Fern's register() | ||
function. | ||
""" | ||
|
||
@abc.abstractmethod | ||
def test(self, *, some_enum: typing.Optional[typing.List[MyEnum]] = None) -> str: | ||
... | ||
|
||
""" | ||
Below are internal methods used by Fern to register your implementation. | ||
You can ignore them. | ||
""" | ||
|
||
@classmethod | ||
def _init_fern(cls, router: fastapi.APIRouter) -> None: | ||
cls.__init_test(router=router) | ||
|
||
@classmethod | ||
def __init_test(cls, router: fastapi.APIRouter) -> None: | ||
endpoint_function = inspect.signature(cls.test) | ||
new_parameters: typing.List[inspect.Parameter] = [] | ||
for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): | ||
if index == 0: | ||
new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) | ||
elif parameter_name == "some_enum": | ||
new_parameters.append(parameter.replace(default=fastapi.Query(default=None, alias="some-enum"))) | ||
else: | ||
new_parameters.append(parameter) | ||
setattr(cls.test, "__signature__", endpoint_function.replace(parameters=new_parameters)) | ||
|
||
@functools.wraps(cls.test) | ||
def wrapper(*args: typing.Any, **kwargs: typing.Any) -> str: | ||
try: | ||
return cls.test(*args, **kwargs) | ||
except FernHTTPException as e: | ||
logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( | ||
f"Endpoint 'test' unexpectedly threw {e.__class__.__name__}. " | ||
+ f"If this was intentional, please add {e.__class__.__name__} to " | ||
+ "the endpoint's errors list in your Fern Definition." | ||
) | ||
raise e | ||
|
||
# this is necessary for FastAPI to find forward-ref'ed type hints. | ||
# https://github.com/tiangolo/fastapi/pull/5077 | ||
wrapper.__globals__.update(cls.test.__globals__) | ||
|
||
router.get( | ||
path="//test", | ||
response_model=str, | ||
description=AbstractSvcService.test.__doc__, | ||
**get_route_args(cls.test, default_tag="svc"), | ||
)(wrapper) |
Oops, something went wrong.